diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-07 20:47:28 +0900 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-07 20:47:28 +0900 |
commit | a1212d278c05ca0a38f5cbd7ae90ac2e367228a8 (patch) | |
tree | 230f8bad53644f1bdd25e5c0fd892475742e7783 /fs/sysfs/symlink.c | |
parent | 0b1e73ed225d8f7aeef96b74147215ca8b990dce (diff) |
Revert "sysfs: drop kobj_ns_type handling"
This reverts commit cb26a311578e67769e92a39a0a63476533cb7e12.
It mysteriously causes NetworkManager to not find the wireless device
for me. As far as I can tell, Tejun *meant* for this commit to not make
any semantic changes, but there clearly are some. So revert it, taking
into account some of the calling convention changes that happened in
this area in subsequent commits.
Cc: Tejun Heo <tj@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/sysfs/symlink.c')
-rw-r--r-- | fs/sysfs/symlink.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 1a23681b817..3ae3f1bf1a0 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -28,6 +28,7 @@ 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); @@ -51,15 +52,29 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, if (!sd) goto out_put; - sd->s_ns = target_sd->s_ns; + ns_type = sysfs_ns_type(parent_sd); + if (ns_type) + 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); - if (warn) - error = sysfs_add_one(&acxt, sd, parent_sd); - else - error = __sysfs_add_one(&acxt, sd, parent_sd); + /* 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); + } sysfs_addrm_finish(&acxt); if (error) @@ -149,7 +164,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) + if (targ->sd && sysfs_ns_type(kobj->sd)) ns = targ->sd->s_ns; spin_unlock(&sysfs_symlink_target_lock); sysfs_hash_and_remove(kobj->sd, name, ns); |