From 19c38de88a80913351fcacefdb461cc0b585fa87 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Sep 2007 15:06:57 -0700 Subject: kobjects: fix up improper use of the kobject name field A number of different drivers incorrect access the kobject name field directly. This is not correct as the name might not be in the array. Use the proper accessor function instead. --- fs/sysfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 83e76b3813c9..ea33b660ae8a 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -1013,7 +1013,7 @@ again: goto again; } - new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name)); + new_dentry = lookup_one_len(kobject_name(kobj), new_parent, strlen(kobject_name(kobj))); if (IS_ERR(new_dentry)) { error = PTR_ERR(new_dentry); goto out_unlock; -- cgit v1.2.2 From 869512ab5ab93e5e82ad7d4aaf4ed098d23bfc3f Mon Sep 17 00:00:00 2001 From: Dave Young Date: Thu, 26 Jul 2007 14:53:53 +0000 Subject: sysfs: cleanup semaphore.h Cleanup semaphore.h Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index ea33b660ae8a..86d75e08de60 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "sysfs.h" DEFINE_MUTEX(sysfs_mutex); -- cgit v1.2.2 From 90bc61359de0148f8627073d68a22edc7ed9893d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 31 Jul 2007 19:15:08 +0900 Subject: sysfs: Remove first pass at shadow directory support While shadow directories appear to be a good idea, the current scheme of controlling their creation and destruction outside of sysfs appears to be a locking and maintenance nightmare in the face of sysfs directories dynamically coming and going. Which can now occur for directories containing network devices when CONFIG_SYSFS_DEPRECATED is not set. This patch removes everything from the initial shadow directory support that allowed the shadow directory creation to be controlled at a higher level. So except for a few bits of sysfs_rename_dir everything from commit b592fcfe7f06c15ec11774b5be7ce0de3aa86e73 is now gone. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 167 ++++++++------------------------------------------------- 1 file changed, 22 insertions(+), 145 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 86d75e08de60..837073dbadf4 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -569,9 +569,6 @@ static void sysfs_drop_dentry(struct sysfs_dirent *sd) spin_unlock(&dcache_lock); spin_unlock(&sysfs_assoc_lock); - /* dentries for shadowed inodes are pinned, unpin */ - if (dentry && sysfs_is_shadowed_inode(dentry->d_inode)) - dput(dentry); dput(dentry); /* adjust nlink and update timestamp */ @@ -723,19 +720,15 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, /** * sysfs_create_dir - create a directory for an object. * @kobj: object we're creating directory for. - * @shadow_parent: parent object. */ -int sysfs_create_dir(struct kobject *kobj, - struct sysfs_dirent *shadow_parent_sd) +int sysfs_create_dir(struct kobject * kobj) { struct sysfs_dirent *parent_sd, *sd; int error = 0; BUG_ON(!kobj); - if (shadow_parent_sd) - parent_sd = shadow_parent_sd; - else if (kobj->parent) + if (kobj->parent) parent_sd = kobj->parent->sd; else if (sysfs_mount && sysfs_mount->mnt_sb) parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; @@ -890,45 +883,44 @@ void sysfs_remove_dir(struct kobject * kobj) __sysfs_remove_dir(sd); } -int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, - const char *new_name) +int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { - struct sysfs_dirent *sd = kobj->sd; - struct dentry *new_parent = NULL; + struct sysfs_dirent *sd; + struct dentry *parent = NULL; struct dentry *old_dentry = NULL, *new_dentry = NULL; + struct sysfs_dirent *parent_sd; const char *dup_name = NULL; int error; + if (!kobj->parent) + return -EINVAL; + /* get dentries */ + sd = kobj->sd; old_dentry = sysfs_get_dentry(sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); goto out_dput; } - new_parent = sysfs_get_dentry(new_parent_sd); - if (IS_ERR(new_parent)) { - error = PTR_ERR(new_parent); + parent_sd = kobj->parent->sd; + parent = sysfs_get_dentry(parent_sd); + if (IS_ERR(parent)) { + error = PTR_ERR(parent); goto out_dput; } - /* lock new_parent and get dentry for new name */ - mutex_lock(&new_parent->d_inode->i_mutex); + /* lock parent and get dentry for new name */ + mutex_lock(&parent->d_inode->i_mutex); - new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); + new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); if (IS_ERR(new_dentry)) { error = PTR_ERR(new_dentry); goto out_unlock; } - /* By allowing two different directories with the same - * d_parent we allow this routine to move between different - * shadows of the same directory - */ error = -EINVAL; - if (old_dentry->d_parent->d_inode != new_parent->d_inode || - new_dentry->d_parent->d_inode != new_parent->d_inode || - old_dentry == new_dentry) + if (old_dentry == new_dentry) goto out_unlock; error = -EEXIST; @@ -955,9 +947,9 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, d_move(sd->s_dentry, new_dentry); sysfs_unlink_sibling(sd); - sysfs_get(new_parent_sd); + sysfs_get(parent_sd); sysfs_put(sd->s_parent); - sd->s_parent = new_parent_sd; + sd->s_parent = parent_sd; sysfs_link_sibling(sd); mutex_unlock(&sysfs_mutex); @@ -968,10 +960,10 @@ int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, out_drop: d_drop(new_dentry); out_unlock: - mutex_unlock(&new_parent->d_inode->i_mutex); + mutex_unlock(&parent->d_inode->i_mutex); out_dput: kfree(dup_name); - dput(new_parent); + dput(parent); dput(old_dentry); dput(new_dentry); return error; @@ -1192,121 +1184,6 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) return offset; } - -/** - * sysfs_make_shadowed_dir - Setup so a directory can be shadowed - * @kobj: object we're creating shadow of. - */ - -int sysfs_make_shadowed_dir(struct kobject *kobj, - void * (*follow_link)(struct dentry *, struct nameidata *)) -{ - struct dentry *dentry; - struct inode *inode; - struct inode_operations *i_op; - - /* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */ - dentry = sysfs_get_dentry(kobj->sd); - if (IS_ERR(dentry)) - return PTR_ERR(dentry); - - inode = dentry->d_inode; - if (inode->i_op != &sysfs_dir_inode_operations) { - dput(dentry); - return -EINVAL; - } - - i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); - if (!i_op) - return -ENOMEM; - - memcpy(i_op, &sysfs_dir_inode_operations, sizeof(*i_op)); - i_op->follow_link = follow_link; - - /* Locking of inode->i_op? - * Since setting i_op is a single word write and they - * are atomic we should be ok here. - */ - inode->i_op = i_op; - return 0; -} - -/** - * sysfs_create_shadow_dir - create a shadow directory for an object. - * @kobj: object we're creating directory for. - * - * sysfs_make_shadowed_dir must already have been called on this - * directory. - */ - -struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) -{ - struct sysfs_dirent *parent_sd = kobj->sd->s_parent; - struct dentry *dir, *parent, *shadow; - struct inode *inode; - struct sysfs_dirent *sd; - struct sysfs_addrm_cxt acxt; - - dir = sysfs_get_dentry(kobj->sd); - if (IS_ERR(dir)) { - sd = (void *)dir; - goto out; - } - parent = dir->d_parent; - - inode = dir->d_inode; - sd = ERR_PTR(-EINVAL); - if (!sysfs_is_shadowed_inode(inode)) - goto out_dput; - - shadow = d_alloc(parent, &dir->d_name); - if (!shadow) - goto nomem; - - sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); - if (!sd) - goto nomem; - sd->s_elem.dir.kobj = kobj; - - sysfs_addrm_start(&acxt, parent_sd); - - /* add but don't link into children list */ - sysfs_add_one(&acxt, sd); - - /* attach and instantiate dentry */ - sysfs_attach_dentry(sd, shadow); - d_instantiate(shadow, igrab(inode)); - inc_nlink(inode); /* tj: synchronization? */ - - sysfs_addrm_finish(&acxt); - - dget(shadow); /* Extra count - pin the dentry in core */ - - goto out_dput; - - nomem: - dput(shadow); - sd = ERR_PTR(-ENOMEM); - out_dput: - dput(dir); - out: - return sd; -} - -/** - * sysfs_remove_shadow_dir - remove an object's directory. - * @shadow_sd: sysfs_dirent of shadow directory - * - * The only thing special about this is that we remove any files in - * the directory before we remove the directory, and we've inlined - * what used to be sysfs_rmdir() below, instead of calling separately. - */ - -void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd) -{ - __sysfs_remove_dir(shadow_sd); -} - const struct file_operations sysfs_dir_operations = { .open = sysfs_dir_open, .release = sysfs_dir_close, -- cgit v1.2.2 From a7a0475497f9018e2e28cd421ee467d2ad68643e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Aug 2007 21:38:02 +0900 Subject: sysfs: cosmetic changes in sysfs_lookup() * remove space between * and symbol name in variable declaration. * kill unnecessary new line. * kill 'found' and test 'sd' instead. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 837073dbadf4..5da8da806660 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -756,24 +756,19 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct dentry *ret = NULL; - struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; - struct sysfs_dirent * sd; + struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; + struct sysfs_dirent *sd; struct bin_attribute *bin_attr; struct inode *inode; - int found = 0; mutex_lock(&sysfs_mutex); - for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) { - if (sysfs_type(sd) && - !strcmp(sd->s_name, dentry->d_name.name)) { - found = 1; + for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) + if (sysfs_type(sd) && !strcmp(sd->s_name, dentry->d_name.name)) break; - } - } /* no such entry */ - if (!found) + if (!sd) goto out_unlock; /* attach dentry and inode */ -- cgit v1.2.2 From ff869de7bf5e76adffebd3a176c1c73bca7eddb7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Aug 2007 21:38:02 +0900 Subject: sysfs: simplify sysfs_rename_dir() With the shadow directories gone, sysfs_rename_dir() can be simplified. * parent doesn't need to be grabbed separately. Just access old_dentry->d_parent. * parent sd can never change. Remove code to move under the new parent. * Massage comments a bit. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 5da8da806660..9504d4cb63eb 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -883,14 +883,10 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) struct sysfs_dirent *sd; struct dentry *parent = NULL; struct dentry *old_dentry = NULL, *new_dentry = NULL; - struct sysfs_dirent *parent_sd; const char *dup_name = NULL; int error; - if (!kobj->parent) - return -EINVAL; - - /* get dentries */ + /* get the original dentry */ sd = kobj->sd; old_dentry = sysfs_get_dentry(sd); if (IS_ERR(old_dentry)) { @@ -898,12 +894,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) goto out_dput; } - parent_sd = kobj->parent->sd; - parent = sysfs_get_dentry(parent_sd); - if (IS_ERR(parent)) { - error = PTR_ERR(parent); - goto out_dput; - } + parent = old_dentry->d_parent; /* lock parent and get dentry for new name */ mutex_lock(&parent->d_inode->i_mutex); @@ -933,22 +924,14 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) goto out_drop; mutex_lock(&sysfs_mutex); - dup_name = sd->s_name; sd->s_name = new_name; + mutex_unlock(&sysfs_mutex); - /* move under the new parent */ + /* rename */ d_add(new_dentry, NULL); d_move(sd->s_dentry, new_dentry); - sysfs_unlink_sibling(sd); - sysfs_get(parent_sd); - sysfs_put(sd->s_parent); - sd->s_parent = parent_sd; - sysfs_link_sibling(sd); - - mutex_unlock(&sysfs_mutex); - error = 0; goto out_unlock; @@ -958,7 +941,6 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) mutex_unlock(&parent->d_inode->i_mutex); out_dput: kfree(dup_name); - dput(parent); dput(old_dentry); dput(new_dentry); return error; -- cgit v1.2.2 From 41fc1c27452e041a18e5141b8203ee0ea72bc483 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Aug 2007 21:38:03 +0900 Subject: sysfs: make sysfs_add/remove_one() call link/unlink_sibling() implictly When adding or removing a sysfs_dirent, the user used to be required to call link/unlink separately. It was for two reasons - code looked like that before sysfs_addrm_cxt conversion and to avoid looping through parent_sd->children list twice during removal. Performance optimization during removal just isn't worth it. Make sysfs_add/remove_one() call sysfs_link/unlink_sibing() implicitly. This makes code simpler albeit slightly less efficient. This change doesn't introduce any noticeable behavior change. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9504d4cb63eb..354675ad0965 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -30,7 +30,7 @@ static DEFINE_IDA(sysfs_ino_ida); * Locking: * mutex_lock(sysfs_mutex) */ -void sysfs_link_sibling(struct sysfs_dirent *sd) +static void sysfs_link_sibling(struct sysfs_dirent *sd) { struct sysfs_dirent *parent_sd = sd->s_parent; @@ -49,7 +49,7 @@ void sysfs_link_sibling(struct sysfs_dirent *sd) * Locking: * mutex_lock(sysfs_mutex) */ -void sysfs_unlink_sibling(struct sysfs_dirent *sd) +static void sysfs_unlink_sibling(struct sysfs_dirent *sd) { struct sysfs_dirent **pos; @@ -500,6 +500,8 @@ void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) inc_nlink(acxt->parent_inode); acxt->cnt++; + + sysfs_link_sibling(sd); } /** @@ -521,7 +523,9 @@ void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) */ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { - BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED)); + BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED); + + sysfs_unlink_sibling(sd); sd->s_flags |= SYSFS_FLAG_REMOVED; sd->s_sibling = acxt->removed; @@ -697,10 +701,8 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, /* link in */ sysfs_addrm_start(&acxt, parent_sd); - if (!sysfs_find_dirent(parent_sd, name)) { + if (!sysfs_find_dirent(parent_sd, name)) sysfs_add_one(&acxt, sd); - sysfs_link_sibling(sd); - } if (!sysfs_addrm_finish(&acxt)) { sysfs_put(sd); @@ -821,7 +823,6 @@ static void remove_dir(struct sysfs_dirent *sd) struct sysfs_addrm_cxt acxt; sysfs_addrm_start(&acxt, sd->s_parent); - sysfs_unlink_sibling(sd); sysfs_remove_one(&acxt, sd); sysfs_addrm_finish(&acxt); } @@ -846,11 +847,9 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) while (*pos) { struct sysfs_dirent *sd = *pos; - if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) { - *pos = sd->s_sibling; - sd->s_sibling = NULL; + if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) sysfs_remove_one(&acxt, sd); - } else + else pos = &(*pos)->s_sibling; } sysfs_addrm_finish(&acxt); -- cgit v1.2.2 From 23dc279950a056c33a14d09cf759f5173d41abd9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Aug 2007 21:38:03 +0900 Subject: sysfs: make sysfs_add_one() automatically check for duplicate entry Make sysfs_add_one() check for duplicate entry and return -EEXIST if such entry exists. This simplifies node addition code a bit. This patch doesn't introduce any noticeable behavior change. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 354675ad0965..620603296c6c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -491,9 +491,16 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, * * LOCKING: * Determined by sysfs_addrm_start(). + * + * RETURNS: + * 0 on success, -EEXIST if entry with the given name already + * exists. */ -void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) +int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { + if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) + return -EEXIST; + sd->s_parent = sysfs_get(acxt->parent_sd); if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) @@ -502,6 +509,8 @@ void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) acxt->cnt++; sysfs_link_sibling(sd); + + return 0; } /** @@ -691,6 +700,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; struct sysfs_addrm_cxt acxt; struct sysfs_dirent *sd; + int rc; /* allocate */ sd = sysfs_new_dirent(name, mode, SYSFS_DIR); @@ -700,17 +710,15 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, /* link in */ sysfs_addrm_start(&acxt, parent_sd); + rc = sysfs_add_one(&acxt, sd); + sysfs_addrm_finish(&acxt); - if (!sysfs_find_dirent(parent_sd, name)) - sysfs_add_one(&acxt, sd); - - if (!sysfs_addrm_finish(&acxt)) { + if (rc == 0) + *p_sd = sd; + else sysfs_put(sd); - return -EEXIST; - } - *p_sd = sd; - return 0; + return rc; } int sysfs_create_subdir(struct kobject *kobj, const char *name, -- cgit v1.2.2 From 990e53f880be9ff93072b4cce590ec2826cee0b6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 2 Aug 2007 21:38:03 +0900 Subject: sysfs: make sysfs_addrm_finish() return void With the previous sysfs_add_one() update, there is only one user of the return value of sysfs_addrm_finish() and the user can switch to testing @sd easily. Make sysfs_addrm_finish() return void for cleaner semantics as suggested by Satyam Sharma. This patch doesn't introduce any noticeable behavior change. Signed-off-by: Tejun Heo Cc: Satyam Sharma Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 620603296c6c..a0da2b05a754 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -609,11 +609,8 @@ static void sysfs_drop_dentry(struct sysfs_dirent *sd) * * LOCKING: * All mutexes acquired by sysfs_addrm_start() are released. - * - * RETURNS: - * Number of added/removed sysfs_dirents since sysfs_addrm_start(). */ -int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) +void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) { /* release resources acquired by sysfs_addrm_start() */ mutex_unlock(&sysfs_mutex); @@ -639,8 +636,6 @@ int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) sysfs_deactivate(sd); sysfs_put(sd); } - - return acxt->cnt; } /** -- cgit v1.2.2 From 253280267a7f1ced0c434fb24b7bef92d7d22628 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 20 Aug 2007 21:36:29 +0900 Subject: sysfs: fix i_mutex locking in sysfs_get_dentry() lookup_one_len_kern() should be called with the parent's i_mutex locked. Fix it. Spotted by Eric W. Biederman. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index a0da2b05a754..54ca4bc02dcf 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -130,8 +130,10 @@ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) /* look it up */ parent_dentry = dentry; + mutex_lock(&parent_dentry->d_inode->i_mutex); dentry = lookup_one_len_kern(cur->s_name, parent_dentry, strlen(cur->s_name)); + mutex_unlock(&parent_dentry->d_inode->i_mutex); dput(parent_dentry); if (IS_ERR(dentry)) { -- cgit v1.2.2 From 372e88bd1922228e0a55228f6dc8e311d1696fa0 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:29 +0900 Subject: sysfs: Move all of inode initialization into sysfs_init_inode Signed-off-by: "Eric W. Biederman" Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 54ca4bc02dcf..5a70a93fc2f7 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -748,24 +748,12 @@ int sysfs_create_dir(struct kobject * kobj) return error; } -static int sysfs_count_nlink(struct sysfs_dirent *sd) -{ - struct sysfs_dirent *child; - int nr = 0; - - for (child = sd->s_children; child; child = child->s_sibling) - if (sysfs_type(child) == SYSFS_DIR) - nr++; - return nr + 2; -} - static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { struct dentry *ret = NULL; struct sysfs_dirent *parent_sd = dentry->d_parent->d_fsdata; struct sysfs_dirent *sd; - struct bin_attribute *bin_attr; struct inode *inode; mutex_lock(&sysfs_mutex); @@ -785,31 +773,6 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, goto out_unlock; } - if (inode->i_state & I_NEW) { - /* initialize inode according to type */ - switch (sysfs_type(sd)) { - case SYSFS_DIR: - inode->i_op = &sysfs_dir_inode_operations; - inode->i_fop = &sysfs_dir_operations; - inode->i_nlink = sysfs_count_nlink(sd); - break; - case SYSFS_KOBJ_ATTR: - inode->i_size = PAGE_SIZE; - inode->i_fop = &sysfs_file_operations; - break; - case SYSFS_KOBJ_BIN_ATTR: - bin_attr = sd->s_elem.bin_attr.bin_attr; - inode->i_size = bin_attr->size; - inode->i_fop = &bin_fops; - break; - case SYSFS_KOBJ_LINK: - inode->i_op = &sysfs_symlink_inode_operations; - break; - default: - BUG(); - } - } - sysfs_instantiate(dentry, inode); sysfs_attach_dentry(sd, dentry); -- cgit v1.2.2 From 119dd52be33dfe6285f586ab7354897fdefc7e23 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:29 +0900 Subject: sysfs: Remove sysfs_instantiate Now that sysfs_get_inode is dropping the inode lock we no longer have a need from sysfs_instantiate. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 5a70a93fc2f7..739dda176b43 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -773,7 +773,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, goto out_unlock; } - sysfs_instantiate(dentry, inode); + d_instantiate(dentry, inode); sysfs_attach_dentry(sd, dentry); out_unlock: -- cgit v1.2.2 From 7d0c7d676cc066413e1583b5af9fba8011972d41 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:30 +0900 Subject: sysfs: Make sysfs_mount static This patch modifies the users of sysfs_mount to use sysfs_root instead (which is what they are looking for). It then makes sysfs_mount static to keep people from using it by accident. The net result is slightly faster and cleaner code. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 739dda176b43..7f4abe176701 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -737,10 +737,8 @@ int sysfs_create_dir(struct kobject * kobj) if (kobj->parent) parent_sd = kobj->parent->sd; - else if (sysfs_mount && sysfs_mount->mnt_sb) - parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; else - return -EFAULT; + parent_sd = &sysfs_root; error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); if (!error) -- cgit v1.2.2 From 94777e09180b6249d455baa2dbe34cf630e0c033 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:30 +0900 Subject: sysfs: In sysfs_lookup don't open code sysfs_find_dirent This is a small cleanup patch that makes the code just a little bit cleaner. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 7f4abe176701..b72b42ed80d1 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -756,9 +756,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, mutex_lock(&sysfs_mutex); - for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) - if (sysfs_type(sd) && !strcmp(sd->s_name, dentry->d_name.name)) - break; + sd = sysfs_find_dirent(parent_sd, dentry->d_name.name); /* no such entry */ if (!sd) -- cgit v1.2.2 From 3efa65b92d832873ece62b42a4268c2515943977 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:30 +0900 Subject: sysfs: Simplify readdir. At some point someone wrote sysfs_readdir to insert a cursor into the list of sysfs_dirents to ensure that sysfs_readdir would restart properly. That works but it is complex code and tends to be expensive. The same effect can be achieved by keeping the sysfs_dirents in inode order and using the inode number as the f_pos. Then when we restart we just have to find the first dirent whose inode number is equal or greater then the last sysfs_dirent we attempted to return. Removing the sysfs directory cursor also allows the remove of all of the mysterious checks for sysfs_type(sd) != 0. Which were nonbovious checks to see if a cursor was in a directory list. tj: offset marker for EOF is changed from UINT_MAX to INT_MAX to avoid overflow in case offset is 32bit. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 175 +++++++++++++++------------------------------------------ 1 file changed, 44 insertions(+), 131 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index b72b42ed80d1..953e8432b0ae 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -33,10 +33,20 @@ static DEFINE_IDA(sysfs_ino_ida); static void sysfs_link_sibling(struct sysfs_dirent *sd) { struct sysfs_dirent *parent_sd = sd->s_parent; + struct sysfs_dirent **pos; BUG_ON(sd->s_sibling); - sd->s_sibling = parent_sd->s_children; - parent_sd->s_children = sd; + + /* Store directory entries in order by ino. This allows + * readdir to properly restart without having to add a + * cursor into the s_children list. + */ + for (pos = &parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) { + if (sd->s_ino < (*pos)->s_ino) + break; + } + sd->s_sibling = *pos; + *pos = sd; } /** @@ -659,7 +669,7 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, struct sysfs_dirent *sd; for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) - if (sysfs_type(sd) && !strcmp(sd->s_name, name)) + if (!strcmp(sd->s_name, name)) return sd; return NULL; } @@ -811,7 +821,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) while (*pos) { struct sysfs_dirent *sd = *pos; - if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) + if (sysfs_type(sd) != SYSFS_DIR) sysfs_remove_one(&acxt, sd); else pos = &(*pos)->s_sibling; @@ -976,37 +986,6 @@ again: return error; } -static int sysfs_dir_open(struct inode *inode, struct file *file) -{ - struct dentry * dentry = file->f_path.dentry; - struct sysfs_dirent * parent_sd = dentry->d_fsdata; - struct sysfs_dirent * sd; - - sd = sysfs_new_dirent("_DIR_", 0, 0); - if (sd) { - mutex_lock(&sysfs_mutex); - sd->s_parent = sysfs_get(parent_sd); - sysfs_link_sibling(sd); - mutex_unlock(&sysfs_mutex); - } - - file->private_data = sd; - return sd ? 0 : -ENOMEM; -} - -static int sysfs_dir_close(struct inode *inode, struct file *file) -{ - struct sysfs_dirent * cursor = file->private_data; - - mutex_lock(&sysfs_mutex); - sysfs_unlink_sibling(cursor); - mutex_unlock(&sysfs_mutex); - - release_sysfs_dirent(cursor); - - return 0; -} - /* Relationship between s_mode and the DT_xxx types */ static inline unsigned char dt_type(struct sysfs_dirent *sd) { @@ -1017,117 +996,51 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct dentry *dentry = filp->f_path.dentry; struct sysfs_dirent * parent_sd = dentry->d_fsdata; - struct sysfs_dirent *cursor = filp->private_data; - struct sysfs_dirent **pos; + struct sysfs_dirent *pos; ino_t ino; - int i = filp->f_pos; - switch (i) { - case 0: - ino = parent_sd->s_ino; - if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) - break; + if (filp->f_pos == 0) { + ino = parent_sd->s_ino; + if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) filp->f_pos++; - i++; - /* fallthrough */ - case 1: - if (parent_sd->s_parent) - ino = parent_sd->s_parent->s_ino; - else - ino = parent_sd->s_ino; - if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) - break; + } + if (filp->f_pos == 1) { + if (parent_sd->s_parent) + ino = parent_sd->s_parent->s_ino; + else + ino = parent_sd->s_ino; + if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) filp->f_pos++; - i++; - /* fallthrough */ - default: - mutex_lock(&sysfs_mutex); - - pos = &parent_sd->s_children; - while (*pos != cursor) - pos = &(*pos)->s_sibling; - - /* unlink cursor */ - *pos = cursor->s_sibling; - - if (filp->f_pos == 2) - pos = &parent_sd->s_children; - - for ( ; *pos; pos = &(*pos)->s_sibling) { - struct sysfs_dirent *next = *pos; - const char * name; - int len; - - if (!sysfs_type(next)) - continue; - - name = next->s_name; - len = strlen(name); - ino = next->s_ino; - - if (filldir(dirent, name, len, filp->f_pos, ino, - dt_type(next)) < 0) - break; - - filp->f_pos++; - } + } + if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) { + mutex_lock(&sysfs_mutex); - /* put cursor back in */ - cursor->s_sibling = *pos; - *pos = cursor; + /* Skip the dentries we have already reported */ + pos = parent_sd->s_children; + while (pos && (filp->f_pos > pos->s_ino)) + pos = pos->s_sibling; - mutex_unlock(&sysfs_mutex); - } - return 0; -} + for ( ; pos; pos = pos->s_sibling) { + const char * name; + int len; -static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) -{ - struct dentry * dentry = file->f_path.dentry; + name = pos->s_name; + len = strlen(name); + filp->f_pos = ino = pos->s_ino; - switch (origin) { - case 1: - offset += file->f_pos; - case 0: - if (offset >= 0) + if (filldir(dirent, name, len, filp->f_pos, ino, + dt_type(pos)) < 0) break; - default: - return -EINVAL; - } - if (offset != file->f_pos) { - mutex_lock(&sysfs_mutex); - - file->f_pos = offset; - if (file->f_pos >= 2) { - struct sysfs_dirent *sd = dentry->d_fsdata; - struct sysfs_dirent *cursor = file->private_data; - struct sysfs_dirent **pos; - loff_t n = file->f_pos - 2; - - sysfs_unlink_sibling(cursor); - - pos = &sd->s_children; - while (n && *pos) { - struct sysfs_dirent *next = *pos; - if (sysfs_type(next)) - n--; - pos = &(*pos)->s_sibling; - } - - cursor->s_sibling = *pos; - *pos = cursor; } - + if (!pos) + filp->f_pos = INT_MAX; mutex_unlock(&sysfs_mutex); } - - return offset; + return 0; } + const struct file_operations sysfs_dir_operations = { - .open = sysfs_dir_open, - .release = sysfs_dir_close, - .llseek = sysfs_dir_lseek, .read = generic_read_dir, .readdir = sysfs_readdir, }; -- cgit v1.2.2 From 89bec09705d2033b8b765f3c3ac5093f80bd5bc4 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:30 +0900 Subject: sysfs: Rewrite sysfs_drop_dentry. Currently we find the dentry to drop by looking at sd->s_dentry. We can just as easily accomplish the same task by looking up the sysfs inode and finding all of the dentries from there, with the added bonus that we don't need to play with the sysfs_assoc_lock. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 53 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 953e8432b0ae..1af963e66e3c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -565,50 +565,49 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) * Drop dentry for @sd. @sd must have been unlinked from its * parent on entry to this function such that it can't be looked * up anymore. - * - * @sd->s_dentry which is protected with sysfs_assoc_lock points - * to the currently associated dentry but we're not holding a - * reference to it and racing with dput(). Grab dcache_lock and - * verify dentry before dropping it. If @sd->s_dentry is NULL or - * dput() beats us, no need to bother. */ static void sysfs_drop_dentry(struct sysfs_dirent *sd) { - struct dentry *dentry = NULL; struct inode *inode; + struct dentry *dentry; + + inode = ilookup(sysfs_sb, sd->s_ino); + if (!inode) + return; - /* We're not holding a reference to ->s_dentry dentry but the - * field will stay valid as long as sysfs_assoc_lock is held. + /* Drop any existing dentries associated with sd. + * + * For the dentry to be properly freed we need to grab a + * reference to the dentry under the dcache lock, unhash it, + * and then put it. The playing with the dentry count allows + * dput to immediately free the dentry if it is not in use. */ - spin_lock(&sysfs_assoc_lock); +repeat: spin_lock(&dcache_lock); - - /* drop dentry if it's there and dput() didn't kill it yet */ - if (sd->s_dentry && sd->s_dentry->d_inode) { - dentry = dget_locked(sd->s_dentry); + list_for_each_entry(dentry, &inode->i_dentry, d_alias) { + if (d_unhashed(dentry)) + continue; + dget_locked(dentry); spin_lock(&dentry->d_lock); __d_drop(dentry); spin_unlock(&dentry->d_lock); + spin_unlock(&dcache_lock); + dput(dentry); + goto repeat; } - spin_unlock(&dcache_lock); - spin_unlock(&sysfs_assoc_lock); - - dput(dentry); /* adjust nlink and update timestamp */ - inode = ilookup(sysfs_sb, sd->s_ino); - if (inode) { - mutex_lock(&inode->i_mutex); + mutex_lock(&inode->i_mutex); - inode->i_ctime = CURRENT_TIME; + inode->i_ctime = CURRENT_TIME; + drop_nlink(inode); + if (sysfs_type(sd) == SYSFS_DIR) drop_nlink(inode); - if (sysfs_type(sd) == SYSFS_DIR) - drop_nlink(inode); - mutex_unlock(&inode->i_mutex); - iput(inode); - } + mutex_unlock(&inode->i_mutex); + + iput(inode); } /** -- cgit v1.2.2 From 932ea2e374dd1ca26676297a5eccd1cdab86f7cd Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:30 +0900 Subject: sysfs: Introduce sysfs_rename_mutex Looking carefully at the rename code we have a subtle dependency that the structure of sysfs not change while we are performing a rename. If the parent directory of the object we are renaming changes while the rename is being performed nasty things could happen when we go to release our locks. So introduce a sysfs_rename_mutex to prevent this highly unlikely theoretical issue. In addition hold sysfs_rename_mutex over all calls to sysfs_get_dentry. Allowing sysfs_get_dentry to be simplified in the future. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 1af963e66e3c..9fe83d23dc2c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -15,6 +15,7 @@ #include "sysfs.h" DEFINE_MUTEX(sysfs_mutex); +DEFINE_MUTEX(sysfs_rename_mutex); spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; @@ -82,7 +83,7 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) * down from there looking up dentry for each step. * * LOCKING: - * Kernel thread context (may sleep) + * mutex_lock(sysfs_rename_mutex) * * RETURNS: * Pointer to found dentry on success, ERR_PTR() value on error. @@ -858,6 +859,8 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) const char *dup_name = NULL; int error; + mutex_lock(&sysfs_rename_mutex); + /* get the original dentry */ sd = kobj->sd; old_dentry = sysfs_get_dentry(sd); @@ -915,6 +918,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) kfree(dup_name); dput(old_dentry); dput(new_dentry); + mutex_unlock(&sysfs_rename_mutex); return error; } @@ -926,6 +930,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) struct dentry *old_dentry = NULL, *new_dentry = NULL; int error; + mutex_lock(&sysfs_rename_mutex); BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; @@ -982,6 +987,7 @@ again: dput(new_parent); dput(old_dentry); dput(new_dentry); + mutex_unlock(&sysfs_rename_mutex); return error; } -- cgit v1.2.2 From e0712bbfd9cb617fc3a822781c2466fb6b7ede50 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 20 Aug 2007 21:36:30 +0900 Subject: sysfs: simply sysfs_get_dentry Now that we know the sysfs tree structure cannot change under us and sysfs shadow support is dropped, sysfs_get_dentry() can be simplified greatly. It can just look up from the root and there's no need to retry on failure. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 91 +++++++++++----------------------------------------------- 1 file changed, 16 insertions(+), 75 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9fe83d23dc2c..1c3dc5d01ccd 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -78,9 +78,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) * @sd: sysfs_dirent of interest * * Get dentry for @sd. Dentry is looked up if currently not - * present. This function climbs sysfs_dirent tree till it - * reaches a sysfs_dirent with valid dentry attached and descends - * down from there looking up dentry for each step. + * present. This function descends from the root looking up + * dentry for each step. * * LOCKING: * mutex_lock(sysfs_rename_mutex) @@ -90,86 +89,28 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) */ struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) { - struct sysfs_dirent *cur; - struct dentry *parent_dentry, *dentry; - int i, depth; + struct dentry *dentry = dget(sysfs_sb->s_root); - /* Find the first parent which has valid s_dentry and get the - * dentry. - */ - mutex_lock(&sysfs_mutex); - restart0: - spin_lock(&sysfs_assoc_lock); - restart1: - spin_lock(&dcache_lock); - - dentry = NULL; - depth = 0; - cur = sd; - while (!cur->s_dentry || !cur->s_dentry->d_inode) { - if (cur->s_flags & SYSFS_FLAG_REMOVED) { - dentry = ERR_PTR(-ENOENT); - depth = 0; - break; - } - cur = cur->s_parent; - depth++; - } - if (!IS_ERR(dentry)) - dentry = dget_locked(cur->s_dentry); + while (dentry->d_fsdata != sd) { + struct sysfs_dirent *cur; + struct dentry *parent; - spin_unlock(&dcache_lock); - spin_unlock(&sysfs_assoc_lock); - - /* from the found dentry, look up depth times */ - while (depth--) { - /* find and get depth'th ancestor */ - for (cur = sd, i = 0; cur && i < depth; i++) + /* find the first ancestor which hasn't been looked up */ + cur = sd; + while (cur->s_parent != dentry->d_fsdata) cur = cur->s_parent; - /* This can happen if tree structure was modified due - * to move/rename. Restart. - */ - if (i != depth) { - dput(dentry); - goto restart0; - } - - sysfs_get(cur); - - mutex_unlock(&sysfs_mutex); - /* look it up */ - parent_dentry = dentry; - mutex_lock(&parent_dentry->d_inode->i_mutex); - dentry = lookup_one_len_kern(cur->s_name, parent_dentry, + parent = dentry; + mutex_lock(&parent->d_inode->i_mutex); + dentry = lookup_one_len_kern(cur->s_name, parent, strlen(cur->s_name)); - mutex_unlock(&parent_dentry->d_inode->i_mutex); - dput(parent_dentry); - - if (IS_ERR(dentry)) { - sysfs_put(cur); - return dentry; - } + mutex_unlock(&parent->d_inode->i_mutex); + dput(parent); - mutex_lock(&sysfs_mutex); - spin_lock(&sysfs_assoc_lock); - - /* This, again, can happen if tree structure has - * changed and we looked up the wrong thing. Restart. - */ - if (cur->s_dentry != dentry) { - dput(dentry); - sysfs_put(cur); - goto restart1; - } - - spin_unlock(&sysfs_assoc_lock); - - sysfs_put(cur); + if (IS_ERR(dentry)) + break; } - - mutex_unlock(&sysfs_mutex); return dentry; } -- cgit v1.2.2 From 5a26b79c426f8e55ebf7204cb138eb6b1645d4d3 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:30 +0900 Subject: sysfs: Remove s_dentry The only uses of s_dentry left are the code that maintains s_dentry and trivial users that don't actually need it. So this patch removes the s_dentry maintenance code and restructures the trivial uses to use something else. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 1c3dc5d01ccd..36b6c796d4d5 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -289,22 +289,7 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) { struct sysfs_dirent * sd = dentry->d_fsdata; - if (sd) { - /* sd->s_dentry is protected with sysfs_assoc_lock. - * This allows sysfs_drop_dentry() to dereference it. - */ - spin_lock(&sysfs_assoc_lock); - - /* The dentry might have been deleted or another - * lookup could have happened updating sd->s_dentry to - * point the new dentry. Ignore if it isn't pointing - * to this dentry. - */ - if (sd->s_dentry == dentry) - sd->s_dentry = NULL; - spin_unlock(&sysfs_assoc_lock); - sysfs_put(sd); - } + sysfs_put(sd); iput(inode); } @@ -352,9 +337,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) * @sd: target sysfs_dirent * @dentry: dentry to associate * - * Associate @sd with @dentry. This is protected by - * sysfs_assoc_lock to avoid race with sysfs_d_iput(). - * * LOCKING: * mutex_lock(sysfs_mutex) */ @@ -362,12 +344,6 @@ static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry) { dentry->d_op = &sysfs_dentry_ops; dentry->d_fsdata = sysfs_get(sd); - - /* protect sd->s_dentry against sysfs_d_iput */ - spin_lock(&sysfs_assoc_lock); - sd->s_dentry = dentry; - spin_unlock(&sysfs_assoc_lock); - d_rehash(dentry); } @@ -846,7 +822,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) /* rename */ d_add(new_dentry, NULL); - d_move(sd->s_dentry, new_dentry); + d_move(old_dentry, new_dentry); error = 0; goto out_unlock; @@ -881,7 +857,7 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) error = PTR_ERR(old_dentry); goto out_dput; } - old_parent = sd->s_parent->s_dentry; + old_parent = old_dentry->d_parent; new_parent = sysfs_get_dentry(new_parent_sd); if (IS_ERR(new_parent)) { @@ -907,7 +883,7 @@ again: } else error = 0; d_add(new_dentry, NULL); - d_move(sd->s_dentry, new_dentry); + d_move(old_dentry, new_dentry); dput(new_dentry); /* Remove from old parent's list and insert into new parent's list. */ -- cgit v1.2.2 From 9918f9a4817cb6241c727b434d5f8ec5564198de Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:31 +0900 Subject: sysfs: Rewrite rename in terms of sysfs dirents This patch rewrites sysfs_rename_dir to perform it's checks as much as possible on the underlying sysfs_dirents instead of the contents of the dcache. It turns out that this version is a little simpler, and a little more like the rest of the sysfs directory modification code. tj: fixed double locking of sysfs_mutex Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 36b6c796d4d5..463c5e3ccf1f 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -770,7 +770,7 @@ void sysfs_remove_dir(struct kobject * kobj) int sysfs_rename_dir(struct kobject * kobj, const char *new_name) { - struct sysfs_dirent *sd; + struct sysfs_dirent *sd = kobj->sd; struct dentry *parent = NULL; struct dentry *old_dentry = NULL, *new_dentry = NULL; const char *dup_name = NULL; @@ -778,63 +778,57 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) mutex_lock(&sysfs_rename_mutex); + error = 0; + if (strcmp(sd->s_name, new_name) == 0) + goto out; /* nothing to rename */ + /* get the original dentry */ - sd = kobj->sd; old_dentry = sysfs_get_dentry(sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); - goto out_dput; + goto out; } parent = old_dentry->d_parent; /* lock parent and get dentry for new name */ mutex_lock(&parent->d_inode->i_mutex); + mutex_lock(&sysfs_mutex); - new_dentry = lookup_one_len(new_name, parent, strlen(new_name)); - if (IS_ERR(new_dentry)) { - error = PTR_ERR(new_dentry); - goto out_unlock; - } - - error = -EINVAL; - if (old_dentry == new_dentry) + error = -EEXIST; + if (sysfs_find_dirent(sd->s_parent, new_name)) goto out_unlock; - error = -EEXIST; - if (new_dentry->d_inode) + error = -ENOMEM; + new_dentry = d_alloc_name(parent, new_name); + if (!new_dentry) goto out_unlock; /* rename kobject and sysfs_dirent */ error = -ENOMEM; new_name = dup_name = kstrdup(new_name, GFP_KERNEL); if (!new_name) - goto out_drop; + goto out_unlock; error = kobject_set_name(kobj, "%s", new_name); if (error) - goto out_drop; + goto out_unlock; - mutex_lock(&sysfs_mutex); dup_name = sd->s_name; sd->s_name = new_name; - mutex_unlock(&sysfs_mutex); /* rename */ d_add(new_dentry, NULL); d_move(old_dentry, new_dentry); error = 0; - goto out_unlock; - - out_drop: - d_drop(new_dentry); out_unlock: + mutex_unlock(&sysfs_mutex); mutex_unlock(&parent->d_inode->i_mutex); - out_dput: kfree(dup_name); dput(old_dentry); dput(new_dentry); + out: mutex_unlock(&sysfs_rename_mutex); return error; } -- cgit v1.2.2 From 45aaae9c51d768d5a8fd53fb372b1eb714f37691 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Mon, 20 Aug 2007 21:36:31 +0900 Subject: sysfs: Rewrite sysfs_move_dir in terms of sysfs dirents This patch rewrites sysfs_move_dir to perform it's checks as much as possible on the underlying sysfs_dirents instead of the contents of the dcache, making sysfs_move_dir more like the rest of the sysfs directory modification code. Signed-off-by: Eric W. Biederman Signed-off-by: Tejun Heo Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 463c5e3ccf1f..da4bb66a610c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -845,56 +845,58 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) BUG_ON(!sd->s_parent); new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; + error = 0; + if (sd->s_parent == new_parent_sd) + goto out; /* nothing to move */ + /* get dentries */ old_dentry = sysfs_get_dentry(sd); if (IS_ERR(old_dentry)) { error = PTR_ERR(old_dentry); - goto out_dput; + goto out; } old_parent = old_dentry->d_parent; new_parent = sysfs_get_dentry(new_parent_sd); if (IS_ERR(new_parent)) { error = PTR_ERR(new_parent); - goto out_dput; + goto out; } - if (old_parent->d_inode == new_parent->d_inode) { - error = 0; - goto out_dput; /* nothing to move */ - } again: mutex_lock(&old_parent->d_inode->i_mutex); if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { mutex_unlock(&old_parent->d_inode->i_mutex); goto again; } + mutex_lock(&sysfs_mutex); - new_dentry = lookup_one_len(kobject_name(kobj), new_parent, strlen(kobject_name(kobj))); - if (IS_ERR(new_dentry)) { - error = PTR_ERR(new_dentry); + error = -EEXIST; + if (sysfs_find_dirent(new_parent_sd, sd->s_name)) goto out_unlock; - } else - error = 0; + + error = -ENOMEM; + new_dentry = d_alloc_name(new_parent, sd->s_name); + if (!new_dentry) + goto out_unlock; + + error = 0; d_add(new_dentry, NULL); d_move(old_dentry, new_dentry); dput(new_dentry); /* Remove from old parent's list and insert into new parent's list. */ - mutex_lock(&sysfs_mutex); - sysfs_unlink_sibling(sd); sysfs_get(new_parent_sd); sysfs_put(sd->s_parent); sd->s_parent = new_parent_sd; sysfs_link_sibling(sd); - mutex_unlock(&sysfs_mutex); - out_unlock: + mutex_unlock(&sysfs_mutex); mutex_unlock(&new_parent->d_inode->i_mutex); mutex_unlock(&old_parent->d_inode->i_mutex); - out_dput: + out: dput(new_parent); dput(old_dentry); dput(new_dentry); -- cgit v1.2.2 From 5c3e8964ce87477a12e3e9edc3742156a3929a74 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2007 02:53:13 -0700 Subject: sysfs: spit a warning to users when they try to create a duplicate sysfs file We want to let people know when we create a duplicate sysfs file, as they need to fix up their code. Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index da4bb66a610c..5d95aa8e23c6 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -428,8 +428,12 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, */ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) { - if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) + if (sysfs_find_dirent(acxt->parent_sd, sd->s_name)) { + printk(KERN_WARNING "sysfs: duplicate filename '%s' " + "can not be created\n", sd->s_name); + WARN_ON(1); return -EEXIST; + } sd->s_parent = sysfs_get(acxt->parent_sd); -- cgit v1.2.2 From 181b2e4be1603ce3ccace8322047a548f29f4b20 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:09 +0900 Subject: sysfs: fix comments of sysfs_add/remove_one() sysfs_add/remove_one() now link and unlink the target dirent into and from the children list. Update comments accordingly. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 5d95aa8e23c6..fc615eed67dc 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -410,10 +410,8 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, * @sd: sysfs_dirent to be added * * Get @acxt->parent_sd and set sd->s_parent to it and increment - * nlink of parent inode if @sd is a directory. @sd is NOT - * linked into the children list of the parent. The caller - * should invoke sysfs_link_sibling() after this function - * completes if @sd needs to be on the children list. + * nlink of parent inode if @sd is a directory and link into the + * children list of the parent. * * This function should be called between calls to * sysfs_addrm_start() and sysfs_addrm_finish() and should be @@ -453,9 +451,7 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) * @sd: sysfs_dirent to be added * * Mark @sd removed and drop nlink of parent inode if @sd is a - * directory. @sd is NOT unlinked from the children list of the - * parent. The caller is repsonsible for removing @sd from the - * children list before calling this function. + * directory. @sd is unlinked from the children list. * * This function should be called between calls to * sysfs_addrm_start() and sysfs_addrm_finish() and should be -- cgit v1.2.2 From b1fc3d6144d56360d1373b01c7881826f558b6cd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:11 +0900 Subject: sysfs: make s_elem an anonymous union Make s_elem an anonymous union. Prefixing with s_elem makes things needlessly longer without any advantage. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index fc615eed67dc..6ee76a82eb38 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -273,7 +273,7 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) parent_sd = sd->s_parent; if (sysfs_type(sd) == SYSFS_KOBJ_LINK) - sysfs_put(sd->s_elem.symlink.target_sd); + sysfs_put(sd->s_symlink.target_sd); if (sysfs_type(sd) & SYSFS_COPY_NAME) kfree(sd->s_name); kfree(sd->s_iattr); @@ -630,7 +630,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, sd = sysfs_new_dirent(name, mode, SYSFS_DIR); if (!sd) return -ENOMEM; - sd->s_elem.dir.kobj = kobj; + sd->s_dir.kobj = kobj; /* link in */ sysfs_addrm_start(&acxt, parent_sd); -- cgit v1.2.2 From d6b4fd2faeb9ddf55ce09cf90b88981e579ee010 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:11 +0900 Subject: sysfs: open code sysfs_attach_dentry() sysfs_attach_dentry() now has only one caller and isn't doing much other than obfuscating the code. Open code and kill it. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6ee76a82eb38..48a3ed4f4537 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -332,21 +332,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) return NULL; } -/** - * sysfs_attach_dentry - associate sysfs_dirent with dentry - * @sd: target sysfs_dirent - * @dentry: dentry to associate - * - * LOCKING: - * mutex_lock(sysfs_mutex) - */ -static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry) -{ - dentry->d_op = &sysfs_dentry_ops; - dentry->d_fsdata = sysfs_get(sd); - d_rehash(dentry); -} - static int sysfs_ilookup_test(struct inode *inode, void *arg) { struct sysfs_dirent *sd = arg; @@ -696,8 +681,11 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* instantiate and hash dentry */ + dentry->d_op = &sysfs_dentry_ops; + dentry->d_fsdata = sysfs_get(sd); d_instantiate(dentry, inode); - sysfs_attach_dentry(sd, dentry); + d_rehash(dentry); out_unlock: mutex_unlock(&sysfs_mutex); -- cgit v1.2.2 From bc747f37a0f089b9366f7385ff870e12911f2383 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:12 +0900 Subject: sysfs: move sysfs_dirent->s_children into sysfs_dirent->s_dir Children list head is only meaninful for directory nodes. Move it into s_dir. This doesn't save any space currently but it will with further changes. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 48a3ed4f4537..4ad9422566a8 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -26,7 +26,7 @@ static DEFINE_IDA(sysfs_ino_ida); * @sd: sysfs_dirent of interest * * Link @sd into its sibling list which starts from - * sd->s_parent->s_children. + * sd->s_parent->s_dir.children. * * Locking: * mutex_lock(sysfs_mutex) @@ -40,9 +40,9 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) /* Store directory entries in order by ino. This allows * readdir to properly restart without having to add a - * cursor into the s_children list. + * cursor into the s_dir.children list. */ - for (pos = &parent_sd->s_children; *pos; pos = &(*pos)->s_sibling) { + for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) { if (sd->s_ino < (*pos)->s_ino) break; } @@ -55,7 +55,7 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) * @sd: sysfs_dirent of interest * * Unlink @sd from its sibling list which starts from - * sd->s_parent->s_children. + * sd->s_parent->s_dir.children. * * Locking: * mutex_lock(sysfs_mutex) @@ -64,7 +64,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) { struct sysfs_dirent **pos; - for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) { + for (pos = &sd->s_parent->s_dir.children; *pos; + pos = &(*pos)->s_sibling) { if (*pos == sd) { *pos = sd->s_sibling; sd->s_sibling = NULL; @@ -570,7 +571,7 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, { struct sysfs_dirent *sd; - for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) + for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) if (!strcmp(sd->s_name, name)) return sd; return NULL; @@ -722,7 +723,7 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); sysfs_addrm_start(&acxt, dir_sd); - pos = &dir_sd->s_children; + pos = &dir_sd->s_dir.children; while (*pos) { struct sysfs_dirent *sd = *pos; @@ -922,7 +923,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) mutex_lock(&sysfs_mutex); /* Skip the dentries we have already reported */ - pos = parent_sd->s_children; + pos = parent_sd->s_dir.children; while (pos && (filp->f_pos > pos->s_ino)) pos = pos->s_sibling; -- cgit v1.2.2 From a4e8b912541d5372ae049a3b7c1979968e52c40b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 16:05:12 +0900 Subject: sysfs: move sysfs file poll implementation to sysfs_open_dirent Sysfs file poll implementation is scattered over sysfs and kobject. Event numbering is done in sysfs_dirent but wait itself is done on kobject. This not only unecessarily bloats both kobject and sysfs_dirent but is also buggy - if a sysfs_dirent is removed while there still are pollers, the associaton betwen the kobject and sysfs_dirent breaks and kobject may be freed with the pollers still sleeping on it. This patch moves whole poll implementation into sysfs_open_dirent. Each time a sysfs_open_dirent is created, event number restarts from 1 and pollers sleep on sysfs_open_dirent. As event sequence number is meaningless without any open file and pollers should have open file and thus sysfs_open_dirent, this ephemeral event counting works and is a saner implementation. This patch fixes the dnagling sleepers bug and reduces the sizes of kobject and sysfs_dirent by one pointer. Signed-off-by: Tejun Heo Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 4ad9422566a8..e301a1207b60 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -318,7 +318,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) atomic_set(&sd->s_count, 1); atomic_set(&sd->s_active, 0); - atomic_set(&sd->s_event, 1); sd->s_name = name; sd->s_mode = mode; -- cgit v1.2.2 From 6d66f5cd26e4c482e986130b7572f2735a0f7e8b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 20 Sep 2007 17:31:38 +0900 Subject: sysfs: add copyrights Sysfs has gone through considerable amount of reimplementation. Add copyrights. Any objections? :-) Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'fs/sysfs/dir.c') diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e301a1207b60..9161db4d6b5c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -1,5 +1,13 @@ /* - * dir.c - Operations for sysfs directories. + * fs/sysfs/dir.c - sysfs core and dir operation implementation + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007 Tejun Heo + * + * This file is released under the GPLv2. + * + * Please see Documentation/filesystems/sysfs.txt for more information. */ #undef DEBUG -- cgit v1.2.2