aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
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 /fs/sysfs
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>
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/dir.c54
-rw-r--r--fs/sysfs/group.c9
-rw-r--r--fs/sysfs/sysfs.h3
3 files changed, 36 insertions, 30 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) {