diff options
-rw-r--r-- | fs/sysfs/dir.c | 88 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 24 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 27 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 25 | ||||
-rw-r--r-- | lib/kobject.c | 5 |
5 files changed, 122 insertions, 47 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 08c66969d52a..5e73d6626e50 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -111,11 +111,6 @@ 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 | |||
119 | return 0; | 114 | return 0; |
120 | } | 115 | } |
121 | 116 | ||
@@ -135,13 +130,6 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) | |||
135 | sd->s_parent->s_dir.subdirs--; | 130 | sd->s_parent->s_dir.subdirs--; |
136 | 131 | ||
137 | rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); | 132 | 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; | ||
145 | } | 133 | } |
146 | 134 | ||
147 | /** | 135 | /** |
@@ -291,6 +279,7 @@ static int sysfs_dentry_delete(const struct dentry *dentry) | |||
291 | static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) | 279 | static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) |
292 | { | 280 | { |
293 | struct sysfs_dirent *sd; | 281 | struct sysfs_dirent *sd; |
282 | int type; | ||
294 | 283 | ||
295 | if (flags & LOOKUP_RCU) | 284 | if (flags & LOOKUP_RCU) |
296 | return -ECHILD; | 285 | return -ECHILD; |
@@ -311,8 +300,13 @@ static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) | |||
311 | goto out_bad; | 300 | goto out_bad; |
312 | 301 | ||
313 | /* The sysfs dirent has been moved to a different namespace */ | 302 | /* The sysfs dirent has been moved to a different namespace */ |
314 | if (sd->s_ns && sd->s_ns != sysfs_info(dentry->d_sb)->ns) | 303 | type = KOBJ_NS_TYPE_NONE; |
315 | goto out_bad; | 304 | if (sd->s_parent) { |
305 | type = sysfs_ns_type(sd->s_parent); | ||
306 | if (type != KOBJ_NS_TYPE_NONE && | ||
307 | sysfs_info(dentry->d_sb)->ns[type] != sd->s_ns) | ||
308 | goto out_bad; | ||
309 | } | ||
316 | 310 | ||
317 | mutex_unlock(&sysfs_mutex); | 311 | mutex_unlock(&sysfs_mutex); |
318 | out_valid: | 312 | out_valid: |
@@ -432,6 +426,13 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd, | |||
432 | struct sysfs_inode_attrs *ps_iattr; | 426 | struct sysfs_inode_attrs *ps_iattr; |
433 | int ret; | 427 | int ret; |
434 | 428 | ||
429 | if (!!sysfs_ns_type(parent_sd) != !!sd->s_ns) { | ||
430 | WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", | ||
431 | sysfs_ns_type(parent_sd) ? "required" : "invalid", | ||
432 | parent_sd->s_name, sd->s_name); | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | |||
435 | sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); | 436 | sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns); |
436 | sd->s_parent = sysfs_get(parent_sd); | 437 | sd->s_parent = sysfs_get(parent_sd); |
437 | 438 | ||
@@ -611,6 +612,13 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | |||
611 | struct rb_node *node = parent_sd->s_dir.children.rb_node; | 612 | struct rb_node *node = parent_sd->s_dir.children.rb_node; |
612 | unsigned int hash; | 613 | unsigned int hash; |
613 | 614 | ||
615 | if (!!sysfs_ns_type(parent_sd) != !!ns) { | ||
616 | WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", | ||
617 | sysfs_ns_type(parent_sd) ? "required" : "invalid", | ||
618 | parent_sd->s_name, name); | ||
619 | return NULL; | ||
620 | } | ||
621 | |||
614 | hash = sysfs_name_hash(name, ns); | 622 | hash = sysfs_name_hash(name, ns); |
615 | while (node) { | 623 | while (node) { |
616 | struct sysfs_dirent *sd; | 624 | struct sysfs_dirent *sd; |
@@ -659,6 +667,7 @@ struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, | |||
659 | EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); | 667 | EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); |
660 | 668 | ||
661 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | 669 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, |
670 | enum kobj_ns_type type, | ||
662 | const char *name, const void *ns, | 671 | const char *name, const void *ns, |
663 | struct sysfs_dirent **p_sd) | 672 | struct sysfs_dirent **p_sd) |
664 | { | 673 | { |
@@ -672,6 +681,7 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | |||
672 | if (!sd) | 681 | if (!sd) |
673 | return -ENOMEM; | 682 | return -ENOMEM; |
674 | 683 | ||
684 | sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT); | ||
675 | sd->s_ns = ns; | 685 | sd->s_ns = ns; |
676 | sd->s_dir.kobj = kobj; | 686 | sd->s_dir.kobj = kobj; |
677 | 687 | ||
@@ -691,7 +701,33 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, | |||
691 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | 701 | int sysfs_create_subdir(struct kobject *kobj, const char *name, |
692 | struct sysfs_dirent **p_sd) | 702 | struct sysfs_dirent **p_sd) |
693 | { | 703 | { |
694 | return create_dir(kobj, kobj->sd, name, NULL, p_sd); | 704 | return create_dir(kobj, kobj->sd, |
705 | KOBJ_NS_TYPE_NONE, name, NULL, p_sd); | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * sysfs_read_ns_type: return associated ns_type | ||
710 | * @kobj: the kobject being queried | ||
711 | * | ||
712 | * Each kobject can be tagged with exactly one namespace type | ||
713 | * (i.e. network or user). Return the ns_type associated with | ||
714 | * this object if any | ||
715 | */ | ||
716 | static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj) | ||
717 | { | ||
718 | const struct kobj_ns_type_operations *ops; | ||
719 | enum kobj_ns_type type; | ||
720 | |||
721 | ops = kobj_child_ns_ops(kobj); | ||
722 | if (!ops) | ||
723 | return KOBJ_NS_TYPE_NONE; | ||
724 | |||
725 | type = ops->type; | ||
726 | BUG_ON(type <= KOBJ_NS_TYPE_NONE); | ||
727 | BUG_ON(type >= KOBJ_NS_TYPES); | ||
728 | BUG_ON(!kobj_ns_type_registered(type)); | ||
729 | |||
730 | return type; | ||
695 | } | 731 | } |
696 | 732 | ||
697 | /** | 733 | /** |
@@ -701,6 +737,7 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name, | |||
701 | */ | 737 | */ |
702 | int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) | 738 | int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) |
703 | { | 739 | { |
740 | enum kobj_ns_type type; | ||
704 | struct sysfs_dirent *parent_sd, *sd; | 741 | struct sysfs_dirent *parent_sd, *sd; |
705 | int error = 0; | 742 | int error = 0; |
706 | 743 | ||
@@ -714,7 +751,9 @@ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) | |||
714 | if (!parent_sd) | 751 | if (!parent_sd) |
715 | return -ENOENT; | 752 | return -ENOENT; |
716 | 753 | ||
717 | error = create_dir(kobj, parent_sd, kobject_name(kobj), ns, &sd); | 754 | type = sysfs_read_ns_type(kobj); |
755 | |||
756 | error = create_dir(kobj, parent_sd, type, kobject_name(kobj), ns, &sd); | ||
718 | if (!error) | 757 | if (!error) |
719 | kobj->sd = sd; | 758 | kobj->sd = sd; |
720 | return error; | 759 | return error; |
@@ -728,12 +767,13 @@ static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
728 | struct sysfs_dirent *parent_sd = parent->d_fsdata; | 767 | struct sysfs_dirent *parent_sd = parent->d_fsdata; |
729 | struct sysfs_dirent *sd; | 768 | struct sysfs_dirent *sd; |
730 | struct inode *inode; | 769 | struct inode *inode; |
731 | const void *ns = NULL; | 770 | enum kobj_ns_type type; |
771 | const void *ns; | ||
732 | 772 | ||
733 | mutex_lock(&sysfs_mutex); | 773 | mutex_lock(&sysfs_mutex); |
734 | 774 | ||
735 | if (parent_sd->s_flags & SYSFS_FLAG_HAS_NS) | 775 | type = sysfs_ns_type(parent_sd); |
736 | ns = sysfs_info(dir->i_sb)->ns; | 776 | ns = sysfs_info(dir->i_sb)->ns[type]; |
737 | 777 | ||
738 | sd = sysfs_find_dirent(parent_sd, dentry->d_name.name, ns); | 778 | sd = sysfs_find_dirent(parent_sd, dentry->d_name.name, ns); |
739 | 779 | ||
@@ -1056,15 +1096,15 @@ static int sysfs_readdir(struct file *file, struct dir_context *ctx) | |||
1056 | struct dentry *dentry = file->f_path.dentry; | 1096 | struct dentry *dentry = file->f_path.dentry; |
1057 | struct sysfs_dirent *parent_sd = dentry->d_fsdata; | 1097 | struct sysfs_dirent *parent_sd = dentry->d_fsdata; |
1058 | struct sysfs_dirent *pos = file->private_data; | 1098 | struct sysfs_dirent *pos = file->private_data; |
1059 | const void *ns = NULL; | 1099 | enum kobj_ns_type type; |
1100 | const void *ns; | ||
1101 | |||
1102 | type = sysfs_ns_type(parent_sd); | ||
1103 | ns = sysfs_info(dentry->d_sb)->ns[type]; | ||
1060 | 1104 | ||
1061 | if (!dir_emit_dots(file, ctx)) | 1105 | if (!dir_emit_dots(file, ctx)) |
1062 | return 0; | 1106 | return 0; |
1063 | mutex_lock(&sysfs_mutex); | 1107 | mutex_lock(&sysfs_mutex); |
1064 | |||
1065 | if (parent_sd->s_flags & SYSFS_FLAG_HAS_NS) | ||
1066 | ns = sysfs_info(dentry->d_sb)->ns; | ||
1067 | |||
1068 | for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); | 1108 | for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos); |
1069 | pos; | 1109 | pos; |
1070 | pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { | 1110 | pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) { |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 8c24bce2f4ae..834ec2cdb7a3 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -36,7 +36,7 @@ static const struct super_operations sysfs_ops = { | |||
36 | struct sysfs_dirent sysfs_root = { | 36 | struct 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, | 39 | .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT), |
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,8 +77,14 @@ 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; | ||
80 | 82 | ||
81 | return sb_info->ns == info->ns; | 83 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) { |
84 | if (sb_info->ns[type] != info->ns[type]) | ||
85 | found = 0; | ||
86 | } | ||
87 | return found; | ||
82 | } | 88 | } |
83 | 89 | ||
84 | static int sysfs_set_super(struct super_block *sb, void *data) | 90 | static int sysfs_set_super(struct super_block *sb, void *data) |
@@ -92,7 +98,9 @@ static int sysfs_set_super(struct super_block *sb, void *data) | |||
92 | 98 | ||
93 | static void free_sysfs_super_info(struct sysfs_super_info *info) | 99 | static void free_sysfs_super_info(struct sysfs_super_info *info) |
94 | { | 100 | { |
95 | kobj_ns_drop(KOBJ_NS_TYPE_NET, info->ns); | 101 | int type; |
102 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) | ||
103 | kobj_ns_drop(type, info->ns[type]); | ||
96 | kfree(info); | 104 | kfree(info); |
97 | } | 105 | } |
98 | 106 | ||
@@ -100,6 +108,7 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
100 | int flags, const char *dev_name, void *data) | 108 | int flags, const char *dev_name, void *data) |
101 | { | 109 | { |
102 | struct sysfs_super_info *info; | 110 | struct sysfs_super_info *info; |
111 | enum kobj_ns_type type; | ||
103 | struct super_block *sb; | 112 | struct super_block *sb; |
104 | int error; | 113 | int error; |
105 | 114 | ||
@@ -107,15 +116,18 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
107 | if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type)) | 116 | if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type)) |
108 | return ERR_PTR(-EPERM); | 117 | return ERR_PTR(-EPERM); |
109 | 118 | ||
110 | if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET)) | 119 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) { |
111 | return ERR_PTR(-EPERM); | 120 | if (!kobj_ns_current_may_mount(type)) |
121 | return ERR_PTR(-EPERM); | ||
122 | } | ||
112 | } | 123 | } |
113 | 124 | ||
114 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 125 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
115 | if (!info) | 126 | if (!info) |
116 | return ERR_PTR(-ENOMEM); | 127 | return ERR_PTR(-ENOMEM); |
117 | 128 | ||
118 | info->ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET); | 129 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) |
130 | info->ns[type] = kobj_ns_grab_current(type); | ||
119 | 131 | ||
120 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info); | 132 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info); |
121 | if (IS_ERR(sb) || sb->s_fs_info != info) | 133 | if (IS_ERR(sb) || sb->s_fs_info != info) |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 1a23681b8179..3ae3f1bf1a09 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, | |||
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; | ||
31 | int error; | 32 | int error; |
32 | 33 | ||
33 | BUG_ON(!name || !parent_sd); | 34 | BUG_ON(!name || !parent_sd); |
@@ -51,15 +52,29 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, | |||
51 | if (!sd) | 52 | if (!sd) |
52 | goto out_put; | 53 | goto out_put; |
53 | 54 | ||
54 | sd->s_ns = target_sd->s_ns; | 55 | ns_type = sysfs_ns_type(parent_sd); |
56 | if (ns_type) | ||
57 | sd->s_ns = target_sd->s_ns; | ||
55 | sd->s_symlink.target_sd = target_sd; | 58 | sd->s_symlink.target_sd = target_sd; |
56 | target_sd = NULL; /* reference is now owned by the symlink */ | 59 | target_sd = NULL; /* reference is now owned by the symlink */ |
57 | 60 | ||
58 | sysfs_addrm_start(&acxt); | 61 | sysfs_addrm_start(&acxt); |
59 | if (warn) | 62 | /* Symlinks must be between directories with the same ns_type */ |
60 | error = sysfs_add_one(&acxt, sd, parent_sd); | 63 | if (!ns_type || |
61 | else | 64 | (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) { |
62 | error = __sysfs_add_one(&acxt, sd, parent_sd); | 65 | if (warn) |
66 | error = sysfs_add_one(&acxt, sd, parent_sd); | ||
67 | else | ||
68 | error = __sysfs_add_one(&acxt, sd, parent_sd); | ||
69 | } else { | ||
70 | error = -EINVAL; | ||
71 | WARN(1, KERN_WARNING | ||
72 | "sysfs: symlink across ns_types %s/%s -> %s/%s\n", | ||
73 | parent_sd->s_name, | ||
74 | sd->s_name, | ||
75 | sd->s_symlink.target_sd->s_parent->s_name, | ||
76 | sd->s_symlink.target_sd->s_name); | ||
77 | } | ||
63 | sysfs_addrm_finish(&acxt); | 78 | sysfs_addrm_finish(&acxt); |
64 | 79 | ||
65 | if (error) | 80 | if (error) |
@@ -149,7 +164,7 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, | |||
149 | * sysfs_remove_dir() for details. | 164 | * sysfs_remove_dir() for details. |
150 | */ | 165 | */ |
151 | spin_lock(&sysfs_symlink_target_lock); | 166 | spin_lock(&sysfs_symlink_target_lock); |
152 | if (targ->sd) | 167 | if (targ->sd && sysfs_ns_type(kobj->sd)) |
153 | ns = targ->sd->s_ns; | 168 | ns = targ->sd->s_ns; |
154 | spin_unlock(&sysfs_symlink_target_lock); | 169 | spin_unlock(&sysfs_symlink_target_lock); |
155 | sysfs_hash_and_remove(kobj->sd, name, ns); | 170 | sysfs_hash_and_remove(kobj->sd, name, ns); |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index e3aea92ebfa3..0af09fbfb3f6 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -90,8 +90,11 @@ struct sysfs_dirent { | |||
90 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) | 90 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) |
91 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) | 91 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) |
92 | 92 | ||
93 | #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK | 93 | /* identify any namespace tag on sysfs_dirents */ |
94 | #define SYSFS_FLAG_HAS_NS 0x01000 | 94 | #define SYSFS_NS_TYPE_MASK 0xf00 |
95 | #define SYSFS_NS_TYPE_SHIFT 8 | ||
96 | |||
97 | #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) | ||
95 | #define SYSFS_FLAG_REMOVED 0x02000 | 98 | #define SYSFS_FLAG_REMOVED 0x02000 |
96 | 99 | ||
97 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | 100 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) |
@@ -99,6 +102,15 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | |||
99 | return sd->s_flags & SYSFS_TYPE_MASK; | 102 | return sd->s_flags & SYSFS_TYPE_MASK; |
100 | } | 103 | } |
101 | 104 | ||
105 | /* | ||
106 | * Return any namespace tags on this dirent. | ||
107 | * enum kobj_ns_type is defined in linux/kobject.h | ||
108 | */ | ||
109 | static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd) | ||
110 | { | ||
111 | return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT; | ||
112 | } | ||
113 | |||
102 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 114 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
103 | 115 | ||
104 | #define sysfs_dirent_init_lockdep(sd) \ | 116 | #define sysfs_dirent_init_lockdep(sd) \ |
@@ -143,13 +155,12 @@ struct sysfs_addrm_cxt { | |||
143 | */ | 155 | */ |
144 | 156 | ||
145 | /* | 157 | /* |
146 | * Each sb is associated with one namespace tag, currently the network | 158 | * Each sb is associated with a set of namespace tags (i.e. |
147 | * namespace of the task which mounted this sysfs instance. If multiple | 159 | * the network namespace of the task which mounted this sysfs |
148 | * tags become necessary, make the following an array and compare | 160 | * instance). |
149 | * sysfs_dirent tag against every entry. | ||
150 | */ | 161 | */ |
151 | struct sysfs_super_info { | 162 | struct sysfs_super_info { |
152 | void *ns; | 163 | void *ns[KOBJ_NS_TYPES]; |
153 | }; | 164 | }; |
154 | #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) | 165 | #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) |
155 | extern struct sysfs_dirent sysfs_root; | 166 | extern struct sysfs_dirent sysfs_root; |
diff --git a/lib/kobject.c b/lib/kobject.c index 7a1c203083eb..5b4b8886435e 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -30,14 +30,11 @@ | |||
30 | const void *kobject_namespace(struct kobject *kobj) | 30 | const void *kobject_namespace(struct kobject *kobj) |
31 | { | 31 | { |
32 | const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj); | 32 | const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj); |
33 | const void *ns; | ||
34 | 33 | ||
35 | if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE) | 34 | if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE) |
36 | return NULL; | 35 | return NULL; |
37 | 36 | ||
38 | ns = kobj->ktype->namespace(kobj); | 37 | return kobj->ktype->namespace(kobj); |
39 | WARN_ON(!ns); /* @kobj in a namespace is required to have !NULL tag */ | ||
40 | return ns; | ||
41 | } | 38 | } |
42 | 39 | ||
43 | /* | 40 | /* |