From b8441ed279bff09a0a5ddeacf8f4087d2fb424ca Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 24 Nov 2013 09:54:58 -0500 Subject: sysfs, kernfs: add skeletons for kernfs Core sysfs implementation will be separated into kernfs so that it can be used by other non-kobject users. This patch creates fs/kernfs/ directory and makes boilerplate changes. kernfs interface will be directly based on sysfs_dirent and its forward declaration is moved to include/linux/kernfs.h which is included from include/linux/sysfs.h. sysfs core implementation will be gradually separated out and moved to kernfs. This patch doesn't introduce any functional changes. v2: mount.c added. Signed-off-by: Tejun Heo Cc: linux-fsdevel@vger.kernel.org Cc: Christoph Hellwig Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 fs/kernfs/symlink.c (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c new file mode 100644 index 000000000000..2578715baf0e --- /dev/null +++ b/fs/kernfs/symlink.c @@ -0,0 +1,9 @@ +/* + * fs/kernfs/symlink.c - kernfs symlink implementation + * + * Copyright (c) 2001-3 Patrick Mochel + * Copyright (c) 2007 SUSE Linux Products GmbH + * Copyright (c) 2007, 2013 Tejun Heo + * + * This file is released under the GPLv2. + */ -- cgit v1.2.3 From 2072f1afddfe9fa00c1c0c79f8986707324ec65b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:35 -0500 Subject: sysfs, kernfs: move symlink core code to fs/kernfs/symlink.c Move core symlink code to fs/kernfs/symlink.c. fs/sysfs/symlink.c now only contains sysfs wrappers around kernfs interfaces. The respective declarations in fs/sysfs/sysfs.h are moved to fs/kernfs/kernfs-internal.h. This is pure relocation. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 2578715baf0e..af3570bb4303 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -7,3 +7,142 @@ * * This file is released under the GPLv2. */ + +#include +#include +#include + +#include "kernfs-internal.h" + +/** + * kernfs_create_link - create a symlink + * @parent: directory to create the symlink in + * @name: name of the symlink + * @target: target node for the symlink to point to + * + * Returns the created node on success, ERR_PTR() value on error. + */ +struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, + const char *name, + struct sysfs_dirent *target) +{ + struct sysfs_dirent *sd; + struct sysfs_addrm_cxt acxt; + int error; + + sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); + if (!sd) + return ERR_PTR(-ENOMEM); + + if (parent->s_flags & SYSFS_FLAG_NS) + sd->s_ns = target->s_ns; + sd->s_symlink.target_sd = target; + kernfs_get(target); /* ref owned by symlink */ + + sysfs_addrm_start(&acxt); + error = sysfs_add_one(&acxt, sd, parent); + sysfs_addrm_finish(&acxt); + + if (!error) + return sd; + + kernfs_put(sd); + return ERR_PTR(error); +} + +static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, + struct sysfs_dirent *target_sd, char *path) +{ + struct sysfs_dirent *base, *sd; + char *s = path; + int len = 0; + + /* go up to the root, stop at the base */ + base = parent_sd; + while (base->s_parent) { + sd = target_sd->s_parent; + while (sd->s_parent && base != sd) + sd = sd->s_parent; + + if (base == sd) + break; + + strcpy(s, "../"); + s += 3; + base = base->s_parent; + } + + /* determine end of target string for reverse fillup */ + sd = target_sd; + while (sd->s_parent && sd != base) { + len += strlen(sd->s_name) + 1; + sd = sd->s_parent; + } + + /* check limits */ + if (len < 2) + return -EINVAL; + len--; + if ((s - path) + len > PATH_MAX) + return -ENAMETOOLONG; + + /* reverse fillup of target string from target to base */ + sd = target_sd; + while (sd->s_parent && sd != base) { + int slen = strlen(sd->s_name); + + len -= slen; + strncpy(s + len, sd->s_name, slen); + if (len) + s[--len] = '/'; + + sd = sd->s_parent; + } + + return 0; +} + +static int sysfs_getlink(struct dentry *dentry, char *path) +{ + struct sysfs_dirent *sd = dentry->d_fsdata; + struct sysfs_dirent *parent_sd = sd->s_parent; + struct sysfs_dirent *target_sd = sd->s_symlink.target_sd; + int error; + + mutex_lock(&sysfs_mutex); + error = sysfs_get_target_path(parent_sd, target_sd, path); + mutex_unlock(&sysfs_mutex); + + return error; +} + +static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + int error = -ENOMEM; + unsigned long page = get_zeroed_page(GFP_KERNEL); + if (page) { + error = sysfs_getlink(dentry, (char *) page); + if (error < 0) + free_page((unsigned long)page); + } + nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); + return NULL; +} + +static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, + void *cookie) +{ + char *page = nd_get_link(nd); + if (!IS_ERR(page)) + free_page((unsigned long)page); +} + +const struct inode_operations sysfs_symlink_inode_operations = { + .setxattr = sysfs_setxattr, + .readlink = generic_readlink, + .follow_link = sysfs_follow_link, + .put_link = sysfs_put_link, + .setattr = sysfs_setattr, + .getattr = sysfs_getattr, + .permission = sysfs_permission, +}; -- cgit v1.2.3 From bc755553df9ab33f389c1a0a8bd0b4f4646e80ef Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:41 -0500 Subject: sysfs, kernfs: make inode number ida per kernfs_root kernfs is being updated to allow multiple sysfs_dirent hierarchies so that it can also be used by other users. Currently, inode number is allocated using a global ida, sysfs_ino_ida; however, inos for different hierarchies should be handled separately. This patch makes ino allocation per kernfs_root. sysfs_ino_ida is replaced by kernfs_root->ino_ida and sysfs_new_dirent() is updated to take @root and allocate ino from it. ida_simple_get/remove() are used instead of sysfs_ino_lock and sysfs_alloc/free_ino(). Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index af3570bb4303..004c16465594 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -30,7 +30,8 @@ struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, struct sysfs_addrm_cxt acxt; int error; - sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); + sd = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, + SYSFS_KOBJ_LINK); if (!sd) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From ac9bba031001704a2339713cc12148857eccc5e5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Nov 2013 17:19:09 -0500 Subject: sysfs, kernfs: implement kernfs_ns_enabled() fs/sysfs/symlink.c::sysfs_delete_link() tests @sd->s_flags for SYSFS_FLAG_NS. Let's add kernfs_ns_enabled() so that sysfs doesn't have to test sysfs_dirent flag directly. This makes things tidier for kernfs proper too. This is purely cosmetic. v2: To avoid possible NULL deref, use noop dummy implementation which always returns false when !CONFIG_SYSFS. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 004c16465594..12569a738837 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -35,7 +35,7 @@ struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, if (!sd) return ERR_PTR(-ENOMEM); - if (parent->s_flags & SYSFS_FLAG_NS) + if (kernfs_ns_enabled(parent)) sd->s_ns = target->s_ns; sd->s_symlink.target_sd = target; kernfs_get(target); /* ref owned by symlink */ -- cgit v1.2.3 From 2322392b020badfe49730f1529b9c1a15248c387 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 23 Nov 2013 17:40:02 -0500 Subject: kernfs: implement "trusted.*" xattr support kernfs inherited "security.*" xattr support from sysfs. This patch extends xattr support to "trusted.*" using simple_xattr_*(). As trusted xattrs are restricted to CAP_SYS_ADMIN, simple_xattr_*() which uses kernel memory for storage shouldn't be problematic. Note that the existing "security.*" support doesn't implement get/remove/list and the this patch only implements those ops for "trusted.*". We probably want to extend those ops to include support for "security.*". This patch will allow using kernfs from cgroup which requires "trusted.*" xattr support. Signed-off-by: Tejun Heo Cc: David P. Quigley Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 12569a738837..adf28755b0ee 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -140,6 +140,9 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, const struct inode_operations sysfs_symlink_inode_operations = { .setxattr = sysfs_setxattr, + .removexattr = sysfs_removexattr, + .getxattr = sysfs_getxattr, + .listxattr = sysfs_listxattr, .readlink = generic_readlink, .follow_link = sysfs_follow_link, .put_link = sysfs_put_link, -- cgit v1.2.3 From 324a56e16e44baecac3ca799fd216154145c14bf Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 14:11:53 -0500 Subject: kernfs: s/sysfs_dirent/kernfs_node/ and rename its friends accordingly kernfs has just been separated out from sysfs and we're already in full conflict mode. Nothing can make the situation any worse. Let's take the chance to name things properly. This patch performs the following renames. * s/sysfs_elem_dir/kernfs_elem_dir/ * s/sysfs_elem_symlink/kernfs_elem_symlink/ * s/sysfs_elem_attr/kernfs_elem_file/ * s/sysfs_dirent/kernfs_node/ * s/sd/kn/ in kernfs proper * s/parent_sd/parent/ * s/target_sd/target/ * s/dir_sd/parent/ * s/to_sysfs_dirent()/rb_to_kn()/ * misc renames of local vars when they conflict with the above Because md, mic and gpio dig into sysfs details, this patch ends up modifying them. All are sysfs_dirent renames and trivial. While we can avoid these by introducing a dummy wrapping struct sysfs_dirent around kernfs_node, given the limited usage outside kernfs and sysfs proper, I don't think such workaround is called for. This patch is strictly rename only and doesn't introduce any functional difference. - mic / gpio renames were missing. Spotted by kbuild test robot. Signed-off-by: Tejun Heo Cc: Neil Brown Cc: Linus Walleij Cc: Ashutosh Dixit Cc: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index adf28755b0ee..29dcf5e8debd 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -22,50 +22,50 @@ * * Returns the created node on success, ERR_PTR() value on error. */ -struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, - const char *name, - struct sysfs_dirent *target) +struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, + const char *name, + struct kernfs_node *target) { - struct sysfs_dirent *sd; + struct kernfs_node *kn; struct sysfs_addrm_cxt acxt; int error; - sd = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, + kn = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); - if (!sd) + if (!kn) return ERR_PTR(-ENOMEM); if (kernfs_ns_enabled(parent)) - sd->s_ns = target->s_ns; - sd->s_symlink.target_sd = target; + kn->s_ns = target->s_ns; + kn->s_symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ sysfs_addrm_start(&acxt); - error = sysfs_add_one(&acxt, sd, parent); + error = sysfs_add_one(&acxt, kn, parent); sysfs_addrm_finish(&acxt); if (!error) - return sd; + return kn; - kernfs_put(sd); + kernfs_put(kn); return ERR_PTR(error); } -static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, - struct sysfs_dirent *target_sd, char *path) +static int sysfs_get_target_path(struct kernfs_node *parent, + struct kernfs_node *target, char *path) { - struct sysfs_dirent *base, *sd; + struct kernfs_node *base, *kn; char *s = path; int len = 0; /* go up to the root, stop at the base */ - base = parent_sd; + base = parent; while (base->s_parent) { - sd = target_sd->s_parent; - while (sd->s_parent && base != sd) - sd = sd->s_parent; + kn = target->s_parent; + while (kn->s_parent && base != kn) + kn = kn->s_parent; - if (base == sd) + if (base == kn) break; strcpy(s, "../"); @@ -74,10 +74,10 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, } /* determine end of target string for reverse fillup */ - sd = target_sd; - while (sd->s_parent && sd != base) { - len += strlen(sd->s_name) + 1; - sd = sd->s_parent; + kn = target; + while (kn->s_parent && kn != base) { + len += strlen(kn->s_name) + 1; + kn = kn->s_parent; } /* check limits */ @@ -88,16 +88,16 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, return -ENAMETOOLONG; /* reverse fillup of target string from target to base */ - sd = target_sd; - while (sd->s_parent && sd != base) { - int slen = strlen(sd->s_name); + kn = target; + while (kn->s_parent && kn != base) { + int slen = strlen(kn->s_name); len -= slen; - strncpy(s + len, sd->s_name, slen); + strncpy(s + len, kn->s_name, slen); if (len) s[--len] = '/'; - sd = sd->s_parent; + kn = kn->s_parent; } return 0; @@ -105,13 +105,13 @@ static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, static int sysfs_getlink(struct dentry *dentry, char *path) { - struct sysfs_dirent *sd = dentry->d_fsdata; - struct sysfs_dirent *parent_sd = sd->s_parent; - struct sysfs_dirent *target_sd = sd->s_symlink.target_sd; + struct kernfs_node *kn = dentry->d_fsdata; + struct kernfs_node *parent = kn->s_parent; + struct kernfs_node *target = kn->s_symlink.target_kn; int error; mutex_lock(&sysfs_mutex); - error = sysfs_get_target_path(parent_sd, target_sd, path); + error = sysfs_get_target_path(parent, target, path); mutex_unlock(&sysfs_mutex); return error; -- cgit v1.2.3 From adc5e8b58f4886d45f79f4ff41a09001a76a6b12 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 14:11:54 -0500 Subject: kernfs: drop s_ prefix from kernfs_node members kernfs has just been separated out from sysfs and we're already in full conflict mode. Nothing can make the situation any worse. Let's take the chance to name things properly. s_ prefix for kernfs members is used inconsistently and a misnomer now. It's not like kernfs_node is used widely across the kernel making the ability to grep for the members particularly useful. Let's just drop the prefix. This patch is strictly rename only and doesn't introduce any functional difference. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 29dcf5e8debd..5ac1a57c3807 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -36,8 +36,8 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, return ERR_PTR(-ENOMEM); if (kernfs_ns_enabled(parent)) - kn->s_ns = target->s_ns; - kn->s_symlink.target_kn = target; + kn->ns = target->ns; + kn->symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ sysfs_addrm_start(&acxt); @@ -60,24 +60,24 @@ static int sysfs_get_target_path(struct kernfs_node *parent, /* go up to the root, stop at the base */ base = parent; - while (base->s_parent) { - kn = target->s_parent; - while (kn->s_parent && base != kn) - kn = kn->s_parent; + while (base->parent) { + kn = target->parent; + while (kn->parent && base != kn) + kn = kn->parent; if (base == kn) break; strcpy(s, "../"); s += 3; - base = base->s_parent; + base = base->parent; } /* determine end of target string for reverse fillup */ kn = target; - while (kn->s_parent && kn != base) { - len += strlen(kn->s_name) + 1; - kn = kn->s_parent; + while (kn->parent && kn != base) { + len += strlen(kn->name) + 1; + kn = kn->parent; } /* check limits */ @@ -89,15 +89,15 @@ static int sysfs_get_target_path(struct kernfs_node *parent, /* reverse fillup of target string from target to base */ kn = target; - while (kn->s_parent && kn != base) { - int slen = strlen(kn->s_name); + while (kn->parent && kn != base) { + int slen = strlen(kn->name); len -= slen; - strncpy(s + len, kn->s_name, slen); + strncpy(s + len, kn->name, slen); if (len) s[--len] = '/'; - kn = kn->s_parent; + kn = kn->parent; } return 0; @@ -106,8 +106,8 @@ static int sysfs_get_target_path(struct kernfs_node *parent, static int sysfs_getlink(struct dentry *dentry, char *path) { struct kernfs_node *kn = dentry->d_fsdata; - struct kernfs_node *parent = kn->s_parent; - struct kernfs_node *target = kn->s_symlink.target_kn; + struct kernfs_node *parent = kn->parent; + struct kernfs_node *target = kn->symlink.target_kn; int error; mutex_lock(&sysfs_mutex); -- cgit v1.2.3 From c525aaddc366df23eb095d58a2bdf11cce62a98b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 14:11:55 -0500 Subject: kernfs: s/sysfs/kernfs/ in various data structures kernfs has just been separated out from sysfs and we're already in full conflict mode. Nothing can make the situation any worse. Let's take the chance to name things properly. This patch performs the following renames. * s/sysfs_open_dirent/kernfs_open_node/ * s/sysfs_open_file/kernfs_open_file/ * s/sysfs_inode_attrs/kernfs_iattrs/ * s/sysfs_addrm_cxt/kernfs_addrm_cxt/ * s/sysfs_super_info/kernfs_super_info/ * s/sysfs_info()/kernfs_info()/ * s/sysfs_open_dirent_lock/kernfs_open_node_lock/ * s/sysfs_open_file_mutex/kernfs_open_file_mutex/ * s/sysfs_of()/kernfs_of()/ This patch is strictly rename only and doesn't introduce any functional difference. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 5ac1a57c3807..f36e3f1b2477 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -27,7 +27,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, struct kernfs_node *target) { struct kernfs_node *kn; - struct sysfs_addrm_cxt acxt; + struct kernfs_addrm_cxt acxt; int error; kn = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, -- cgit v1.2.3 From df23fc39bce03bb26e63bea57fc5f5bf6882d74b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 14:11:56 -0500 Subject: kernfs: s/sysfs/kernfs/ in constants kernfs has just been separated out from sysfs and we're already in full conflict mode. Nothing can make the situation any worse. Let's take the chance to name things properly. This patch performs the following renames. * s/SYSFS_DIR/KERNFS_DIR/ * s/SYSFS_KOBJ_ATTR/KERNFS_FILE/ * s/SYSFS_KOBJ_LINK/KERNFS_LINK/ * s/SYSFS_{TYPE_FLAGS}/KERNFS_{TYPE_FLAGS}/ * s/SYSFS_FLAG_{FLAG}/KERNFS_{FLAG}/ * s/sysfs_type()/kernfs_type()/ * s/SD_DEACTIVATED_BIAS/KN_DEACTIVATED_BIAS/ This patch is strictly rename only and doesn't introduce any functional difference. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index f36e3f1b2477..a92284d3c73d 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -31,7 +31,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, int error; kn = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, - SYSFS_KOBJ_LINK); + KERNFS_LINK); if (!kn) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From a797bfc30532388e8a11ca726df60cdd77aa8675 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 14:11:57 -0500 Subject: kernfs: s/sysfs/kernfs/ in global variables kernfs has just been separated out from sysfs and we're already in full conflict mode. Nothing can make the situation any worse. Let's take the chance to name things properly. This patch performs the following renames. * s/sysfs_mutex/kernfs_mutex/ * s/sysfs_dentry_ops/kernfs_dops/ * s/sysfs_dir_operations/kernfs_dir_fops/ * s/sysfs_dir_inode_operations/kernfs_dir_iops/ * s/kernfs_file_operations/kernfs_file_fops/ - renamed for consistency * s/sysfs_symlink_inode_operations/kernfs_symlink_iops/ * s/sysfs_aops/kernfs_aops/ * s/sysfs_backing_dev_info/kernfs_bdi/ * s/sysfs_inode_operations/kernfs_iops/ * s/sysfs_dir_cachep/kernfs_node_cache/ * s/sysfs_ops/kernfs_sops/ This patch is strictly rename only and doesn't introduce any functional difference. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index a92284d3c73d..4105bd04ea2f 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -110,9 +110,9 @@ static int sysfs_getlink(struct dentry *dentry, char *path) struct kernfs_node *target = kn->symlink.target_kn; int error; - mutex_lock(&sysfs_mutex); + mutex_lock(&kernfs_mutex); error = sysfs_get_target_path(parent, target, path); - mutex_unlock(&sysfs_mutex); + mutex_unlock(&kernfs_mutex); return error; } @@ -138,7 +138,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, free_page((unsigned long)page); } -const struct inode_operations sysfs_symlink_inode_operations = { +const struct inode_operations kernfs_symlink_iops = { .setxattr = sysfs_setxattr, .removexattr = sysfs_removexattr, .getxattr = sysfs_getxattr, -- cgit v1.2.3 From c637b8acbe079edb477d887041755b489036f146 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 14:11:58 -0500 Subject: kernfs: s/sysfs/kernfs/ in internal functions and whatever is left kernfs has just been separated out from sysfs and we're already in full conflict mode. Nothing can make the situation any worse. Let's take the chance to name things properly. This patch performs the following renames. * s/sysfs_*()/kernfs_*()/ in all internal functions * s/sysfs/kernfs/ in internal strings, comments and whatever is remaining * Uniformly rename various vfs operations so that they're consistently named and distinguishable. This patch is strictly rename only and doesn't introduce any functional difference. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 4105bd04ea2f..a03e26036ef9 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -30,8 +30,8 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, struct kernfs_addrm_cxt acxt; int error; - kn = sysfs_new_dirent(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, - KERNFS_LINK); + kn = kernfs_new_node(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, + KERNFS_LINK); if (!kn) return ERR_PTR(-ENOMEM); @@ -40,9 +40,9 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, kn->symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ - sysfs_addrm_start(&acxt); - error = sysfs_add_one(&acxt, kn, parent); - sysfs_addrm_finish(&acxt); + kernfs_addrm_start(&acxt); + error = kernfs_add_one(&acxt, kn, parent); + kernfs_addrm_finish(&acxt); if (!error) return kn; @@ -51,8 +51,8 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, return ERR_PTR(error); } -static int sysfs_get_target_path(struct kernfs_node *parent, - struct kernfs_node *target, char *path) +static int kernfs_get_target_path(struct kernfs_node *parent, + struct kernfs_node *target, char *path) { struct kernfs_node *base, *kn; char *s = path; @@ -103,7 +103,7 @@ static int sysfs_get_target_path(struct kernfs_node *parent, return 0; } -static int sysfs_getlink(struct dentry *dentry, char *path) +static int kernfs_getlink(struct dentry *dentry, char *path) { struct kernfs_node *kn = dentry->d_fsdata; struct kernfs_node *parent = kn->parent; @@ -111,18 +111,18 @@ static int sysfs_getlink(struct dentry *dentry, char *path) int error; mutex_lock(&kernfs_mutex); - error = sysfs_get_target_path(parent, target, path); + error = kernfs_get_target_path(parent, target, path); mutex_unlock(&kernfs_mutex); return error; } -static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *kernfs_iop_follow_link(struct dentry *dentry, struct nameidata *nd) { int error = -ENOMEM; unsigned long page = get_zeroed_page(GFP_KERNEL); if (page) { - error = sysfs_getlink(dentry, (char *) page); + error = kernfs_getlink(dentry, (char *) page); if (error < 0) free_page((unsigned long)page); } @@ -130,8 +130,8 @@ static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) return NULL; } -static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, - void *cookie) +static void kernfs_iop_put_link(struct dentry *dentry, struct nameidata *nd, + void *cookie) { char *page = nd_get_link(nd); if (!IS_ERR(page)) @@ -139,14 +139,14 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, } const struct inode_operations kernfs_symlink_iops = { - .setxattr = sysfs_setxattr, - .removexattr = sysfs_removexattr, - .getxattr = sysfs_getxattr, - .listxattr = sysfs_listxattr, + .setxattr = kernfs_iop_setxattr, + .removexattr = kernfs_iop_removexattr, + .getxattr = kernfs_iop_getxattr, + .listxattr = kernfs_iop_listxattr, .readlink = generic_readlink, - .follow_link = sysfs_follow_link, - .put_link = sysfs_put_link, - .setattr = sysfs_setattr, - .getattr = sysfs_getattr, - .permission = sysfs_permission, + .follow_link = kernfs_iop_follow_link, + .put_link = kernfs_iop_put_link, + .setattr = kernfs_iop_setattr, + .getattr = kernfs_iop_getattr, + .permission = kernfs_iop_permission, }; -- cgit v1.2.3 From ae34372eb8408b3d07e870f1939f99007a730d28 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Jan 2014 08:57:21 -0500 Subject: kernfs: remove KERNFS_REMOVED KERNFS_REMOVED is used to mark half-initialized and dying nodes so that they don't show up in lookups and deny adding new nodes under or renaming it; however, its role overlaps those of deactivation and removal from rbtree. It's necessary to deny addition of new children while removal is in progress; however, this role considerably intersects with deactivation - KERNFS_REMOVED prevents new children while deactivation prevents new file operations. There's no reason to have them separate making things more complex than necessary. KERNFS_REMOVED is also used to decide whether a node is still visible to vfs layer, which is rather redundant as equivalent determination can be made by testing whether the node is on its parent's children rbtree or not. This patch removes KERNFS_REMOVED. * Instead of KERNFS_REMOVED, each node now starts its life deactivated. This means that we now use both atomic_add() and atomic_sub() on KN_DEACTIVATED_BIAS, which is INT_MIN. The compiler generates an overflow warnings when negating INT_MIN as the negation can't be represented as a positive number. Nothing is actually broken but let's bump BIAS by one to avoid the warnings for archs which negates the subtrahend.. * KERNFS_REMOVED tests in add and rename paths are replaced with kernfs_get/put_active() of the target nodes. Due to the way the add path is structured now, active ref handling is done in the callers of kernfs_add_one(). This will be consolidated up later. * kernfs_remove_one() is updated to deactivate instead of setting KERNFS_REMOVED. This removes deactivation from kernfs_deactivate(), which is now renamed to kernfs_drain(). * kernfs_dop_revalidate() now tests RB_EMPTY_NODE(&kn->rb) instead of KERNFS_REMOVED and KERNFS_REMOVED test in kernfs_dir_pos() is dropped. A node which is removed from the children rbtree is not included in the iteration in the first place. This means that a node may be visible through vfs a bit longer - it's now also visible after deactivation until the actual removal. This slightly enlarged window difference doesn't make any difference to the userland. * Sanity check on KERNFS_REMOVED in kernfs_put() is replaced with checks on the active ref. * Some comment style updates in the affected area. v2: Reordered before removal path restructuring. kernfs_active() dropped and kernfs_get/put_active() used instead. RB_EMPTY_NODE() used in the lookup paths. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index a03e26036ef9..b2c106ca3434 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -40,9 +40,13 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, kn->symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ - kernfs_addrm_start(&acxt); - error = kernfs_add_one(&acxt, kn, parent); - kernfs_addrm_finish(&acxt); + error = -ENOENT; + if (kernfs_get_active(parent)) { + kernfs_addrm_start(&acxt); + error = kernfs_add_one(&acxt, kn, parent); + kernfs_addrm_finish(&acxt); + kernfs_put_active(parent); + } if (!error) return kn; -- cgit v1.2.3 From 99177a34110889a8f2c36420c34e3bcc9bfd8a70 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Jan 2014 08:57:24 -0500 Subject: kernfs: remove kernfs_addrm_cxt kernfs_addrm_cxt and the accompanying kernfs_addrm_start/finish() were added because there were operations which should be performed outside kernfs_mutex after adding and removing kernfs_nodes. The necessary operations were recorded in kernfs_addrm_cxt and performed by kernfs_addrm_finish(); however, after the recent changes which relocated deactivation and unmapping so that they're performed directly during removal, the only operation kernfs_addrm_finish() performs is kernfs_put(), which can be moved inside the removal path too. This patch moves the kernfs_put() of the base ref to __kernfs_remove() and remove kernfs_addrm_cxt and kernfs_addrm_start/finish(). * kernfs_add_one() is updated to grab and release the parent's active ref and kernfs_mutex itself. kernfs_get/put_active() and kernfs_addrm_start/finish() invocations around it are removed from all users. * __kernfs_remove() puts an unlinked node directly instead of chaining it to kernfs_addrm_cxt. Its callers are updated to grab and release kernfs_mutex instead of calling kernfs_addrm_start/finish() around it. v2: Updated to fit the v2 restructuring of removal path. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index b2c106ca3434..3a939c263ede 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -27,7 +27,6 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, struct kernfs_node *target) { struct kernfs_node *kn; - struct kernfs_addrm_cxt acxt; int error; kn = kernfs_new_node(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, @@ -40,14 +39,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, kn->symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ - error = -ENOENT; - if (kernfs_get_active(parent)) { - kernfs_addrm_start(&acxt); - error = kernfs_add_one(&acxt, kn, parent); - kernfs_addrm_finish(&acxt); - kernfs_put_active(parent); - } - + error = kernfs_add_one(kn, parent); if (!error) return kn; -- cgit v1.2.3 From 7653fe9d6cddc3fc5e4220608079006d8ac0054c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 Jan 2014 14:20:56 -0800 Subject: Revert "kernfs: remove kernfs_addrm_cxt" This reverts commit 99177a34110889a8f2c36420c34e3bcc9bfd8a70. Tejun writes: I'm sorry but can you please revert the whole series? get_active() waiting while a node is deactivated has potential to lead to deadlock and that deactivate/reactivate interface is something fundamentally flawed and that cgroup will have to work with the remove_self() like everybody else. IOW, I think the first posting was correct. Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 3a939c263ede..b2c106ca3434 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -27,6 +27,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, struct kernfs_node *target) { struct kernfs_node *kn; + struct kernfs_addrm_cxt acxt; int error; kn = kernfs_new_node(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, @@ -39,7 +40,14 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, kn->symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ - error = kernfs_add_one(kn, parent); + error = -ENOENT; + if (kernfs_get_active(parent)) { + kernfs_addrm_start(&acxt); + error = kernfs_add_one(&acxt, kn, parent); + kernfs_addrm_finish(&acxt); + kernfs_put_active(parent); + } + if (!error) return kn; -- cgit v1.2.3 From 798c75a0d44cdbd6e3d82a6a676e6de38525b3bb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 Jan 2014 14:36:03 -0800 Subject: Revert "kernfs: remove KERNFS_REMOVED" This reverts commit ae34372eb8408b3d07e870f1939f99007a730d28. Tejun writes: I'm sorry but can you please revert the whole series? get_active() waiting while a node is deactivated has potential to lead to deadlock and that deactivate/reactivate interface is something fundamentally flawed and that cgroup will have to work with the remove_self() like everybody else. IOW, I think the first posting was correct. Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index b2c106ca3434..a03e26036ef9 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -40,13 +40,9 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, kn->symlink.target_kn = target; kernfs_get(target); /* ref owned by symlink */ - error = -ENOENT; - if (kernfs_get_active(parent)) { - kernfs_addrm_start(&acxt); - error = kernfs_add_one(&acxt, kn, parent); - kernfs_addrm_finish(&acxt); - kernfs_put_active(parent); - } + kernfs_addrm_start(&acxt); + error = kernfs_add_one(&acxt, kn, parent); + kernfs_addrm_finish(&acxt); if (!error) return kn; -- cgit v1.2.3 From db4aad209bc9aefd91f0a9aeb9e37364088b39ad Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 17 Jan 2014 09:58:25 -0500 Subject: kernfs: associate a new kernfs_node with its parent on creation Once created, a kernfs_node is always destroyed by kernfs_put(). Since ba7443bc656e ("sysfs, kernfs: implement kernfs_create/destroy_root()"), kernfs_put() depends on kernfs_root() to locate the ino_ida. kernfs_root() in turn depends on kernfs_node->parent being set for !dir nodes. This means that kernfs_put() of a !dir node requires its ->parent to be initialized. This leads to oops when a newly created !dir node is destroyed without going through kernfs_add_one() or after failing kernfs_add_one() before ->parent is set. kernfs_root() invoked from kernfs_put() will try to dereference NULL parent. Fix it by moving parent association to kernfs_new_node() from kernfs_add_one(). kernfs_new_node() now takes @parent instead of @root and determines the root from the parent and also sets the new node's parent properly. @parent parameter is removed from kernfs_add_one(). As there's no parent when creating the root node, __kernfs_new_node() which takes @root as before and doesn't set the parent is used in that case. This ensures that a kernfs_node in any stage in its life has its parent associated and thus can be put. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/symlink.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs/kernfs/symlink.c') diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index a03e26036ef9..4d457055acb9 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -30,8 +30,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, struct kernfs_addrm_cxt acxt; int error; - kn = kernfs_new_node(kernfs_root(parent), name, S_IFLNK|S_IRWXUGO, - KERNFS_LINK); + kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK); if (!kn) return ERR_PTR(-ENOMEM); @@ -41,7 +40,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, kernfs_get(target); /* ref owned by symlink */ kernfs_addrm_start(&acxt); - error = kernfs_add_one(&acxt, kn, parent); + error = kernfs_add_one(&acxt, kn); kernfs_addrm_finish(&acxt); if (!error) -- cgit v1.2.3