From 58292cbe6669d74498a5f08db13e57cb3bcfb81d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 22:29:04 -0400 Subject: sysfs: make attr namespace interface less convoluted sysfs ns (namespace) implementation became more convoluted than necessary while trying to hide ns information from visible interface. The relatively recent attr ns support is a good example. * attr ns tag is determined by sysfs_ops->namespace() callback while dir tag is determined by kobj_type->namespace(). The placement is arbitrary. * Instead of performing operations with explicit ns tag, the namespace callback is routed through sysfs_attr_ns(), sysfs_ops->namespace(), class_attr_namespace(), class_attr->namespace(). It's not simpler in any sense. The only thing this convolution does is traversing the whole stack backwards. The namespace callbacks are unncessary because the operations involved are inherently synchronous. The information can be provided in in straight-forward top-down direction and reversing that direction is unnecessary and against basic design principles. This backward interface is unnecessarily convoluted and hinders properly separating out sysfs from driver model / kobject for proper layering. This patch updates attr ns support such that * sysfs_ops->namespace() and class_attr->namespace() are dropped. * sysfs_{create|remove}_file_ns(), which take explicit @ns param, are added and sysfs_{create|remove}_file() are now simple wrappers around the ns aware functions. * ns handling is dropped from sysfs_chmod_file(). Nobody uses it at this point. sysfs_chmod_file_ns() can be added later if necessary. * Explicit @ns is propagated through class_{create|remove}_file_ns() and netdev_class_{create|remove}_file_ns(). * driver/net/bonding which is currently the only user of attr namespace is updated to use netdev_class_{create|remove}_file_ns() with @bh->net as the ns tag instead of using the namespace callback. This patch should be an equivalent conversion without any functional difference. It makes the code easier to follow, reduces lines of code a bit and helps proper separation and layering. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'include/linux/sysfs.h') diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 11baec7c9b26..82f7fac78e77 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -173,7 +173,6 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size) struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *, char *); ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); - const void *(*namespace)(struct kobject *, const struct attribute *); }; struct sysfs_dirent; @@ -189,13 +188,15 @@ int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name); int __must_check sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj); -int __must_check sysfs_create_file(struct kobject *kobj, - const struct attribute *attr); +int __must_check sysfs_create_file_ns(struct kobject *kobj, + const struct attribute *attr, + const void *ns); int __must_check sysfs_create_files(struct kobject *kobj, const struct attribute **attr); int __must_check sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, umode_t mode); -void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); +void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, + const void *ns); void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); int __must_check sysfs_create_bin_file(struct kobject *kobj, @@ -277,8 +278,9 @@ static inline int sysfs_move_dir(struct kobject *kobj, return 0; } -static inline int sysfs_create_file(struct kobject *kobj, - const struct attribute *attr) +static inline int sysfs_create_file_ns(struct kobject *kobj, + const struct attribute *attr, + const void *ns) { return 0; } @@ -295,8 +297,9 @@ static inline int sysfs_chmod_file(struct kobject *kobj, return 0; } -static inline void sysfs_remove_file(struct kobject *kobj, - const struct attribute *attr) +static inline void sysfs_remove_file_ns(struct kobject *kobj, + const struct attribute *attr, + const void *ns) { } @@ -435,4 +438,16 @@ static inline int __must_check sysfs_init(void) #endif /* CONFIG_SYSFS */ +static inline int __must_check sysfs_create_file(struct kobject *kobj, + const struct attribute *attr) +{ + return sysfs_create_file_ns(kobj, attr, NULL); +} + +static inline void sysfs_remove_file(struct kobject *kobj, + const struct attribute *attr) +{ + return sysfs_remove_file_ns(kobj, attr, NULL); +} + #endif /* _SYSFS_H_ */ -- cgit v1.2.3 From e34ff4906199d2ebd248ae897ae34f52bea151c9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 22:29:05 -0400 Subject: sysfs: remove ktype->namespace() invocations in directory code For some unrecognizable reason, namespace information is communicated to sysfs through ktype->namespace() callback when there's *nothing* which needs the use of a callback. The whole sequence of operations is completely synchronous and sysfs operations simply end up calling back into the layer which just invoked it in order to find out the namespace information, which is completely backwards, obfuscates what's going on and unnecessarily tangles two separate layers. This patch doesn't remove ktype->namespace() but shifts its handling to kobject layer. We probably want to get rid of the callback in the long term. This patch adds an explicit param to sysfs_{create|rename|move}_dir() and renames them to sysfs_{create|rename|move}_dir_ns(), respectively. ktype->namespace() invocations are moved to the calling sites of the above functions. A new helper kboject_namespace() is introduced which directly tests kobj_ns_type_operations->type which should give the same result as testing sysfs_fs_type(parent_sd) and returns @kobj's namespace tag as necessary. kobject_namespace() is extern as it will be used from another file in the following patches. This patch should be an equivalent conversion without any functional difference. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'include/linux/sysfs.h') diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 82f7fac78e77..7f56bad3be82 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -182,11 +182,13 @@ struct sysfs_dirent; int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), void *data, struct module *owner); -int __must_check sysfs_create_dir(struct kobject *kobj); +int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns); void sysfs_remove_dir(struct kobject *kobj); -int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name); -int __must_check sysfs_move_dir(struct kobject *kobj, - struct kobject *new_parent_kobj); +int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, + const void *new_ns); +int __must_check sysfs_move_dir_ns(struct kobject *kobj, + struct kobject *new_parent_kobj, + const void *new_ns); int __must_check sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr, @@ -258,7 +260,7 @@ static inline int sysfs_schedule_callback(struct kobject *kobj, return -ENOSYS; } -static inline int sysfs_create_dir(struct kobject *kobj) +static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) { return 0; } @@ -267,13 +269,15 @@ static inline void sysfs_remove_dir(struct kobject *kobj) { } -static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name) +static inline int sysfs_rename_dir_ns(struct kobject *kobj, + const char *new_name, const void *new_ns) { return 0; } -static inline int sysfs_move_dir(struct kobject *kobj, - struct kobject *new_parent_kobj) +static inline int sysfs_move_dir_ns(struct kobject *kobj, + struct kobject *new_parent_kobj, + const void *new_ns) { return 0; } -- cgit v1.2.3 From 4b30ee58ee64c64f59fd876e4afa6ed82caef3a4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 22:29:06 -0400 Subject: sysfs: remove ktype->namespace() invocations in symlink code There's no reason for sysfs to be calling ktype->namespace(). It is backwards, obfuscates what's going on and unnecessarily tangles two separate layers. There are two places where symlink code calls ktype->namespace(). * sysfs_do_create_link_sd() calls it to find out the namespace tag of the target directory. Unless symlinking races with cross-namespace renaming, this equals @target_sd->s_ns. * sysfs_rename_link() uses it to find out the new namespace to rename to and the new namespace can be different from the existing one. The function is renamed to sysfs_rename_link_ns() with an explicit @ns argument and the ktype->namespace() invocation is shifted to the device layer. While this patch replaces ktype->namespace() invocation with the recorded result in @target_sd, this shouldn't result in any behvior difference. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'include/linux/sysfs.h') diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 7f56bad3be82..c792f73ac7fa 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -213,8 +213,9 @@ int __must_check sysfs_create_link_nowarn(struct kobject *kobj, const char *name); void sysfs_remove_link(struct kobject *kobj, const char *name); -int sysfs_rename_link(struct kobject *kobj, struct kobject *target, - const char *old_name, const char *new_name); +int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name, + const void *new_ns); void sysfs_delete_link(struct kobject *dir, struct kobject *targ, const char *name); @@ -340,8 +341,9 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name) { } -static inline int sysfs_rename_link(struct kobject *k, struct kobject *t, - const char *old_name, const char *new_name) +static inline int sysfs_rename_link_ns(struct kobject *k, struct kobject *t, + const char *old_name, + const char *new_name, const void *ns) { return 0; } @@ -454,4 +456,10 @@ static inline void sysfs_remove_file(struct kobject *kobj, return sysfs_remove_file_ns(kobj, attr, NULL); } +static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target, + const char *old_name, const char *new_name) +{ + return sysfs_rename_link_ns(kobj, target, old_name, new_name, NULL); +} + #endif /* _SYSFS_H_ */ -- cgit v1.2.3 From 388975cccaaf11abd47525f664c76891c440481a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 11 Sep 2013 23:19:13 -0400 Subject: sysfs: clean up sysfs_get_dirent() The pre-existing sysfs interfaces which take explicit namespace argument are weird in that they place the optional @ns in front of @name which is contrary to the established convention. For example, we end up forcing vast majority of sysfs_get_dirent() users to do sysfs_get_dirent(parent, NULL, name), which is silly and error-prone especially as @ns and @name may be interchanged without causing compilation warning. This renames sysfs_get_dirent() to sysfs_get_dirent_ns() and swap the positions of @name and @ns, and sysfs_get_dirent() is now a wrapper around sysfs_get_dirent_ns(). This makes confusions a lot less likely. There are other interfaces which take @ns before @name. They'll be updated by following patches. This patch doesn't introduce any functional changes. v2: EXPORT_SYMBOL_GPL() wasn't updated leading to undefined symbol error on module builds. Reported by build test robot. Fixed. Signed-off-by: Tejun Heo Cc: Eric W. Biederman Cc: Kay Sievers Cc: Fengguang Wu Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'include/linux/sysfs.h') diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index c792f73ac7fa..6695040a0317 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -245,9 +245,9 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr); void sysfs_notify_dirent(struct sysfs_dirent *sd); -struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, - const void *ns, - const unsigned char *name); +struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, + const unsigned char *name, + const void *ns); struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd); void sysfs_put(struct sysfs_dirent *sd); @@ -422,10 +422,9 @@ static inline void sysfs_notify(struct kobject *kobj, const char *dir, static inline void sysfs_notify_dirent(struct sysfs_dirent *sd) { } -static inline -struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, - const void *ns, - const unsigned char *name) +static inline struct sysfs_dirent * +sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, const unsigned char *name, + const void *ns) { return NULL; } @@ -462,4 +461,10 @@ static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target return sysfs_rename_link_ns(kobj, target, old_name, new_name, NULL); } +static inline struct sysfs_dirent * +sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name) +{ + return sysfs_get_dirent_ns(parent_sd, name, NULL); +} + #endif /* _SYSFS_H_ */ -- cgit v1.2.3