From ae6621b0716852146e4655fef7f74a181faa6c81 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:31 -0500 Subject: sysfs, kernfs: move internal decls to fs/kernfs/kernfs-internal.h Move data structure, constant and basic accessor declarations from fs/sysfs/sysfs.h to fs/kernfs/kernfs-internal.h. The two files currently include each other. Once kernfs / sysfs separation is complete, the cross inclusions will be removed. Inclusion protectors are added to fs/sysfs/sysfs.h to allow cross-inclusion. This patch doesn't introduce any functional changes. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 115 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 fs/kernfs/kernfs-internal.h (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h new file mode 100644 index 000000000000..5a2c3a17d7cb --- /dev/null +++ b/fs/kernfs/kernfs-internal.h @@ -0,0 +1,115 @@ +/* + * fs/kernfs/kernfs-internal.h - kernfs internal header file + * + * 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. + */ + +#ifndef __KERNFS_INTERNAL_H +#define __KERNFS_INTERNAL_H + +#include +#include +#include + +#include + +struct sysfs_open_dirent; + +/* type-specific structures for sysfs_dirent->s_* union members */ +struct sysfs_elem_dir { + unsigned long subdirs; + /* children rbtree starts here and goes through sd->s_rb */ + struct rb_root children; +}; + +struct sysfs_elem_symlink { + struct sysfs_dirent *target_sd; +}; + +struct sysfs_elem_attr { + const struct kernfs_ops *ops; + struct sysfs_open_dirent *open; + loff_t size; +}; + +struct sysfs_inode_attrs { + struct iattr ia_iattr; + void *ia_secdata; + u32 ia_secdata_len; +}; + +/* + * sysfs_dirent - the building block of sysfs hierarchy. Each and + * every sysfs node is represented by single sysfs_dirent. + * + * As long as s_count reference is held, the sysfs_dirent itself is + * accessible. Dereferencing s_elem or any other outer entity + * requires s_active reference. + */ +struct sysfs_dirent { + atomic_t s_count; + atomic_t s_active; +#ifdef CONFIG_DEBUG_LOCK_ALLOC + struct lockdep_map dep_map; +#endif + struct sysfs_dirent *s_parent; + const char *s_name; + + struct rb_node s_rb; + + union { + struct completion *completion; + struct sysfs_dirent *removed_list; + } u; + + const void *s_ns; /* namespace tag */ + unsigned int s_hash; /* ns + name hash */ + union { + struct sysfs_elem_dir s_dir; + struct sysfs_elem_symlink s_symlink; + struct sysfs_elem_attr s_attr; + }; + + void *priv; + + unsigned short s_flags; + umode_t s_mode; + unsigned int s_ino; + struct sysfs_inode_attrs *s_iattr; +}; + +#define SD_DEACTIVATED_BIAS INT_MIN + +#define SYSFS_TYPE_MASK 0x000f +#define SYSFS_DIR 0x0001 +#define SYSFS_KOBJ_ATTR 0x0002 +#define SYSFS_KOBJ_LINK 0x0004 +#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) +#define SYSFS_ACTIVE_REF SYSFS_KOBJ_ATTR + +#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK +#define SYSFS_FLAG_REMOVED 0x0010 +#define SYSFS_FLAG_NS 0x0020 +#define SYSFS_FLAG_HAS_SEQ_SHOW 0x0040 +#define SYSFS_FLAG_HAS_MMAP 0x0080 +#define SYSFS_FLAG_LOCKDEP 0x0100 + +static inline unsigned int sysfs_type(struct sysfs_dirent *sd) +{ + return sd->s_flags & SYSFS_TYPE_MASK; +} + +/* + * Context structure to be used while adding/removing nodes. + */ +struct sysfs_addrm_cxt { + struct sysfs_dirent *removed; +}; + +#include "../sysfs/sysfs.h" + +#endif /* __KERNFS_INTERNAL_H */ -- cgit v1.2.3 From ffed24e22845a3da0ae01095ae3f11c8d16e889d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:32 -0500 Subject: sysfs, kernfs: move inode code to fs/kernfs/inode.c There's nothing sysfs-specific in fs/sysfs/inode.c. Move everything in it to fs/kernfs/inode.c. 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/kernfs-internal.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 5a2c3a17d7cb..933ac8d5d07a 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -112,4 +112,17 @@ struct sysfs_addrm_cxt { #include "../sysfs/sysfs.h" +/* + * inode.c + */ +struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); +void sysfs_evict_inode(struct inode *inode); +int sysfs_permission(struct inode *inode, int mask); +int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); +int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat); +int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags); +int sysfs_inode_init(void); + #endif /* __KERNFS_INTERNAL_H */ -- cgit v1.2.3 From fd7b9f7b9776b11df629e9dd3865320bf57ce588 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:33 -0500 Subject: sysfs, kernfs: move dir core code to fs/kernfs/dir.c Move core dir code to fs/kernfs/dir.c. fs/sysfs/dir.c now only contains sysfs_warn_dup() and 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. v2: sysfs_symlink_target_lock was mistakenly relocated to kernfs. It should remain with sysfs. Fixed. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 933ac8d5d07a..31f0dbe1881b 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -125,4 +126,20 @@ int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int sysfs_inode_init(void); +/* + * dir.c + */ +extern struct mutex sysfs_mutex; +extern const struct dentry_operations sysfs_dentry_ops; +extern const struct file_operations sysfs_dir_operations; +extern const struct inode_operations sysfs_dir_inode_operations; + +struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); +void sysfs_put_active(struct sysfs_dirent *sd); +void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt); +int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, + struct sysfs_dirent *parent_sd); +void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); +struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); + #endif /* __KERNFS_INTERNAL_H */ -- cgit v1.2.3 From 414985ae23c031efbd6d16d484dea8b5de28b8f7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:34 -0500 Subject: sysfs, kernfs: move file core code to fs/kernfs/file.c Move core file code to fs/kernfs/file.c. fs/sysfs/file.c now contains sysfs kernfs_ops callbacks, sysfs wrappers around kernfs interfaces, and sysfs_schedule_callback(). The respective declarations in fs/sysfs/sysfs.h are moved to fs/kernfs/kernfs-internal.h. This is pure relocation. v2: Refreshed on top of the v2 of "sysfs, kernfs: prepare read path for kernfs". v3: Refreshed on top of the v3 of "sysfs, kernfs: prepare read path for kernfs". Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 31f0dbe1881b..38e3a163e5ad 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -142,4 +142,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); +/* + * file.c + */ +extern const struct file_operations kernfs_file_operations; + +void sysfs_unmap_bin_file(struct sysfs_dirent *sd); + #endif /* __KERNFS_INTERNAL_H */ -- 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/kernfs-internal.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 38e3a163e5ad..62ae35f997f7 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -149,4 +149,9 @@ extern const struct file_operations kernfs_file_operations; void sysfs_unmap_bin_file(struct sysfs_dirent *sd); +/* + * symlink.c + */ +extern const struct inode_operations sysfs_symlink_inode_operations; + #endif /* __KERNFS_INTERNAL_H */ -- cgit v1.2.3 From ba7443bc656e5236c316b2acacc8b551f872910f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:40 -0500 Subject: sysfs, kernfs: implement kernfs_create/destroy_root() There currently is single kernfs hierarchy in the whole system which is used for sysfs. kernfs needs to support multiple hierarchies to allow other users. This patch introduces struct kernfs_root which serves as the root of each kernfs hierarchy and implements kernfs_create/destroy_root(). * Each kernfs_root is associated with a root sd (sysfs_dentry). The root is freed when the root sd is released and kernfs_destory_root() simply invokes kernfs_remove() on the root sd. sysfs_remove_one() is updated to handle release of the root sd. Note that ps_iattr update in sysfs_remove_one() is trivially updated for readability. * Root sd's are now dynamically allocated using sysfs_new_dirent(). Update sysfs_alloc_ino() so that it gives out ino from 1 so that the root sd still gets ino 1. * While kernfs currently only points to the root sd, it'll soon grow fields which are specific to each hierarchy. As determining a given sd's root will be necessary, sd->s_dir.root is added. This backlink fits better as a separate field in sd; however, sd->s_dir is inside union with space to spare, so use it to save space and provide kernfs_root() accessor to determine the root sd. * As hierarchies may be destroyed now, each mount needs to hold onto the hierarchy it's attached to. Update sysfs_fill_super() and sysfs_kill_sb() so that they get and put the kernfs_root respectively. * sysfs_root is replaced with kernfs_root which is dynamically created by invoking kernfs_create_root() from sysfs_init(). This patch doesn't introduce any visible behavior changes. v2: kernfs_create_root() forgot to set @sd->priv. Fixed. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 62ae35f997f7..7dfe06278350 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -25,6 +25,12 @@ struct sysfs_elem_dir { unsigned long subdirs; /* children rbtree starts here and goes through sd->s_rb */ struct rb_root children; + + /* + * The kernfs hierarchy this directory belongs to. This fits + * better directly in sysfs_dirent but is here to save space. + */ + struct kernfs_root *root; }; struct sysfs_elem_symlink { @@ -104,6 +110,20 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd) return sd->s_flags & SYSFS_TYPE_MASK; } +/** + * kernfs_root - find out the kernfs_root a sysfs_dirent belongs to + * @sd: sysfs_dirent of interest + * + * Return the kernfs_root @sd belongs to. + */ +static inline struct kernfs_root *kernfs_root(struct sysfs_dirent *sd) +{ + /* if parent exists, it's always a dir; otherwise, @sd is a dir */ + if (sd->s_parent) + sd = sd->s_parent; + return sd->s_dir.root; +} + /* * Context structure to be used while adding/removing nodes. */ -- 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/kernfs-internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 7dfe06278350..466943d576f1 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -160,7 +160,8 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt); int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, struct sysfs_dirent *parent_sd); void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); -struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type); +struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root, + const char *name, umode_t mode, int type); /* * file.c -- cgit v1.2.3 From 4b93dc9b1c684d0587fe44d36bbfdf45bd3bea9d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:43 -0500 Subject: sysfs, kernfs: prepare mount path for kernfs We're in the process of separating out core sysfs functionality into kernfs which will deal with sysfs_dirents directly. This patch rearranges mount path so that the kernfs and sysfs parts are separate. * As sysfs_super_info won't be visible outside kernfs proper, kernfs_super_ns() is added to allow kernfs users to access a super_block's namespace tag. * Generic mount operation is separated out into kernfs_mount_ns(). sysfs_mount() now just performs sysfs-specific permission check, acquires namespace tag, and invokes kernfs_mount_ns(). * Generic superblock release is separated out into kernfs_kill_sb() which can be used directly as file_system_type->kill_sb(). As sysfs needs to put the namespace tag, sysfs_kill_sb() wraps kernfs_kill_sb() with ns tag put. * sysfs_dir_cachep init and sysfs_inode_init() are separated out into kernfs_init(). kernfs_init() uses only small amount of memory and trying to handle and propagate kernfs_init() failure doesn't make much sense. Use SLAB_PANIC for sysfs_dir_cachep and make sysfs_inode_init() panic on failure. After this change, kernfs_init() should be called before sysfs_init(), fs/namespace.c::mnt_init() modified accordingly. Signed-off-by: Tejun Heo Cc: linux-fsdevel@vger.kernel.org Cc: Christoph Hellwig Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 466943d576f1..0d949885389d 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -144,7 +144,7 @@ int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); -int sysfs_inode_init(void); +void sysfs_inode_init(void); /* * dir.c -- cgit v1.2.3 From fa736a951e456b996a76826ba78ff974414c3b55 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:44 -0500 Subject: sysfs, kernfs: move mount core code to fs/kernfs/mount.c Move core mount code to fs/kernfs/mount.c. 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/kernfs-internal.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 0d949885389d..ced0d6dadc7d 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -133,6 +133,28 @@ struct sysfs_addrm_cxt { #include "../sysfs/sysfs.h" +/* + * mount.c + */ +struct sysfs_super_info { + /* + * The root associated with this super_block. Each super_block is + * identified by the root and ns it's associated with. + */ + struct kernfs_root *root; + + /* + * Each sb is associated with one namespace tag, currently the network + * namespace of the task which mounted this sysfs instance. If multiple + * tags become necessary, make the following an array and compare + * sysfs_dirent tag against every entry. + */ + const void *ns; +}; +#define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) + +extern struct kmem_cache *sysfs_dir_cachep; + /* * inode.c */ -- cgit v1.2.3 From cf9e5a73aaff0204801dd19cb4bd91d32f32026a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 29 Nov 2013 17:18:32 -0500 Subject: sysfs, kernfs: make sysfs_dirent definition public sysfs_dirent includes some information which should be available to kernfs users - the type, flags, name and parent pointer. This patch moves sysfs_dirent definition from kernfs/kernfs-internal.h to include/linux/kernfs.h so that kernfs users can access them. The type part of flags is exported as enum kernfs_node_type, the flags kernfs_node_flag, sysfs_type() and kernfs_enable_ns() are moved to include/linux/kernfs.h and the former is updated to return the enum type. sysfs_dirent->s_parent and ->s_name are marked explicitly as public. This patch doesn't introduce any functional changes. v2: Flags exported too and kernfs_enable_ns() definition moved. v3: While moving kernfs_enable_ns() to include/linux/kernfs.h, v1 and v2 put the definition outside CONFIG_SYSFS replacing the dummy implementation with the actual implementation too. Unfortunately, this can lead to oops when !CONFIG_SYSFS because kernfs_enable_ns() may be called on a NULL @sd and now tries to dereference @sd instead of not doing anything. This issue was reported by Yuanhan Liu. Signed-off-by: Tejun Heo Reported-by: Yuanhan Liu Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 85 +-------------------------------------------- 1 file changed, 1 insertion(+), 84 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index ced0d6dadc7d..f33a7844e8fd 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -13,102 +13,19 @@ #include #include -#include #include #include -struct sysfs_open_dirent; - -/* type-specific structures for sysfs_dirent->s_* union members */ -struct sysfs_elem_dir { - unsigned long subdirs; - /* children rbtree starts here and goes through sd->s_rb */ - struct rb_root children; - - /* - * The kernfs hierarchy this directory belongs to. This fits - * better directly in sysfs_dirent but is here to save space. - */ - struct kernfs_root *root; -}; - -struct sysfs_elem_symlink { - struct sysfs_dirent *target_sd; -}; - -struct sysfs_elem_attr { - const struct kernfs_ops *ops; - struct sysfs_open_dirent *open; - loff_t size; -}; - struct sysfs_inode_attrs { struct iattr ia_iattr; void *ia_secdata; u32 ia_secdata_len; }; -/* - * sysfs_dirent - the building block of sysfs hierarchy. Each and - * every sysfs node is represented by single sysfs_dirent. - * - * As long as s_count reference is held, the sysfs_dirent itself is - * accessible. Dereferencing s_elem or any other outer entity - * requires s_active reference. - */ -struct sysfs_dirent { - atomic_t s_count; - atomic_t s_active; -#ifdef CONFIG_DEBUG_LOCK_ALLOC - struct lockdep_map dep_map; -#endif - struct sysfs_dirent *s_parent; - const char *s_name; - - struct rb_node s_rb; - - union { - struct completion *completion; - struct sysfs_dirent *removed_list; - } u; - - const void *s_ns; /* namespace tag */ - unsigned int s_hash; /* ns + name hash */ - union { - struct sysfs_elem_dir s_dir; - struct sysfs_elem_symlink s_symlink; - struct sysfs_elem_attr s_attr; - }; - - void *priv; - - unsigned short s_flags; - umode_t s_mode; - unsigned int s_ino; - struct sysfs_inode_attrs *s_iattr; -}; - #define SD_DEACTIVATED_BIAS INT_MIN -#define SYSFS_TYPE_MASK 0x000f -#define SYSFS_DIR 0x0001 -#define SYSFS_KOBJ_ATTR 0x0002 -#define SYSFS_KOBJ_LINK 0x0004 -#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) -#define SYSFS_ACTIVE_REF SYSFS_KOBJ_ATTR - -#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK -#define SYSFS_FLAG_REMOVED 0x0010 -#define SYSFS_FLAG_NS 0x0020 -#define SYSFS_FLAG_HAS_SEQ_SHOW 0x0040 -#define SYSFS_FLAG_HAS_MMAP 0x0080 -#define SYSFS_FLAG_LOCKDEP 0x0100 - -static inline unsigned int sysfs_type(struct sysfs_dirent *sd) -{ - return sd->s_flags & SYSFS_TYPE_MASK; -} +/* SYSFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ /** * kernfs_root - find out the kernfs_root a sysfs_dirent belongs to -- cgit v1.2.3 From bfc5c17337145955b31c22b96a6e07def048471b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 28 Nov 2013 14:54:47 -0500 Subject: sysfs, kernfs: remove cross inclusions of internal headers fs/kernfs/kernfs-internal.h needed to include fs/sysfs/sysfs.h because part of kernfs core implementation was living in sysfs. fs/sysfs/sysfs.h needed to include fs/kernfs/kernfs-internal.h because include/linux/kernfs.h didn't expose enough interface. The separation is complete and neither is true anymore. Remove the cross inclusion and make sysfs a proper user of kernfs. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index f33a7844e8fd..d1ff591c5cf3 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -48,8 +48,6 @@ struct sysfs_addrm_cxt { struct sysfs_dirent *removed; }; -#include "../sysfs/sysfs.h" - /* * mount.c */ -- cgit v1.2.3 From 9a8049affd55a2c857a89faece27b878416fbf91 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 23 Nov 2013 17:40:01 -0500 Subject: kernfs: update sysfs_init_inode_attrs() sysfs_init_inode_attrs() is a bit clumsy to use requiring the caller to check whether @sd->s_iattr is already set or not. Rename it to sysfs_inode_attrs(), update it to check whether @sd->s_iattr is already initialized before trying to initialize it and return @sd->s_iattr. This simplifies the callers. While at it, * Rename struct sysfs_inode_attrs pointer variables to "attrs". As kernfs no longer deals with "struct attribute", this isn't confusing and makes it easier to distinguish from struct iattr pointers. * A new field will be added to sysfs_inode_attrs. Reindent in preparation. This patch doesn't introduce any behavior changes. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index d1ff591c5cf3..f25b3548bcca 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -18,9 +18,9 @@ #include struct sysfs_inode_attrs { - struct iattr ia_iattr; - void *ia_secdata; - u32 ia_secdata_len; + struct iattr ia_iattr; + void *ia_secdata; + u32 ia_secdata_len; }; #define SD_DEACTIVATED_BIAS INT_MIN -- 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/kernfs-internal.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index f25b3548bcca..910e485b7333 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -21,6 +22,8 @@ struct sysfs_inode_attrs { struct iattr ia_iattr; void *ia_secdata; u32 ia_secdata_len; + + struct simple_xattrs xattrs; }; #define SD_DEACTIVATED_BIAS INT_MIN @@ -81,6 +84,10 @@ int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); +int sysfs_removexattr(struct dentry *dentry, const char *name); +ssize_t sysfs_getxattr(struct dentry *dentry, const char *name, void *buf, + size_t size); +ssize_t sysfs_listxattr(struct dentry *dentry, char *buf, size_t size); void sysfs_inode_init(void); /* -- 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/kernfs-internal.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 910e485b7333..b7ea76c6fb33 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -31,24 +31,24 @@ struct sysfs_inode_attrs { /* SYSFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ /** - * kernfs_root - find out the kernfs_root a sysfs_dirent belongs to - * @sd: sysfs_dirent of interest + * kernfs_root - find out the kernfs_root a kernfs_node belongs to + * @kn: kernfs_node of interest * - * Return the kernfs_root @sd belongs to. + * Return the kernfs_root @kn belongs to. */ -static inline struct kernfs_root *kernfs_root(struct sysfs_dirent *sd) +static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) { /* if parent exists, it's always a dir; otherwise, @sd is a dir */ - if (sd->s_parent) - sd = sd->s_parent; - return sd->s_dir.root; + if (kn->s_parent) + kn = kn->s_parent; + return kn->s_dir.root; } /* * Context structure to be used while adding/removing nodes. */ struct sysfs_addrm_cxt { - struct sysfs_dirent *removed; + struct kernfs_node *removed; }; /* @@ -62,10 +62,10 @@ struct sysfs_super_info { struct kernfs_root *root; /* - * Each sb is associated with one namespace tag, currently the network - * namespace of the task which mounted this sysfs instance. If multiple - * tags become necessary, make the following an array and compare - * sysfs_dirent tag against every entry. + * Each sb is associated with one namespace tag, currently the + * network namespace of the task which mounted this sysfs instance. + * If multiple tags become necessary, make the following an array + * and compare kernfs_node tag against every entry. */ const void *ns; }; @@ -76,7 +76,7 @@ extern struct kmem_cache *sysfs_dir_cachep; /* * inode.c */ -struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd); +struct inode *sysfs_get_inode(struct super_block *sb, struct kernfs_node *kn); void sysfs_evict_inode(struct inode *inode); int sysfs_permission(struct inode *inode, int mask); int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); @@ -98,21 +98,21 @@ extern const struct dentry_operations sysfs_dentry_ops; extern const struct file_operations sysfs_dir_operations; extern const struct inode_operations sysfs_dir_inode_operations; -struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); -void sysfs_put_active(struct sysfs_dirent *sd); +struct kernfs_node *sysfs_get_active(struct kernfs_node *kn); +void sysfs_put_active(struct kernfs_node *kn); void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt); -int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, - struct sysfs_dirent *parent_sd); +int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct kernfs_node *kn, + struct kernfs_node *parent); void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); -struct sysfs_dirent *sysfs_new_dirent(struct kernfs_root *root, - const char *name, umode_t mode, int type); +struct kernfs_node *sysfs_new_dirent(struct kernfs_root *root, + const char *name, umode_t mode, int type); /* * file.c */ extern const struct file_operations kernfs_file_operations; -void sysfs_unmap_bin_file(struct sysfs_dirent *sd); +void sysfs_unmap_bin_file(struct kernfs_node *kn); /* * symlink.c -- 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/kernfs-internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index b7ea76c6fb33..2dbb1cb95e7f 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -39,9 +39,9 @@ struct sysfs_inode_attrs { static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) { /* if parent exists, it's always a dir; otherwise, @sd is a dir */ - if (kn->s_parent) - kn = kn->s_parent; - return kn->s_dir.root; + if (kn->parent) + kn = kn->parent; + return kn->dir.root; } /* -- 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/kernfs-internal.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 2dbb1cb95e7f..573f66988643 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -18,7 +18,7 @@ #include -struct sysfs_inode_attrs { +struct kernfs_iattrs { struct iattr ia_iattr; void *ia_secdata; u32 ia_secdata_len; @@ -47,14 +47,14 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) /* * Context structure to be used while adding/removing nodes. */ -struct sysfs_addrm_cxt { +struct kernfs_addrm_cxt { struct kernfs_node *removed; }; /* * mount.c */ -struct sysfs_super_info { +struct kernfs_super_info { /* * The root associated with this super_block. Each super_block is * identified by the root and ns it's associated with. @@ -63,13 +63,13 @@ struct sysfs_super_info { /* * Each sb is associated with one namespace tag, currently the - * network namespace of the task which mounted this sysfs instance. - * If multiple tags become necessary, make the following an array - * and compare kernfs_node tag against every entry. + * network namespace of the task which mounted this kernfs + * instance. If multiple tags become necessary, make the following + * an array and compare kernfs_node tag against every entry. */ const void *ns; }; -#define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) +#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info)) extern struct kmem_cache *sysfs_dir_cachep; @@ -100,10 +100,10 @@ extern const struct inode_operations sysfs_dir_inode_operations; struct kernfs_node *sysfs_get_active(struct kernfs_node *kn); void sysfs_put_active(struct kernfs_node *kn); -void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt); -int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct kernfs_node *kn, +void sysfs_addrm_start(struct kernfs_addrm_cxt *acxt); +int sysfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, struct kernfs_node *parent); -void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); +void sysfs_addrm_finish(struct kernfs_addrm_cxt *acxt); struct kernfs_node *sysfs_new_dirent(struct kernfs_root *root, const char *name, umode_t mode, int type); -- 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/kernfs-internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 573f66988643..c4bf5bf72f78 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -26,9 +26,9 @@ struct kernfs_iattrs { struct simple_xattrs xattrs; }; -#define SD_DEACTIVATED_BIAS INT_MIN +#define KN_DEACTIVATED_BIAS INT_MIN -/* SYSFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ +/* KERNFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ /** * kernfs_root - find out the kernfs_root a kernfs_node belongs to -- 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/kernfs-internal.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index c4bf5bf72f78..e62e8ec15d65 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -71,7 +71,7 @@ struct kernfs_super_info { }; #define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info)) -extern struct kmem_cache *sysfs_dir_cachep; +extern struct kmem_cache *kernfs_node_cache; /* * inode.c @@ -93,10 +93,10 @@ void sysfs_inode_init(void); /* * dir.c */ -extern struct mutex sysfs_mutex; -extern const struct dentry_operations sysfs_dentry_ops; -extern const struct file_operations sysfs_dir_operations; -extern const struct inode_operations sysfs_dir_inode_operations; +extern struct mutex kernfs_mutex; +extern const struct dentry_operations kernfs_dops; +extern const struct file_operations kernfs_dir_fops; +extern const struct inode_operations kernfs_dir_iops; struct kernfs_node *sysfs_get_active(struct kernfs_node *kn); void sysfs_put_active(struct kernfs_node *kn); @@ -110,13 +110,13 @@ struct kernfs_node *sysfs_new_dirent(struct kernfs_root *root, /* * file.c */ -extern const struct file_operations kernfs_file_operations; +extern const struct file_operations kernfs_file_fops; void sysfs_unmap_bin_file(struct kernfs_node *kn); /* * symlink.c */ -extern const struct inode_operations sysfs_symlink_inode_operations; +extern const struct inode_operations kernfs_symlink_iops; #endif /* __KERNFS_INTERNAL_H */ -- 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/kernfs-internal.h | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index e62e8ec15d65..a4ff491fd59c 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -76,19 +76,19 @@ extern struct kmem_cache *kernfs_node_cache; /* * inode.c */ -struct inode *sysfs_get_inode(struct super_block *sb, struct kernfs_node *kn); -void sysfs_evict_inode(struct inode *inode); -int sysfs_permission(struct inode *inode, int mask); -int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); -int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat); -int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags); -int sysfs_removexattr(struct dentry *dentry, const char *name); -ssize_t sysfs_getxattr(struct dentry *dentry, const char *name, void *buf, - size_t size); -ssize_t sysfs_listxattr(struct dentry *dentry, char *buf, size_t size); -void sysfs_inode_init(void); +struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn); +void kernfs_evict_inode(struct inode *inode); +int kernfs_iop_permission(struct inode *inode, int mask); +int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr); +int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat); +int kernfs_iop_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags); +int kernfs_iop_removexattr(struct dentry *dentry, const char *name); +ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf, + size_t size); +ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); +void kernfs_inode_init(void); /* * dir.c @@ -98,21 +98,21 @@ extern const struct dentry_operations kernfs_dops; extern const struct file_operations kernfs_dir_fops; extern const struct inode_operations kernfs_dir_iops; -struct kernfs_node *sysfs_get_active(struct kernfs_node *kn); -void sysfs_put_active(struct kernfs_node *kn); -void sysfs_addrm_start(struct kernfs_addrm_cxt *acxt); -int sysfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, - struct kernfs_node *parent); -void sysfs_addrm_finish(struct kernfs_addrm_cxt *acxt); -struct kernfs_node *sysfs_new_dirent(struct kernfs_root *root, - const char *name, umode_t mode, int type); +struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); +void kernfs_put_active(struct kernfs_node *kn); +void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt); +int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, + struct kernfs_node *parent); +void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); +struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, + umode_t mode, int type); /* * file.c */ extern const struct file_operations kernfs_file_fops; -void sysfs_unmap_bin_file(struct kernfs_node *kn); +void kernfs_unmap_bin_file(struct kernfs_node *kn); /* * symlink.c -- cgit v1.2.3 From 2063d608f5110d120db60e896ec2c70c95bb7978 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Dec 2013 16:02:57 -0500 Subject: kernfs: mark static names with KERNFS_STATIC_NAME Because sysfs used struct attribute which are supposed to stay constant, sysfs didn't copy names when creating regular files. The specified string for name was supposed to stay constant. Such distinction isn't inherent for kernfs. kernfs_create_file[_ns]() should be able to take the same @name as kernfs_create_dir[_ns]() As there can be huge number of sysfs attributes, we still want to be able to use static names for sysfs attributes. This patch renames kernfs_create_file_ns_key() to __kernfs_create_file() and adds @name_is_static parameter so that the caller can explicitly indicate that @name can be used without copying. kernfs is updated to use KERNFS_STATIC_NAME to distinguish static and copied names. This patch doesn't introduce any behavior changes. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index a4ff491fd59c..c6ba5bc37a98 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -105,7 +105,7 @@ int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, struct kernfs_node *parent); void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, - umode_t mode, int type); + umode_t mode, unsigned flags); /* * file.c -- 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/kernfs-internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index c6ba5bc37a98..57a93f4d645c 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -26,7 +26,8 @@ struct kernfs_iattrs { struct simple_xattrs xattrs; }; -#define KN_DEACTIVATED_BIAS INT_MIN +/* +1 to avoid triggering overflow warning when negating it */ +#define KN_DEACTIVATED_BIAS (INT_MIN + 1) /* KERNFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ -- cgit v1.2.3 From f601f9a2bf7dc1f7ee18feece4c4e2fc6845d6c4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Jan 2014 08:57:23 -0500 Subject: kernfs: invoke kernfs_unmap_bin_file() directly from __kernfs_remove() kernfs_unmap_bin_file() is supposed to unmap all memory mappings of the target file before kernfs_remove() finishes; however, it currently is being called from kernfs_addrm_finish() and has the same race problem as the original implementation of deactivation when there are multiple removers - only the remover which snatches the node to its addrm_cxt->removed list is guaranteed to wait for its completion before returning. It can be fixed by moving kernfs_unmap_bin_file() invocation from kernfs_addrm_finish() to __kernfs_remove(). The function may be called multiple times but that shouldn't do any harm. We end up dropping kernfs_mutex in the removal loop and the node may be removed inbetween by someone else. kernfs_unlink_sibling() is updated to test whether the node has already been removed and return accordingly. __kernfs_remove() in turn performs post-unlinking cleanup only if it actually unlinked the node. KERNFS_HAS_MMAP test is moved out of the unmap function into __kernfs_remove() so that we don't unlock kernfs_mutex unnecessarily. While at it, drop the now meaningless "bin" qualifier from the function name. v2: Rewritten to fit the v2 restructuring of removal path. HAS_MMAP test relocated. Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/kernfs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 57a93f4d645c..e9ec38c86074 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -113,7 +113,7 @@ struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, */ extern const struct file_operations kernfs_file_fops; -void kernfs_unmap_bin_file(struct kernfs_node *kn); +void kernfs_unmap_file(struct kernfs_node *kn); /* * symlink.c -- 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/kernfs-internal.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index e9ec38c86074..4bc57848076c 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -45,13 +45,6 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) return kn->dir.root; } -/* - * Context structure to be used while adding/removing nodes. - */ -struct kernfs_addrm_cxt { - struct kernfs_node *removed; -}; - /* * mount.c */ @@ -101,10 +94,7 @@ extern const struct inode_operations kernfs_dir_iops; struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); void kernfs_put_active(struct kernfs_node *kn); -void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt); -int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, - struct kernfs_node *parent); -void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); +int kernfs_add_one(struct kernfs_node *kn, struct kernfs_node *parent); struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, umode_t mode, unsigned flags); -- 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/kernfs-internal.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 4bc57848076c..e9ec38c86074 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -45,6 +45,13 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) return kn->dir.root; } +/* + * Context structure to be used while adding/removing nodes. + */ +struct kernfs_addrm_cxt { + struct kernfs_node *removed; +}; + /* * mount.c */ @@ -94,7 +101,10 @@ extern const struct inode_operations kernfs_dir_iops; struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); void kernfs_put_active(struct kernfs_node *kn); -int kernfs_add_one(struct kernfs_node *kn, struct kernfs_node *parent); +void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt); +int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, + struct kernfs_node *parent); +void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, umode_t mode, unsigned flags); -- cgit v1.2.3 From 55f6e30d0a6a8975cc0831e8a4a3715b815b6a2f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 Jan 2014 14:27:16 -0800 Subject: Revert "kernfs: invoke kernfs_unmap_bin_file() directly from __kernfs_remove()" This reverts commit f601f9a2bf7dc1f7ee18feece4c4e2fc6845d6c4. 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/kernfs-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index e9ec38c86074..57a93f4d645c 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -113,7 +113,7 @@ struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, */ extern const struct file_operations kernfs_file_fops; -void kernfs_unmap_file(struct kernfs_node *kn); +void kernfs_unmap_bin_file(struct kernfs_node *kn); /* * symlink.c -- 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/kernfs-internal.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 57a93f4d645c..c6ba5bc37a98 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -26,8 +26,7 @@ struct kernfs_iattrs { struct simple_xattrs xattrs; }; -/* +1 to avoid triggering overflow warning when negating it */ -#define KN_DEACTIVATED_BIAS (INT_MIN + 1) +#define KN_DEACTIVATED_BIAS INT_MIN /* KERNFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ -- 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/kernfs-internal.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/kernfs/kernfs-internal.h') diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index c6ba5bc37a98..eb536b76374a 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -101,11 +101,11 @@ extern const struct inode_operations kernfs_dir_iops; struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); void kernfs_put_active(struct kernfs_node *kn); void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt); -int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn, - struct kernfs_node *parent); +int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn); void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); -struct kernfs_node *kernfs_new_node(struct kernfs_root *root, const char *name, - umode_t mode, unsigned flags); +struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, + const char *name, umode_t mode, + unsigned flags); /* * file.c -- cgit v1.2.3