aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-09-11 22:29:07 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-09-26 18:30:22 -0400
commitcb26a311578e67769e92a39a0a63476533cb7e12 (patch)
tree13a1c59bdf23abdb063d1bc4a8cc1679e36dcd38
parent4b30ee58ee64c64f59fd876e4afa6ed82caef3a4 (diff)
sysfs: drop kobj_ns_type handling
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 or where namespace is enabled. 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. Also, whether to filter by namespace tag or not can be trivially determined by whether the node has any tagged children or not. This patch rips out kobj_ns_type handling from sysfs. sysfs no longer cares whether specific type of namespace is enabled or not. If a sysfs_dirent has a non-NULL tag, the parent is marked as needing namespace filtering and the value is tested against the allowed set of tags for the superblock (currently only one but increasing this number isn't difficult) and the sysfs_dirent is ignored if it doesn't match. This removes most kobject namespace knowledge from sysfs proper which will enable proper separation and layering of sysfs. The namespace sanity checks in fs/sysfs/dir.c are replaced by the new sanity check in kobject_namespace(). As this is the only place ktype->namespace() is called for sysfs, this doesn't weaken the sanity check significantly. I omitted converting the sanity check in sysfs_do_create_link_sd(). While the check can be shifted to upper layer, mistakes there are well contained and should be easily visible anyway. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Kay Sievers <kay@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/sysfs/dir.c90
-rw-r--r--fs/sysfs/mount.c24
-rw-r--r--fs/sysfs/symlink.c27
-rw-r--r--fs/sysfs/sysfs.h25
-rw-r--r--lib/kobject.c5
5 files changed, 48 insertions, 123 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 878ac3afe1b8..1dfb4aaf9446 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -111,6 +111,11 @@ static int sysfs_link_sibling(struct sysfs_dirent *sd)
111 /* add new node and rebalance the tree */ 111 /* add new node and rebalance the tree */
112 rb_link_node(&sd->s_rb, parent, node); 112 rb_link_node(&sd->s_rb, parent, node);
113 rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children); 113 rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children);
114
115 /* if @sd has ns tag, mark the parent to enable ns filtering */
116 if (sd->s_ns)
117 sd->s_parent->s_flags |= SYSFS_FLAG_HAS_NS;
118
114 return 0; 119 return 0;
115} 120}
116 121
@@ -130,6 +135,13 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
130 sd->s_parent->s_dir.subdirs--; 135 sd->s_parent->s_dir.subdirs--;
131 136
132 rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); 137 rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
138
139 /*
140 * Either all or none of the children have tags. Clearing HAS_NS
141 * when there's no child left is enough to keep the flag synced.
142 */
143 if (RB_EMPTY_ROOT(&sd->s_parent->s_dir.children))
144 sd->s_parent->s_flags &= ~SYSFS_FLAG_HAS_NS;
133} 145}
134 146
135#ifdef CONFIG_DEBUG_LOCK_ALLOC 147#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -297,7 +309,6 @@ static int sysfs_dentry_delete(const struct dentry *dentry)
297static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) 309static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
298{ 310{
299 struct sysfs_dirent *sd; 311 struct sysfs_dirent *sd;
300 int type;
301 312
302 if (flags & LOOKUP_RCU) 313 if (flags & LOOKUP_RCU)
303 return -ECHILD; 314 return -ECHILD;
@@ -318,13 +329,8 @@ static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
318 goto out_bad; 329 goto out_bad;
319 330
320 /* The sysfs dirent has been moved to a different namespace */ 331 /* The sysfs dirent has been moved to a different namespace */
321 type = KOBJ_NS_TYPE_NONE; 332 if (sd->s_ns && sd->s_ns != sysfs_info(dentry->d_sb)->ns)
322 if (sd->s_parent) { 333 goto out_bad;
323 type = sysfs_ns_type(sd->s_parent);
324 if (type != KOBJ_NS_TYPE_NONE &&
325 sysfs_info(dentry->d_sb)->ns[type] != sd->s_ns)
326 goto out_bad;
327 }
328 334
329 mutex_unlock(&sysfs_mutex); 335 mutex_unlock(&sysfs_mutex);
330out_valid: 336out_valid:
@@ -445,13 +451,6 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
445 struct sysfs_inode_attrs *ps_iattr; 451 struct sysfs_inode_attrs *ps_iattr;
446 int ret; 452 int ret;
447 453
448 if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
449 WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
450 sysfs_ns_type(acxt->parent_sd) ? "required" : "invalid",
451 acxt->parent_sd->s_name, sd->s_name);
452 return -EINVAL;
453 }
454
455 sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name); 454 sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
456 sd->s_parent = sysfs_get(acxt->parent_sd); 455 sd->s_parent = sysfs_get(acxt->parent_sd);
457 456
@@ -613,13 +612,6 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
613 struct rb_node *node = parent_sd->s_dir.children.rb_node; 612 struct rb_node *node = parent_sd->s_dir.children.rb_node;
614 unsigned int hash; 613 unsigned int hash;
615 614
616 if (!!sysfs_ns_type(parent_sd) != !!ns) {
617 WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
618 sysfs_ns_type(parent_sd) ? "required" : "invalid",
619 parent_sd->s_name, name);
620 return NULL;
621 }
622
623 hash = sysfs_name_hash(ns, name); 615 hash = sysfs_name_hash(ns, name);
624 while (node) { 616 while (node) {
625 struct sysfs_dirent *sd; 617 struct sysfs_dirent *sd;
@@ -667,8 +659,7 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
667EXPORT_SYMBOL_GPL(sysfs_get_dirent); 659EXPORT_SYMBOL_GPL(sysfs_get_dirent);
668 660
669static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, 661static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
670 enum kobj_ns_type type, const void *ns, const char *name, 662 const void *ns, const char *name, struct sysfs_dirent **p_sd)
671 struct sysfs_dirent **p_sd)
672{ 663{
673 umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; 664 umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
674 struct sysfs_addrm_cxt acxt; 665 struct sysfs_addrm_cxt acxt;
@@ -680,7 +671,6 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
680 if (!sd) 671 if (!sd)
681 return -ENOMEM; 672 return -ENOMEM;
682 673
683 sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT);
684 sd->s_ns = ns; 674 sd->s_ns = ns;
685 sd->s_dir.kobj = kobj; 675 sd->s_dir.kobj = kobj;
686 676
@@ -700,33 +690,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
700int sysfs_create_subdir(struct kobject *kobj, const char *name, 690int sysfs_create_subdir(struct kobject *kobj, const char *name,
701 struct sysfs_dirent **p_sd) 691 struct sysfs_dirent **p_sd)
702{ 692{
703 return create_dir(kobj, kobj->sd, 693 return create_dir(kobj, kobj->sd, NULL, name, p_sd);
704 KOBJ_NS_TYPE_NONE, NULL, name, p_sd);
705}
706
707/**
708 * sysfs_read_ns_type: return associated ns_type
709 * @kobj: the kobject being queried
710 *
711 * Each kobject can be tagged with exactly one namespace type
712 * (i.e. network or user). Return the ns_type associated with
713 * this object if any
714 */
715static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj)
716{
717 const struct kobj_ns_type_operations *ops;
718 enum kobj_ns_type type;
719
720 ops = kobj_child_ns_ops(kobj);
721 if (!ops)
722 return KOBJ_NS_TYPE_NONE;
723
724 type = ops->type;
725 BUG_ON(type <= KOBJ_NS_TYPE_NONE);
726 BUG_ON(type >= KOBJ_NS_TYPES);
727 BUG_ON(!kobj_ns_type_registered(type));
728
729 return type;
730} 694}
731 695
732/** 696/**
@@ -736,7 +700,6 @@ static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj)
736 */ 700 */
737int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) 701int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
738{ 702{
739 enum kobj_ns_type type;
740 struct sysfs_dirent *parent_sd, *sd; 703 struct sysfs_dirent *parent_sd, *sd;
741 int error = 0; 704 int error = 0;
742 705
@@ -750,9 +713,7 @@ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
750 if (!parent_sd) 713 if (!parent_sd)
751 return -ENOENT; 714 return -ENOENT;
752 715
753 type = sysfs_read_ns_type(kobj); 716 error = create_dir(kobj, parent_sd, ns, kobject_name(kobj), &sd);
754
755 error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd);
756 if (!error) 717 if (!error)
757 kobj->sd = sd; 718 kobj->sd = sd;
758 return error; 719 return error;
@@ -766,13 +727,12 @@ static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry,
766 struct sysfs_dirent *parent_sd = parent->d_fsdata; 727 struct sysfs_dirent *parent_sd = parent->d_fsdata;
767 struct sysfs_dirent *sd; 728 struct sysfs_dirent *sd;
768 struct inode *inode; 729 struct inode *inode;
769 enum kobj_ns_type type; 730 const void *ns = NULL;
770 const void *ns;
771 731
772 mutex_lock(&sysfs_mutex); 732 mutex_lock(&sysfs_mutex);
773 733
774 type = sysfs_ns_type(parent_sd); 734 if (parent_sd->s_flags & SYSFS_FLAG_HAS_NS)
775 ns = sysfs_info(dir->i_sb)->ns[type]; 735 ns = sysfs_info(dir->i_sb)->ns;
776 736
777 sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name); 737 sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name);
778 738
@@ -995,15 +955,15 @@ static int sysfs_readdir(struct file *file, struct dir_context *ctx)
995 struct dentry *dentry = file->f_path.dentry; 955 struct dentry *dentry = file->f_path.dentry;
996 struct sysfs_dirent *parent_sd = dentry->d_fsdata; 956 struct sysfs_dirent *parent_sd = dentry->d_fsdata;
997 struct sysfs_dirent *pos = file->private_data; 957 struct sysfs_dirent *pos = file->private_data;
998 enum kobj_ns_type type; 958 const void *ns = NULL;
999 const void *ns;
1000
1001 type = sysfs_ns_type(parent_sd);
1002 ns = sysfs_info(dentry->d_sb)->ns[type];
1003 959
1004 if (!dir_emit_dots(file, ctx)) 960 if (!dir_emit_dots(file, ctx))
1005 return 0; 961 return 0;
1006 mutex_lock(&sysfs_mutex); 962 mutex_lock(&sysfs_mutex);
963
964 if (parent_sd->s_flags & SYSFS_FLAG_HAS_NS)
965 ns = sysfs_info(dentry->d_sb)->ns;
966
1007 for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); 967 for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos);
1008 pos; 968 pos;
1009 pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { 969 pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) {
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 834ec2cdb7a3..8c24bce2f4ae 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -36,7 +36,7 @@ static const struct super_operations sysfs_ops = {
36struct sysfs_dirent sysfs_root = { 36struct sysfs_dirent sysfs_root = {
37 .s_name = "", 37 .s_name = "",
38 .s_count = ATOMIC_INIT(1), 38 .s_count = ATOMIC_INIT(1),
39 .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT), 39 .s_flags = SYSFS_DIR,
40 .s_mode = S_IFDIR | S_IRUGO | S_IXUGO, 40 .s_mode = S_IFDIR | S_IRUGO | S_IXUGO,
41 .s_ino = 1, 41 .s_ino = 1,
42}; 42};
@@ -77,14 +77,8 @@ static int sysfs_test_super(struct super_block *sb, void *data)
77{ 77{
78 struct sysfs_super_info *sb_info = sysfs_info(sb); 78 struct sysfs_super_info *sb_info = sysfs_info(sb);
79 struct sysfs_super_info *info = data; 79 struct sysfs_super_info *info = data;
80 enum kobj_ns_type type;
81 int found = 1;
82 80
83 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) { 81 return sb_info->ns == info->ns;
84 if (sb_info->ns[type] != info->ns[type])
85 found = 0;
86 }
87 return found;
88} 82}
89 83
90static int sysfs_set_super(struct super_block *sb, void *data) 84static int sysfs_set_super(struct super_block *sb, void *data)
@@ -98,9 +92,7 @@ static int sysfs_set_super(struct super_block *sb, void *data)
98 92
99static void free_sysfs_super_info(struct sysfs_super_info *info) 93static void free_sysfs_super_info(struct sysfs_super_info *info)
100{ 94{
101 int type; 95 kobj_ns_drop(KOBJ_NS_TYPE_NET, info->ns);
102 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
103 kobj_ns_drop(type, info->ns[type]);
104 kfree(info); 96 kfree(info);
105} 97}
106 98
@@ -108,7 +100,6 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
108 int flags, const char *dev_name, void *data) 100 int flags, const char *dev_name, void *data)
109{ 101{
110 struct sysfs_super_info *info; 102 struct sysfs_super_info *info;
111 enum kobj_ns_type type;
112 struct super_block *sb; 103 struct super_block *sb;
113 int error; 104 int error;
114 105
@@ -116,18 +107,15 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
116 if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type)) 107 if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
117 return ERR_PTR(-EPERM); 108 return ERR_PTR(-EPERM);
118 109
119 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) { 110 if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET))
120 if (!kobj_ns_current_may_mount(type)) 111 return ERR_PTR(-EPERM);
121 return ERR_PTR(-EPERM);
122 }
123 } 112 }
124 113
125 info = kzalloc(sizeof(*info), GFP_KERNEL); 114 info = kzalloc(sizeof(*info), GFP_KERNEL);
126 if (!info) 115 if (!info)
127 return ERR_PTR(-ENOMEM); 116 return ERR_PTR(-ENOMEM);
128 117
129 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) 118 info->ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
130 info->ns[type] = kobj_ns_grab_current(type);
131 119
132 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info); 120 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
133 if (IS_ERR(sb) || sb->s_fs_info != info) 121 if (IS_ERR(sb) || sb->s_fs_info != info)
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 12d58ada3e6d..7d981ce2e87f 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,
28 struct sysfs_dirent *target_sd = NULL; 28 struct sysfs_dirent *target_sd = NULL;
29 struct sysfs_dirent *sd = NULL; 29 struct sysfs_dirent *sd = NULL;
30 struct sysfs_addrm_cxt acxt; 30 struct sysfs_addrm_cxt acxt;
31 enum kobj_ns_type ns_type;
32 int error; 31 int error;
33 32
34 BUG_ON(!name || !parent_sd); 33 BUG_ON(!name || !parent_sd);
@@ -50,29 +49,15 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
50 if (!sd) 49 if (!sd)
51 goto out_put; 50 goto out_put;
52 51
53 ns_type = sysfs_ns_type(parent_sd); 52 sd->s_ns = target_sd->s_ns;
54 if (ns_type)
55 sd->s_ns = target_sd->s_ns;
56 sd->s_symlink.target_sd = target_sd; 53 sd->s_symlink.target_sd = target_sd;
57 target_sd = NULL; /* reference is now owned by the symlink */ 54 target_sd = NULL; /* reference is now owned by the symlink */
58 55
59 sysfs_addrm_start(&acxt, parent_sd); 56 sysfs_addrm_start(&acxt, parent_sd);
60 /* Symlinks must be between directories with the same ns_type */ 57 if (warn)
61 if (!ns_type || 58 error = sysfs_add_one(&acxt, sd);
62 (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) { 59 else
63 if (warn) 60 error = __sysfs_add_one(&acxt, sd);
64 error = sysfs_add_one(&acxt, sd);
65 else
66 error = __sysfs_add_one(&acxt, sd);
67 } else {
68 error = -EINVAL;
69 WARN(1, KERN_WARNING
70 "sysfs: symlink across ns_types %s/%s -> %s/%s\n",
71 parent_sd->s_name,
72 sd->s_name,
73 sd->s_symlink.target_sd->s_parent->s_name,
74 sd->s_symlink.target_sd->s_name);
75 }
76 sysfs_addrm_finish(&acxt); 61 sysfs_addrm_finish(&acxt);
77 62
78 if (error) 63 if (error)
@@ -156,7 +141,7 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
156{ 141{
157 const void *ns = NULL; 142 const void *ns = NULL;
158 spin_lock(&sysfs_assoc_lock); 143 spin_lock(&sysfs_assoc_lock);
159 if (targ->sd && sysfs_ns_type(kobj->sd)) 144 if (targ->sd)
160 ns = targ->sd->s_ns; 145 ns = targ->sd->s_ns;
161 spin_unlock(&sysfs_assoc_lock); 146 spin_unlock(&sysfs_assoc_lock);
162 sysfs_hash_and_remove(kobj->sd, ns, name); 147 sysfs_hash_and_remove(kobj->sd, ns, name);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a96da2559db2..7664d1b3d594 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -93,11 +93,8 @@ struct sysfs_dirent {
93#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) 93#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
94#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) 94#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR)
95 95
96/* identify any namespace tag on sysfs_dirents */ 96#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
97#define SYSFS_NS_TYPE_MASK 0xf00 97#define SYSFS_FLAG_HAS_NS 0x01000
98#define SYSFS_NS_TYPE_SHIFT 8
99
100#define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK)
101#define SYSFS_FLAG_REMOVED 0x02000 98#define SYSFS_FLAG_REMOVED 0x02000
102 99
103static inline unsigned int sysfs_type(struct sysfs_dirent *sd) 100static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
@@ -105,15 +102,6 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
105 return sd->s_flags & SYSFS_TYPE_MASK; 102 return sd->s_flags & SYSFS_TYPE_MASK;
106} 103}
107 104
108/*
109 * Return any namespace tags on this dirent.
110 * enum kobj_ns_type is defined in linux/kobject.h
111 */
112static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd)
113{
114 return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT;
115}
116
117#ifdef CONFIG_DEBUG_LOCK_ALLOC 105#ifdef CONFIG_DEBUG_LOCK_ALLOC
118#define sysfs_dirent_init_lockdep(sd) \ 106#define sysfs_dirent_init_lockdep(sd) \
119do { \ 107do { \
@@ -141,12 +129,13 @@ struct sysfs_addrm_cxt {
141 */ 129 */
142 130
143/* 131/*
144 * Each sb is associated with a set of namespace tags (i.e. 132 * Each sb is associated with one namespace tag, currently the network
145 * the network namespace of the task which mounted this sysfs 133 * namespace of the task which mounted this sysfs instance. If multiple
146 * instance). 134 * tags become necessary, make the following an array and compare
135 * sysfs_dirent tag against every entry.
147 */ 136 */
148struct sysfs_super_info { 137struct sysfs_super_info {
149 void *ns[KOBJ_NS_TYPES]; 138 void *ns;
150}; 139};
151#define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) 140#define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info))
152extern struct sysfs_dirent sysfs_root; 141extern struct sysfs_dirent sysfs_root;
diff --git a/lib/kobject.c b/lib/kobject.c
index 85fb3a161b21..e769ee3c2fb9 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -29,11 +29,14 @@
29const void *kobject_namespace(struct kobject *kobj) 29const void *kobject_namespace(struct kobject *kobj)
30{ 30{
31 const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj); 31 const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj);
32 const void *ns;
32 33
33 if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE) 34 if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE)
34 return NULL; 35 return NULL;
35 36
36 return kobj->ktype->namespace(kobj); 37 ns = kobj->ktype->namespace(kobj);
38 WARN_ON(!ns); /* @kobj in a namespace is required to have !NULL tag */
39 return ns;
37} 40}
38 41
39/* 42/*