Commit c516865cfbac0d862d4888df91793ad1e74ffd58

Authored by Maneesh Soni
Committed by Greg Kroah-Hartman
1 parent 22f98c0cd7

[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>

Showing 4 changed files with 39 additions and 5 deletions Side-by-side Diff

... ... @@ -50,6 +50,32 @@
50 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 79 int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
54 80 void * element, umode_t mode, int type)
55 81 {
... ... @@ -102,7 +128,11 @@
102 128 mutex_lock(&p->d_inode->i_mutex);
103 129 *d = lookup_one_len(n, p, strlen(n));
104 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 136 if (!error) {
107 137 error = sysfs_create(*d, mode, init_dir);
108 138 if (!error) {
... ... @@ -361,10 +361,12 @@
361 361 {
362 362 struct sysfs_dirent * parent_sd = dir->d_fsdata;
363 363 umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
364   - int error = 0;
  364 + int error = -EEXIST;
365 365  
366 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 370 mutex_unlock(&dir->d_inode->i_mutex);
369 371  
370 372 return error;
... ... @@ -82,12 +82,13 @@
82 82 int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
83 83 {
84 84 struct dentry * dentry = kobj->dentry;
85   - int error = 0;
  85 + int error = -EEXIST;
86 86  
87 87 BUG_ON(!kobj || !kobj->dentry || !name);
88 88  
89 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 92 mutex_unlock(&dentry->d_inode->i_mutex);
92 93 return error;
93 94 }
... ... @@ -5,6 +5,7 @@
5 5 extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
6 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 9 extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
9 10 umode_t, int);
10 11