diff options
author | Maneesh Soni <maneesh@in.ibm.com> | 2006-03-09 09:10:14 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-20 16:42:59 -0500 |
commit | c516865cfbac0d862d4888df91793ad1e74ffd58 (patch) | |
tree | 432024125976af3e6c87ae5b9e64b6f1cc291f70 | |
parent | 22f98c0cd7e003b896ee52ded945081307118745 (diff) |
[PATCH] sysfs: fix problem with duplicate sysfs directories and files
The following patch checks for existing sysfs_dirent before
preparing new one while creating sysfs directories and files.
Signed-off-by: Maneesh Soni <maneesh@in.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | fs/sysfs/dir.c | 32 | ||||
-rw-r--r-- | fs/sysfs/file.c | 6 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 5 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 1 |
4 files changed, 39 insertions, 5 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index cfd290d3d6b1..bea1f4c02b9b 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -50,6 +50,32 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd, | |||
50 | return sd; | 50 | return sd; |
51 | } | 51 | } |
52 | 52 | ||
53 | /** | ||
54 | * | ||
55 | * Return -EEXIST if there is already a sysfs element with the same name for | ||
56 | * the same parent. | ||
57 | * | ||
58 | * called with parent inode's i_mutex held | ||
59 | */ | ||
60 | int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, | ||
61 | const unsigned char *new) | ||
62 | { | ||
63 | struct sysfs_dirent * sd; | ||
64 | |||
65 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | ||
66 | if (sd->s_element) { | ||
67 | const unsigned char *existing = sysfs_get_name(sd); | ||
68 | if (strcmp(existing, new)) | ||
69 | continue; | ||
70 | else | ||
71 | return -EEXIST; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | |||
53 | int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, | 79 | int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, |
54 | void * element, umode_t mode, int type) | 80 | void * element, umode_t mode, int type) |
55 | { | 81 | { |
@@ -102,7 +128,11 @@ static int create_dir(struct kobject * k, struct dentry * p, | |||
102 | mutex_lock(&p->d_inode->i_mutex); | 128 | mutex_lock(&p->d_inode->i_mutex); |
103 | *d = lookup_one_len(n, p, strlen(n)); | 129 | *d = lookup_one_len(n, p, strlen(n)); |
104 | if (!IS_ERR(*d)) { | 130 | if (!IS_ERR(*d)) { |
105 | error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR); | 131 | if (sysfs_dirent_exist(p->d_fsdata, n)) |
132 | error = -EEXIST; | ||
133 | else | ||
134 | error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, | ||
135 | SYSFS_DIR); | ||
106 | if (!error) { | 136 | if (!error) { |
107 | error = sysfs_create(*d, mode, init_dir); | 137 | error = sysfs_create(*d, mode, init_dir); |
108 | if (!error) { | 138 | if (!error) { |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index e21f4022feb8..5e83e7246788 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -361,10 +361,12 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) | |||
361 | { | 361 | { |
362 | struct sysfs_dirent * parent_sd = dir->d_fsdata; | 362 | struct sysfs_dirent * parent_sd = dir->d_fsdata; |
363 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; | 363 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; |
364 | int error = 0; | 364 | int error = -EEXIST; |
365 | 365 | ||
366 | mutex_lock(&dir->d_inode->i_mutex); | 366 | mutex_lock(&dir->d_inode->i_mutex); |
367 | error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type); | 367 | if (!sysfs_dirent_exist(parent_sd, attr->name)) |
368 | error = sysfs_make_dirent(parent_sd, NULL, (void *)attr, | ||
369 | mode, type); | ||
368 | mutex_unlock(&dir->d_inode->i_mutex); | 370 | mutex_unlock(&dir->d_inode->i_mutex); |
369 | 371 | ||
370 | return error; | 372 | return error; |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index e38d6338a20d..fe23f47f6e43 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -82,12 +82,13 @@ exit1: | |||
82 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) | 82 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) |
83 | { | 83 | { |
84 | struct dentry * dentry = kobj->dentry; | 84 | struct dentry * dentry = kobj->dentry; |
85 | int error = 0; | 85 | int error = -EEXIST; |
86 | 86 | ||
87 | BUG_ON(!kobj || !kobj->dentry || !name); | 87 | BUG_ON(!kobj || !kobj->dentry || !name); |
88 | 88 | ||
89 | mutex_lock(&dentry->d_inode->i_mutex); | 89 | mutex_lock(&dentry->d_inode->i_mutex); |
90 | error = sysfs_add_link(dentry, name, target); | 90 | if (!sysfs_dirent_exist(dentry->d_fsdata, name)) |
91 | error = sysfs_add_link(dentry, name, target); | ||
91 | mutex_unlock(&dentry->d_inode->i_mutex); | 92 | mutex_unlock(&dentry->d_inode->i_mutex); |
92 | return error; | 93 | return error; |
93 | } | 94 | } |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3f8953e0e5d0..cf11d5b789d9 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -5,6 +5,7 @@ extern kmem_cache_t *sysfs_dir_cachep; | |||
5 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); | 5 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); |
6 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | 6 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); |
7 | 7 | ||
8 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); | ||
8 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, | 9 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, |
9 | umode_t, int); | 10 | umode_t, int); |
10 | 11 | ||