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 /fs/sysfs | |
| 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>
Diffstat (limited to 'fs/sysfs')
| -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 | ||
