Merge tag 'clock' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[cascardo/linux.git] / fs / sysfs / dir.c
index 35a36d3..e6bb9b2 100644 (file)
@@ -132,6 +132,24 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
        rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
 }
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+/* Test for attributes that want to ignore lockdep for read-locking */
+static bool ignore_lockdep(struct sysfs_dirent *sd)
+{
+       return sysfs_type(sd) == SYSFS_KOBJ_ATTR &&
+                       sd->s_attr.attr->ignore_lockdep;
+}
+
+#else
+
+static inline bool ignore_lockdep(struct sysfs_dirent *sd)
+{
+       return true;
+}
+
+#endif
+
 /**
  *     sysfs_get_active - get an active reference to sysfs_dirent
  *     @sd: sysfs_dirent to get an active reference to
@@ -155,15 +173,17 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
                        return NULL;
 
                t = atomic_cmpxchg(&sd->s_active, v, v + 1);
-               if (likely(t == v)) {
-                       rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
-                       return sd;
-               }
+               if (likely(t == v))
+                       break;
                if (t < 0)
                        return NULL;
 
                cpu_relax();
        }
+
+       if (likely(!ignore_lockdep(sd)))
+               rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
+       return sd;
 }
 
 /**
@@ -180,7 +200,8 @@ void sysfs_put_active(struct sysfs_dirent *sd)
        if (unlikely(!sd))
                return;
 
-       rwsem_release(&sd->dep_map, 1, _RET_IP_);
+       if (likely(!ignore_lockdep(sd)))
+               rwsem_release(&sd->dep_map, 1, _RET_IP_);
        v = atomic_dec_return(&sd->s_active);
        if (likely(v != SD_DEACTIVATED_BIAS))
                return;
@@ -858,7 +879,6 @@ int sysfs_rename(struct sysfs_dirent *sd,
        struct sysfs_dirent *new_parent_sd, const void *new_ns,
        const char *new_name)
 {
-       const char *dup_name = NULL;
        int error;
 
        mutex_lock(&sysfs_mutex);
@@ -875,11 +895,11 @@ int sysfs_rename(struct sysfs_dirent *sd,
        /* rename sysfs_dirent */
        if (strcmp(sd->s_name, new_name) != 0) {
                error = -ENOMEM;
-               new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
+               new_name = kstrdup(new_name, GFP_KERNEL);
                if (!new_name)
                        goto out;
 
-               dup_name = sd->s_name;
+               kfree(sd->s_name);
                sd->s_name = new_name;
        }
 
@@ -895,7 +915,6 @@ int sysfs_rename(struct sysfs_dirent *sd,
        error = 0;
  out:
        mutex_unlock(&sysfs_mutex);
-       kfree(dup_name);
        return error;
 }