diff options
author | Tejun Heo <tj@kernel.org> | 2013-11-23 18:01:46 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-11-27 13:01:03 -0800 |
commit | c84a3b27798dfce928b867fa1c9f3c3fd66f0a31 (patch) | |
tree | 87a706232ee20ce8262b4a34bbf9eaf06b3ddfe6 /fs/sysfs/symlink.c | |
parent | 6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae (diff) |
sysfs: drop kobj_ns_type handling, take #2
The way namespace tags are implemented in sysfs is more complicated
than necessary. As each tag is a pointer value and required to be
non-NULL under a namespace enabled parent, there's no need to record
separately what type each tag is. If multiple namespace types are
needed, which currently aren't, we can simply compare the tag to a set
of allowed tags in the superblock assuming that the tags, being
pointers, won't have the same value across multiple types.
This patch rips out kobj_ns_type handling from sysfs. sysfs now has
an enable switch to turn on namespace under a node. If enabled, all
children are required to have non-NULL namespace tags and filtered
against the super_block's tag.
kobject namespace determination is now performed in
lib/kobject.c::create_dir() making sysfs_read_ns_type() unnecessary.
The sanity checks are also moved. create_dir() is restructured to
ease such addition. This removes most kobject namespace knowledge
from sysfs proper which will enable proper separation and layering of
sysfs.
This is the second try. The first one was cb26a311578e ("sysfs: drop
kobj_ns_type handling") which tried to automatically enable namespace
if there are children with non-NULL namespace tags; however, it was
broken for symlinks as they should inherit the target's tag iff
namespace is enabled in the parent. This led to namespace filtering
enabled incorrectly for wireless net class devices through phy80211
symlinks and thus network configuration failure. a1212d278c05
("Revert "sysfs: drop kobj_ns_type handling"") reverted the commit.
This shouldn't introduce any behavior changes, for real.
v2: Dummy implementation of sysfs_enable_ns() for !CONFIG_SYSFS was
missing and caused build failure. Reported by kbuild test robot.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Kay Sievers <kay@vrfy.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/sysfs/symlink.c')
-rw-r--r-- | fs/sysfs/symlink.c | 26 |
1 files changed, 6 insertions, 20 deletions
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 3ae3f1bf1a09..c660363fdaea 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -28,7 +28,6 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, struct sysfs_dirent *target_sd = NULL; struct sysfs_dirent *sd = NULL; struct sysfs_addrm_cxt acxt; - enum kobj_ns_type ns_type; int error; BUG_ON(!name || !parent_sd); @@ -52,29 +51,16 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, if (!sd) goto out_put; - ns_type = sysfs_ns_type(parent_sd); - if (ns_type) + if (parent_sd->s_flags & SYSFS_FLAG_NS) sd->s_ns = target_sd->s_ns; sd->s_symlink.target_sd = target_sd; target_sd = NULL; /* reference is now owned by the symlink */ sysfs_addrm_start(&acxt); - /* Symlinks must be between directories with the same ns_type */ - if (!ns_type || - (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) { - if (warn) - error = sysfs_add_one(&acxt, sd, parent_sd); - else - error = __sysfs_add_one(&acxt, sd, parent_sd); - } else { - error = -EINVAL; - WARN(1, KERN_WARNING - "sysfs: symlink across ns_types %s/%s -> %s/%s\n", - parent_sd->s_name, - sd->s_name, - sd->s_symlink.target_sd->s_parent->s_name, - sd->s_symlink.target_sd->s_name); - } + if (warn) + error = sysfs_add_one(&acxt, sd, parent_sd); + else + error = __sysfs_add_one(&acxt, sd, parent_sd); sysfs_addrm_finish(&acxt); if (error) @@ -164,7 +150,7 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, * sysfs_remove_dir() for details. */ spin_lock(&sysfs_symlink_target_lock); - if (targ->sd && sysfs_ns_type(kobj->sd)) + if (targ->sd && (kobj->sd->s_flags & SYSFS_FLAG_NS)) ns = targ->sd->s_ns; spin_unlock(&sysfs_symlink_target_lock); sysfs_hash_and_remove(kobj->sd, name, ns); |