aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-07 06:47:28 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-07 06:47:28 -0500
commita1212d278c05ca0a38f5cbd7ae90ac2e367228a8 (patch)
tree230f8bad53644f1bdd25e5c0fd892475742e7783 /fs/sysfs/dir.c
parent0b1e73ed225d8f7aeef96b74147215ca8b990dce (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/dir.c')
-rw-r--r--fs/sysfs/dir.c88
1 files changed, 64 insertions, 24 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)
291static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) 279static 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);
318out_valid: 312out_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,
659EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); 667EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns);
660 668
661static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, 669static 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,
691int sysfs_create_subdir(struct kobject *kobj, const char *name, 701int 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 */
716static 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 */
702int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) 738int 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)) {