Revert "sysfs: drop kobj_ns_type handling"
[linux-drm-fsl-dcu.git] / fs / sysfs / symlink.c
index 1a23681b817901a46dad3e4432c54de147248d37..3ae3f1bf1a0957075bec9d36d8834550000c3b14 100644 (file)
@@ -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);