aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/dir.c67
-rw-r--r--fs/sysfs/file.c2
-rw-r--r--fs/sysfs/inode.c33
-rw-r--r--fs/sysfs/symlink.c8
-rw-r--r--fs/sysfs/sysfs.h7
-rw-r--r--include/linux/sysfs.h1
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
97struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, int type) 98struct 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
122void sysfs_attach_dirent(struct sysfs_dirent *sd, 135void 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)
427int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, 437int 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 */
197const 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
225static inline void orphan_all_buffers(struct inode *node) 194static 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
22extern void release_sysfs_dirent(struct sysfs_dirent * sd); 23extern void release_sysfs_dirent(struct sysfs_dirent * sd);
23extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); 24extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
24extern struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, 25extern struct sysfs_dirent *sysfs_new_dirent(const char *name, void *element,
25 int type); 26 umode_t mode, int type);
26extern void sysfs_attach_dirent(struct sysfs_dirent *sd, 27extern 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
34extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); 35extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
35extern void sysfs_remove_subdir(struct dentry *); 36extern void sysfs_remove_subdir(struct dentry *);
36 37
37extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
38extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); 38extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
39extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); 39extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
40 40
@@ -48,7 +48,6 @@ extern const struct inode_operations sysfs_dir_inode_operations;
48extern const struct inode_operations sysfs_symlink_inode_operations; 48extern const struct inode_operations sysfs_symlink_inode_operations;
49 49
50struct sysfs_symlink { 50struct 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