aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-11-28 14:54:15 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-29 20:20:13 -0500
commit93b2b8e4aa4317e3fe6414d117deb5f3c362e8bb (patch)
tree0055820ae48856f7ff3bf05c948d0e95d2c73c07
parent7c6e2d362c19f01e6d6c8be59d83a89722032884 (diff)
sysfs, kernfs: introduce kernfs_create_dir[_ns]()
Introduce kernfs interface to manipulate a directory which takes and returns sysfs_dirents. create_dir() is renamed to kernfs_create_dir_ns() and its argumantes and return value are updated. create_dir() usages are replaced with kernfs_create_dir_ns() and sysfs_create_subdir() usages are replaced with kernfs_create_dir(). Dup warnings are handled explicitly by sysfs users of the kernfs interface. sysfs_enable_ns() is renamed to kernfs_enable_ns(). This patch doesn't introduce any behavior changes. v2: Dummy implementation for !CONFIG_SYSFS updated to return -ENOSYS. v3: kernfs_enable_ns() added. v4: Refreshed on top of "sysfs: drop kobj_ns_type handling, take #2" so that this patch removes sysfs_enable_ns(). Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/sysfs/dir.c54
-rw-r--r--fs/sysfs/group.c9
-rw-r--r--fs/sysfs/sysfs.h3
-rw-r--r--include/linux/kernfs.h17
-rw-r--r--include/linux/sysfs.h6
-rw-r--r--lib/kobject.c2
6 files changed, 54 insertions, 37 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index aeb08bd3f3dd..cfbf4091fe5c 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -666,9 +666,18 @@ struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd,
666} 666}
667EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); 667EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns);
668 668
669static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, 669/**
670 const char *name, const void *ns, 670 * kernfs_create_dir_ns - create a directory
671 struct sysfs_dirent **p_sd) 671 * @parent: parent in which to create a new directory
672 * @name: name of the new directory
673 * @priv: opaque data associated with the new directory
674 * @ns: optional namespace tag of the directory
675 *
676 * Returns the created node on success, ERR_PTR() value on failure.
677 */
678struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent,
679 const char *name, void *priv,
680 const void *ns)
672{ 681{
673 umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; 682 umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
674 struct sysfs_addrm_cxt acxt; 683 struct sysfs_addrm_cxt acxt;
@@ -678,28 +687,21 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
678 /* allocate */ 687 /* allocate */
679 sd = sysfs_new_dirent(name, mode, SYSFS_DIR); 688 sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
680 if (!sd) 689 if (!sd)
681 return -ENOMEM; 690 return ERR_PTR(-ENOMEM);
682 691
683 sd->s_ns = ns; 692 sd->s_ns = ns;
684 sd->priv = kobj; 693 sd->priv = priv;
685 694
686 /* link in */ 695 /* link in */
687 sysfs_addrm_start(&acxt); 696 sysfs_addrm_start(&acxt);
688 rc = sysfs_add_one(&acxt, sd, parent_sd); 697 rc = __sysfs_add_one(&acxt, sd, parent);
689 sysfs_addrm_finish(&acxt); 698 sysfs_addrm_finish(&acxt);
690 699
691 if (rc == 0) 700 if (!rc)
692 *p_sd = sd; 701 return sd;
693 else
694 sysfs_put(sd);
695 702
696 return rc; 703 sysfs_put(sd);
697} 704 return ERR_PTR(rc);
698
699int sysfs_create_subdir(struct kobject *kobj, const char *name,
700 struct sysfs_dirent **p_sd)
701{
702 return create_dir(kobj, kobj->sd, name, NULL, p_sd);
703} 705}
704 706
705/** 707/**
@@ -710,7 +712,6 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
710int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) 712int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
711{ 713{
712 struct sysfs_dirent *parent_sd, *sd; 714 struct sysfs_dirent *parent_sd, *sd;
713 int error = 0;
714 715
715 BUG_ON(!kobj); 716 BUG_ON(!kobj);
716 717
@@ -722,10 +723,15 @@ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
722 if (!parent_sd) 723 if (!parent_sd)
723 return -ENOENT; 724 return -ENOENT;
724 725
725 error = create_dir(kobj, parent_sd, kobject_name(kobj), ns, &sd); 726 sd = kernfs_create_dir_ns(parent_sd, kobject_name(kobj), kobj, ns);
726 if (!error) 727 if (IS_ERR(sd)) {
727 kobj->sd = sd; 728 if (PTR_ERR(sd) == -EEXIST)
728 return error; 729 sysfs_warn_dup(parent_sd, kobject_name(kobj));
730 return PTR_ERR(sd);
731 }
732
733 kobj->sd = sd;
734 return 0;
729} 735}
730 736
731static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry, 737static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry,
@@ -1005,14 +1011,14 @@ int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
1005} 1011}
1006 1012
1007/** 1013/**
1008 * sysfs_enable_ns - enable namespace under a directory 1014 * kernfs_enable_ns - enable namespace under a directory
1009 * @sd: directory of interest, should be empty 1015 * @sd: directory of interest, should be empty
1010 * 1016 *
1011 * This is to be called right after @sd is created to enable namespace 1017 * This is to be called right after @sd is created to enable namespace
1012 * under it. All children of @sd must have non-NULL namespace tags and 1018 * under it. All children of @sd must have non-NULL namespace tags and
1013 * only the ones which match the super_block's tag will be visible. 1019 * only the ones which match the super_block's tag will be visible.
1014 */ 1020 */
1015void sysfs_enable_ns(struct sysfs_dirent *sd) 1021void kernfs_enable_ns(struct sysfs_dirent *sd)
1016{ 1022{
1017 WARN_ON_ONCE(sysfs_type(sd) != SYSFS_DIR); 1023 WARN_ON_ONCE(sysfs_type(sd) != SYSFS_DIR);
1018 WARN_ON_ONCE(!RB_EMPTY_ROOT(&sd->s_dir.children)); 1024 WARN_ON_ONCE(!RB_EMPTY_ROOT(&sd->s_dir.children));
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 4bd997340830..065689ddb4cb 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -101,9 +101,12 @@ static int internal_create_group(struct kobject *kobj, int update,
101 return -EINVAL; 101 return -EINVAL;
102 } 102 }
103 if (grp->name) { 103 if (grp->name) {
104 error = sysfs_create_subdir(kobj, grp->name, &sd); 104 sd = kernfs_create_dir(kobj->sd, grp->name, kobj);
105 if (error) 105 if (IS_ERR(sd)) {
106 return error; 106 if (PTR_ERR(sd) == -EEXIST)
107 sysfs_warn_dup(kobj->sd, grp->name);
108 return PTR_ERR(sd);
109 }
107 } else 110 } else
108 sd = kobj->sd; 111 sd = kobj->sd;
109 sysfs_get(sd); 112 sysfs_get(sd);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a6f3fa3f02fe..9ac234ef4943 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -179,9 +179,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
179 179
180void release_sysfs_dirent(struct sysfs_dirent *sd); 180void release_sysfs_dirent(struct sysfs_dirent *sd);
181 181
182int sysfs_create_subdir(struct kobject *kobj, const char *name,
183 struct sysfs_dirent **p_sd);
184
185static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) 182static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
186{ 183{
187 if (sd) { 184 if (sd) {
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index 8cb673875715..e8b73d4a08d2 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -17,6 +17,9 @@ struct sysfs_dirent;
17 17
18#ifdef CONFIG_SYSFS 18#ifdef CONFIG_SYSFS
19 19
20struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent,
21 const char *name, void *priv,
22 const void *ns);
20struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, 23struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
21 const char *name, 24 const char *name,
22 struct sysfs_dirent *target); 25 struct sysfs_dirent *target);
@@ -25,11 +28,17 @@ int kernfs_remove_by_name_ns(struct sysfs_dirent *parent, const char *name,
25 const void *ns); 28 const void *ns);
26int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent, 29int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent,
27 const char *new_name, const void *new_ns); 30 const char *new_name, const void *new_ns);
31void kernfs_enable_ns(struct sysfs_dirent *sd);
28int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr); 32int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr);
29 33
30#else /* CONFIG_SYSFS */ 34#else /* CONFIG_SYSFS */
31 35
32static inline struct sysfs_dirent * 36static inline struct sysfs_dirent *
37kernfs_create_dir_ns(struct sysfs_dirent *parent, const char *name, void *priv,
38 const void *ns)
39{ return ERR_PTR(-ENOSYS); }
40
41static inline struct sysfs_dirent *
33kernfs_create_link(struct sysfs_dirent *parent, const char *name, 42kernfs_create_link(struct sysfs_dirent *parent, const char *name,
34 struct sysfs_dirent *target) 43 struct sysfs_dirent *target)
35{ return ERR_PTR(-ENOSYS); } 44{ return ERR_PTR(-ENOSYS); }
@@ -45,12 +54,20 @@ static inline int kernfs_rename_ns(struct sysfs_dirent *sd,
45 const char *new_name, const void *new_ns) 54 const char *new_name, const void *new_ns)
46{ return -ENOSYS; } 55{ return -ENOSYS; }
47 56
57static inline void kernfs_enable_ns(struct sysfs_dirent *sd) { }
58
48static inline int kernfs_setattr(struct sysfs_dirent *sd, 59static inline int kernfs_setattr(struct sysfs_dirent *sd,
49 const struct iattr *iattr) 60 const struct iattr *iattr)
50{ return -ENOSYS; } 61{ return -ENOSYS; }
51 62
52#endif /* CONFIG_SYSFS */ 63#endif /* CONFIG_SYSFS */
53 64
65static inline struct sysfs_dirent *
66kernfs_create_dir(struct sysfs_dirent *parent, const char *name, void *priv)
67{
68 return kernfs_create_dir_ns(parent, name, priv, NULL);
69}
70
54static inline int kernfs_remove_by_name(struct sysfs_dirent *parent, 71static inline int kernfs_remove_by_name(struct sysfs_dirent *parent,
55 const char *name) 72 const char *name)
56{ 73{
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index e17381a92e1a..2bc735d3e938 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -219,8 +219,6 @@ int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *target,
219void sysfs_delete_link(struct kobject *dir, struct kobject *targ, 219void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
220 const char *name); 220 const char *name);
221 221
222void sysfs_enable_ns(struct sysfs_dirent *sd);
223
224int __must_check sysfs_create_group(struct kobject *kobj, 222int __must_check sysfs_create_group(struct kobject *kobj,
225 const struct attribute_group *grp); 223 const struct attribute_group *grp);
226int __must_check sysfs_create_groups(struct kobject *kobj, 224int __must_check sysfs_create_groups(struct kobject *kobj,
@@ -354,10 +352,6 @@ static inline void sysfs_delete_link(struct kobject *k, struct kobject *t,
354{ 352{
355} 353}
356 354
357static inline void sysfs_enable_ns(struct sysfs_dirent *sd)
358{
359}
360
361static inline int sysfs_create_group(struct kobject *kobj, 355static inline int sysfs_create_group(struct kobject *kobj,
362 const struct attribute_group *grp) 356 const struct attribute_group *grp)
363{ 357{
diff --git a/lib/kobject.c b/lib/kobject.c
index 16e9335b32d3..b8d848fb1377 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -94,7 +94,7 @@ static int create_dir(struct kobject *kobj)
94 BUG_ON(ops->type >= KOBJ_NS_TYPES); 94 BUG_ON(ops->type >= KOBJ_NS_TYPES);
95 BUG_ON(!kobj_ns_type_registered(ops->type)); 95 BUG_ON(!kobj_ns_type_registered(ops->type));
96 96
97 sysfs_enable_ns(kobj->sd); 97 kernfs_enable_ns(kobj->sd);
98 } 98 }
99 99
100 return 0; 100 return 0;