aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-06-13 14:45:15 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-11 19:09:04 -0400
commit0c096b507f15397da890051ee73de4266d3941fb (patch)
treec6b7d204a493157b3926bdb46500313eee9f9690 /fs/sysfs/dir.c
parent13b3086d2ea483cbcae5a4236446cecc082a72cf (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.c67
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
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 */