aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-08-20 08:36:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:51:08 -0400
commit932ea2e374dd1ca26676297a5eccd1cdab86f7cd (patch)
tree83bba794de7f1f9f9290192f4f95a8ed9c91dfb6 /fs/sysfs/dir.c
parent89bec09705d2033b8b765f3c3ac5093f80bd5bc4 (diff)
sysfs: Introduce sysfs_rename_mutex
Looking carefully at the rename code we have a subtle dependency that the structure of sysfs not change while we are performing a rename. If the parent directory of the object we are renaming changes while the rename is being performed nasty things could happen when we go to release our locks. So introduce a sysfs_rename_mutex to prevent this highly unlikely theoretical issue. In addition hold sysfs_rename_mutex over all calls to sysfs_get_dentry. Allowing sysfs_get_dentry to be simplified in the future. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Tejun Heo <htejun@gmail.com> Cc: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 1af963e66e3c..9fe83d23dc2c 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -15,6 +15,7 @@
15#include "sysfs.h" 15#include "sysfs.h"
16 16
17DEFINE_MUTEX(sysfs_mutex); 17DEFINE_MUTEX(sysfs_mutex);
18DEFINE_MUTEX(sysfs_rename_mutex);
18spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; 19spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
19 20
20static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; 21static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
@@ -82,7 +83,7 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
82 * down from there looking up dentry for each step. 83 * down from there looking up dentry for each step.
83 * 84 *
84 * LOCKING: 85 * LOCKING:
85 * Kernel thread context (may sleep) 86 * mutex_lock(sysfs_rename_mutex)
86 * 87 *
87 * RETURNS: 88 * RETURNS:
88 * Pointer to found dentry on success, ERR_PTR() value on error. 89 * Pointer to found dentry on success, ERR_PTR() value on error.
@@ -858,6 +859,8 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
858 const char *dup_name = NULL; 859 const char *dup_name = NULL;
859 int error; 860 int error;
860 861
862 mutex_lock(&sysfs_rename_mutex);
863
861 /* get the original dentry */ 864 /* get the original dentry */
862 sd = kobj->sd; 865 sd = kobj->sd;
863 old_dentry = sysfs_get_dentry(sd); 866 old_dentry = sysfs_get_dentry(sd);
@@ -915,6 +918,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
915 kfree(dup_name); 918 kfree(dup_name);
916 dput(old_dentry); 919 dput(old_dentry);
917 dput(new_dentry); 920 dput(new_dentry);
921 mutex_unlock(&sysfs_rename_mutex);
918 return error; 922 return error;
919} 923}
920 924
@@ -926,6 +930,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
926 struct dentry *old_dentry = NULL, *new_dentry = NULL; 930 struct dentry *old_dentry = NULL, *new_dentry = NULL;
927 int error; 931 int error;
928 932
933 mutex_lock(&sysfs_rename_mutex);
929 BUG_ON(!sd->s_parent); 934 BUG_ON(!sd->s_parent);
930 new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; 935 new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
931 936
@@ -982,6 +987,7 @@ again:
982 dput(new_parent); 987 dput(new_parent);
983 dput(old_dentry); 988 dput(old_dentry);
984 dput(new_dentry); 989 dput(new_dentry);
990 mutex_unlock(&sysfs_rename_mutex);
985 return error; 991 return error;
986} 992}
987 993