diff options
author | Tejun Heo <htejun@gmail.com> | 2007-06-13 14:45:15 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:09:04 -0400 |
commit | 0c096b507f15397da890051ee73de4266d3941fb (patch) | |
tree | c6b7d204a493157b3926bdb46500313eee9f9690 /fs/sysfs/dir.c | |
parent | 13b3086d2ea483cbcae5a4236446cecc082a72cf (diff) |
sysfs: add sysfs_dirent->s_name
Add s_name to sysfs_dirent. This is to further reduce dependency to
the associated dentry. Name is copied for directories and symlinks
but not for attributes.
Where possible, name dereferences are converted to use sd->s_name.
sysfs_symlink->link_name and sysfs_get_name() are unused now and
removed.
This change allows symlink to be implemented using sysfs_dirent tree
proper, which is the last remaining dentry-dependent sysfs walk.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 67 |
1 files changed, 44 insertions, 23 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 */ |