diff options
-rw-r--r-- | fs/sysfs/dir.c | 67 | ||||
-rw-r--r-- | fs/sysfs/file.c | 2 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 33 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 8 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 7 | ||||
-rw-r--r-- | include/linux/sysfs.h | 1 |
6 files changed, 51 insertions, 67 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 5d50e1ddfbd1..6e8d6f54f082 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -54,10 +54,11 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) | |||
54 | 54 | ||
55 | if (sd->s_type & SYSFS_KOBJ_LINK) { | 55 | if (sd->s_type & SYSFS_KOBJ_LINK) { |
56 | struct sysfs_symlink * sl = sd->s_element; | 56 | struct sysfs_symlink * sl = sd->s_element; |
57 | kfree(sl->link_name); | ||
58 | kobject_put(sl->target_kobj); | 57 | kobject_put(sl->target_kobj); |
59 | kfree(sl); | 58 | kfree(sl); |
60 | } | 59 | } |
60 | if (sd->s_type & SYSFS_COPY_NAME) | ||
61 | kfree(sd->s_name); | ||
61 | kfree(sd->s_iattr); | 62 | kfree(sd->s_iattr); |
62 | sysfs_free_ino(sd->s_ino); | 63 | sysfs_free_ino(sd->s_ino); |
63 | kmem_cache_free(sysfs_dir_cachep, sd); | 64 | kmem_cache_free(sysfs_dir_cachep, sd); |
@@ -94,29 +95,41 @@ static struct dentry_operations sysfs_dentry_ops = { | |||
94 | .d_iput = sysfs_d_iput, | 95 | .d_iput = sysfs_d_iput, |
95 | }; | 96 | }; |
96 | 97 | ||
97 | struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, int type) | 98 | struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, |
99 | umode_t mode, int type) | ||
98 | { | 100 | { |
99 | struct sysfs_dirent * sd; | 101 | char *dup_name = NULL; |
102 | struct sysfs_dirent *sd = NULL; | ||
103 | |||
104 | if (type & SYSFS_COPY_NAME) { | ||
105 | name = dup_name = kstrdup(name, GFP_KERNEL); | ||
106 | if (!name) | ||
107 | goto err_out; | ||
108 | } | ||
100 | 109 | ||
101 | sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); | 110 | sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); |
102 | if (!sd) | 111 | if (!sd) |
103 | return NULL; | 112 | goto err_out; |
104 | 113 | ||
105 | if (sysfs_alloc_ino(&sd->s_ino)) { | 114 | if (sysfs_alloc_ino(&sd->s_ino)) |
106 | kmem_cache_free(sysfs_dir_cachep, sd); | 115 | goto err_out; |
107 | return NULL; | ||
108 | } | ||
109 | 116 | ||
110 | atomic_set(&sd->s_count, 1); | 117 | atomic_set(&sd->s_count, 1); |
111 | atomic_set(&sd->s_event, 1); | 118 | atomic_set(&sd->s_event, 1); |
112 | INIT_LIST_HEAD(&sd->s_children); | 119 | INIT_LIST_HEAD(&sd->s_children); |
113 | INIT_LIST_HEAD(&sd->s_sibling); | 120 | INIT_LIST_HEAD(&sd->s_sibling); |
114 | 121 | ||
122 | sd->s_name = name; | ||
115 | sd->s_element = element; | 123 | sd->s_element = element; |
116 | sd->s_mode = mode; | 124 | sd->s_mode = mode; |
117 | sd->s_type = type; | 125 | sd->s_type = type; |
118 | 126 | ||
119 | return sd; | 127 | return sd; |
128 | |||
129 | err_out: | ||
130 | kfree(dup_name); | ||
131 | kmem_cache_free(sysfs_dir_cachep, sd); | ||
132 | return NULL; | ||
120 | } | 133 | } |
121 | 134 | ||
122 | void sysfs_attach_dirent(struct sysfs_dirent *sd, | 135 | void sysfs_attach_dirent(struct sysfs_dirent *sd, |
@@ -148,8 +161,7 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, | |||
148 | 161 | ||
149 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 162 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { |
150 | if (sd->s_element) { | 163 | if (sd->s_element) { |
151 | const unsigned char *existing = sysfs_get_name(sd); | 164 | if (strcmp(sd->s_name, new)) |
152 | if (strcmp(existing, new)) | ||
153 | continue; | 165 | continue; |
154 | else | 166 | else |
155 | return -EEXIST; | 167 | return -EEXIST; |
@@ -203,7 +215,7 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, | |||
203 | goto out_dput; | 215 | goto out_dput; |
204 | 216 | ||
205 | error = -ENOMEM; | 217 | error = -ENOMEM; |
206 | sd = sysfs_new_dirent(kobj, mode, SYSFS_DIR); | 218 | sd = sysfs_new_dirent(name, kobj, mode, SYSFS_DIR); |
207 | if (!sd) | 219 | if (!sd) |
208 | goto out_drop; | 220 | goto out_drop; |
209 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); | 221 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); |
@@ -334,9 +346,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
334 | 346 | ||
335 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 347 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { |
336 | if (sd->s_type & SYSFS_NOT_PINNED) { | 348 | if (sd->s_type & SYSFS_NOT_PINNED) { |
337 | const unsigned char * name = sysfs_get_name(sd); | 349 | if (strcmp(sd->s_name, dentry->d_name.name)) |
338 | |||
339 | if (strcmp(name, dentry->d_name.name)) | ||
340 | continue; | 350 | continue; |
341 | 351 | ||
342 | if (sd->s_type & SYSFS_KOBJ_LINK) | 352 | if (sd->s_type & SYSFS_KOBJ_LINK) |
@@ -427,9 +437,11 @@ void sysfs_remove_dir(struct kobject * kobj) | |||
427 | int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, | 437 | int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, |
428 | const char *new_name) | 438 | const char *new_name) |
429 | { | 439 | { |
440 | struct sysfs_dirent *sd = kobj->dentry->d_fsdata; | ||
441 | struct sysfs_dirent *parent_sd = new_parent->d_fsdata; | ||
442 | struct dentry *new_dentry; | ||
443 | char *dup_name; | ||
430 | int error; | 444 | int error; |
431 | struct dentry * new_dentry; | ||
432 | struct sysfs_dirent *sd, *parent_sd; | ||
433 | 445 | ||
434 | if (!new_parent) | 446 | if (!new_parent) |
435 | return -EFAULT; | 447 | return -EFAULT; |
@@ -457,22 +469,31 @@ int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, | |||
457 | if (new_dentry->d_inode) | 469 | if (new_dentry->d_inode) |
458 | goto out_dput; | 470 | goto out_dput; |
459 | 471 | ||
472 | /* rename kobject and sysfs_dirent */ | ||
473 | error = -ENOMEM; | ||
474 | new_name = dup_name = kstrdup(new_name, GFP_KERNEL); | ||
475 | if (!new_name) | ||
476 | goto out_drop; | ||
477 | |||
460 | error = kobject_set_name(kobj, "%s", new_name); | 478 | error = kobject_set_name(kobj, "%s", new_name); |
461 | if (error) | 479 | if (error) |
462 | goto out_drop; | 480 | goto out_free; |
463 | 481 | ||
482 | kfree(sd->s_name); | ||
483 | sd->s_name = new_name; | ||
484 | |||
485 | /* move under the new parent */ | ||
464 | d_add(new_dentry, NULL); | 486 | d_add(new_dentry, NULL); |
465 | d_move(kobj->dentry, new_dentry); | 487 | d_move(kobj->dentry, new_dentry); |
466 | 488 | ||
467 | sd = kobj->dentry->d_fsdata; | ||
468 | parent_sd = new_parent->d_fsdata; | ||
469 | |||
470 | list_del_init(&sd->s_sibling); | 489 | list_del_init(&sd->s_sibling); |
471 | list_add(&sd->s_sibling, &parent_sd->s_children); | 490 | list_add(&sd->s_sibling, &parent_sd->s_children); |
472 | 491 | ||
473 | error = 0; | 492 | error = 0; |
474 | goto out_unlock; | 493 | goto out_unlock; |
475 | 494 | ||
495 | out_free: | ||
496 | kfree(dup_name); | ||
476 | out_drop: | 497 | out_drop: |
477 | d_drop(new_dentry); | 498 | d_drop(new_dentry); |
478 | out_dput: | 499 | out_dput: |
@@ -535,7 +556,7 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) | |||
535 | struct sysfs_dirent * sd; | 556 | struct sysfs_dirent * sd; |
536 | 557 | ||
537 | mutex_lock(&dentry->d_inode->i_mutex); | 558 | mutex_lock(&dentry->d_inode->i_mutex); |
538 | sd = sysfs_new_dirent(NULL, 0, 0); | 559 | sd = sysfs_new_dirent("_DIR_", NULL, 0, 0); |
539 | if (sd) | 560 | if (sd) |
540 | sysfs_attach_dirent(sd, parent_sd, NULL); | 561 | sysfs_attach_dirent(sd, parent_sd, NULL); |
541 | mutex_unlock(&dentry->d_inode->i_mutex); | 562 | mutex_unlock(&dentry->d_inode->i_mutex); |
@@ -605,7 +626,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
605 | if (!next->s_element) | 626 | if (!next->s_element) |
606 | continue; | 627 | continue; |
607 | 628 | ||
608 | name = sysfs_get_name(next); | 629 | name = next->s_name; |
609 | len = strlen(name); | 630 | len = strlen(name); |
610 | ino = next->s_ino; | 631 | ino = next->s_ino; |
611 | 632 | ||
@@ -717,7 +738,7 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) | |||
717 | if (!shadow) | 738 | if (!shadow) |
718 | goto nomem; | 739 | goto nomem; |
719 | 740 | ||
720 | sd = sysfs_new_dirent(kobj, inode->i_mode, SYSFS_DIR); | 741 | sd = sysfs_new_dirent("_SHADOW_", kobj, inode->i_mode, SYSFS_DIR); |
721 | if (!sd) | 742 | if (!sd) |
722 | goto nomem; | 743 | goto nomem; |
723 | /* point to parent_sd but don't attach to it */ | 744 | /* point to parent_sd but don't attach to it */ |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index fd4b6dc03d2d..8240b1687dd0 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -454,7 +454,7 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) | |||
454 | goto out_unlock; | 454 | goto out_unlock; |
455 | } | 455 | } |
456 | 456 | ||
457 | sd = sysfs_new_dirent((void *)attr, mode, type); | 457 | sd = sysfs_new_dirent(attr->name, (void *)attr, mode, type); |
458 | if (!sd) { | 458 | if (!sd) { |
459 | error = -ENOMEM; | 459 | error = -ENOMEM; |
460 | goto out_unlock; | 460 | goto out_unlock; |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 5266eec15f6e..5c605b0003a8 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -191,37 +191,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) | |||
191 | return error; | 191 | return error; |
192 | } | 192 | } |
193 | 193 | ||
194 | /* | ||
195 | * Get the name for corresponding element represented by the given sysfs_dirent | ||
196 | */ | ||
197 | const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) | ||
198 | { | ||
199 | struct attribute * attr; | ||
200 | struct bin_attribute * bin_attr; | ||
201 | struct sysfs_symlink * sl; | ||
202 | |||
203 | BUG_ON(!sd || !sd->s_element); | ||
204 | |||
205 | switch (sd->s_type) { | ||
206 | case SYSFS_DIR: | ||
207 | /* Always have a dentry so use that */ | ||
208 | return sd->s_dentry->d_name.name; | ||
209 | |||
210 | case SYSFS_KOBJ_ATTR: | ||
211 | attr = sd->s_element; | ||
212 | return attr->name; | ||
213 | |||
214 | case SYSFS_KOBJ_BIN_ATTR: | ||
215 | bin_attr = sd->s_element; | ||
216 | return bin_attr->attr.name; | ||
217 | |||
218 | case SYSFS_KOBJ_LINK: | ||
219 | sl = sd->s_element; | ||
220 | return sl->link_name; | ||
221 | } | ||
222 | return NULL; | ||
223 | } | ||
224 | |||
225 | static inline void orphan_all_buffers(struct inode *node) | 194 | static inline void orphan_all_buffers(struct inode *node) |
226 | { | 195 | { |
227 | struct sysfs_buffer_collection *set; | 196 | struct sysfs_buffer_collection *set; |
@@ -305,7 +274,7 @@ int sysfs_hash_and_remove(struct dentry * dir, const char * name) | |||
305 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 274 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { |
306 | if (!sd->s_element) | 275 | if (!sd->s_element) |
307 | continue; | 276 | continue; |
308 | if (!strcmp(sysfs_get_name(sd), name)) { | 277 | if (!strcmp(sd->s_name, name)) { |
309 | list_del_init(&sd->s_sibling); | 278 | list_del_init(&sd->s_sibling); |
310 | sysfs_drop_dentry(sd, dir); | 279 | sysfs_drop_dentry(sd, dir); |
311 | sysfs_put(sd); | 280 | sysfs_put(sd); |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index d96bb9cbc9d4..c72820450e7c 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -57,14 +57,9 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj | |||
57 | if (!sl) | 57 | if (!sl) |
58 | goto err_out; | 58 | goto err_out; |
59 | 59 | ||
60 | sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL); | ||
61 | if (!sl->link_name) | ||
62 | goto err_out; | ||
63 | |||
64 | strcpy(sl->link_name, name); | ||
65 | sl->target_kobj = kobject_get(target); | 60 | sl->target_kobj = kobject_get(target); |
66 | 61 | ||
67 | sd = sysfs_new_dirent(sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); | 62 | sd = sysfs_new_dirent(name, sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); |
68 | if (!sd) | 63 | if (!sd) |
69 | goto err_out; | 64 | goto err_out; |
70 | sysfs_attach_dirent(sd, parent_sd, NULL); | 65 | sysfs_attach_dirent(sd, parent_sd, NULL); |
@@ -74,7 +69,6 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj | |||
74 | err_out: | 69 | err_out: |
75 | if (sl) { | 70 | if (sl) { |
76 | kobject_put(sl->target_kobj); | 71 | kobject_put(sl->target_kobj); |
77 | kfree(sl->link_name); | ||
78 | kfree(sl); | 72 | kfree(sl); |
79 | } | 73 | } |
80 | return error; | 74 | return error; |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index ce05d6fd7522..d34b008537d5 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -3,6 +3,7 @@ struct sysfs_dirent { | |||
3 | struct sysfs_dirent * s_parent; | 3 | struct sysfs_dirent * s_parent; |
4 | struct list_head s_sibling; | 4 | struct list_head s_sibling; |
5 | struct list_head s_children; | 5 | struct list_head s_children; |
6 | const char * s_name; | ||
6 | void * s_element; | 7 | void * s_element; |
7 | int s_type; | 8 | int s_type; |
8 | umode_t s_mode; | 9 | umode_t s_mode; |
@@ -21,8 +22,8 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | |||
21 | 22 | ||
22 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); | 23 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); |
23 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); | 24 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); |
24 | extern struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, | 25 | extern struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element, |
25 | int type); | 26 | umode_t mode, int type); |
26 | extern void sysfs_attach_dirent(struct sysfs_dirent *sd, | 27 | extern void sysfs_attach_dirent(struct sysfs_dirent *sd, |
27 | struct sysfs_dirent *parent_sd, | 28 | struct sysfs_dirent *parent_sd, |
28 | struct dentry *dentry); | 29 | struct dentry *dentry); |
@@ -34,7 +35,6 @@ extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * na | |||
34 | extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); | 35 | extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); |
35 | extern void sysfs_remove_subdir(struct dentry *); | 36 | extern void sysfs_remove_subdir(struct dentry *); |
36 | 37 | ||
37 | extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); | ||
38 | extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); | 38 | extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); |
39 | extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | 39 | extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); |
40 | 40 | ||
@@ -48,7 +48,6 @@ extern const struct inode_operations sysfs_dir_inode_operations; | |||
48 | extern const struct inode_operations sysfs_symlink_inode_operations; | 48 | extern const struct inode_operations sysfs_symlink_inode_operations; |
49 | 49 | ||
50 | struct sysfs_symlink { | 50 | struct sysfs_symlink { |
51 | char * link_name; | ||
52 | struct kobject * target_kobj; | 51 | struct kobject * target_kobj; |
53 | }; | 52 | }; |
54 | 53 | ||
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 7d5d1ec95c2e..2f86b080b39d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -76,6 +76,7 @@ struct sysfs_ops { | |||
76 | #define SYSFS_KOBJ_BIN_ATTR 0x0008 | 76 | #define SYSFS_KOBJ_BIN_ATTR 0x0008 |
77 | #define SYSFS_KOBJ_LINK 0x0020 | 77 | #define SYSFS_KOBJ_LINK 0x0020 |
78 | #define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK) | 78 | #define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK) |
79 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) | ||
79 | 80 | ||
80 | #ifdef CONFIG_SYSFS | 81 | #ifdef CONFIG_SYSFS |
81 | 82 | ||