aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManeesh Soni <maneesh@in.ibm.com>2006-03-09 09:10:14 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-20 16:42:59 -0500
commitc516865cfbac0d862d4888df91793ad1e74ffd58 (patch)
tree432024125976af3e6c87ae5b9e64b6f1cc291f70
parent22f98c0cd7e003b896ee52ded945081307118745 (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.c32
-rw-r--r--fs/sysfs/file.c6
-rw-r--r--fs/sysfs/symlink.c5
-rw-r--r--fs/sysfs/sysfs.h1
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 */
60int 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
53int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, 79int 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:
82int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) 82int 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;
5extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); 5extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); 6extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
7 7
8extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, 9extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
9 umode_t, int); 10 umode_t, int);
10 11