diff options
author | Tejun Heo <tj@kernel.org> | 2013-11-28 14:54:15 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-11-29 20:20:13 -0500 |
commit | 93b2b8e4aa4317e3fe6414d117deb5f3c362e8bb (patch) | |
tree | 0055820ae48856f7ff3bf05c948d0e95d2c73c07 | |
parent | 7c6e2d362c19f01e6d6c8be59d83a89722032884 (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.c | 54 | ||||
-rw-r--r-- | fs/sysfs/group.c | 9 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 3 | ||||
-rw-r--r-- | include/linux/kernfs.h | 17 | ||||
-rw-r--r-- | include/linux/sysfs.h | 6 | ||||
-rw-r--r-- | lib/kobject.c | 2 |
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 | } |
667 | EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); | 667 | EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns); |
668 | 668 | ||
669 | static 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 | */ | ||
678 | struct 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 | |||
699 | int 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, | |||
710 | int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) | 712 | int 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 | ||
731 | static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry, | 737 | static 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 | */ |
1015 | void sysfs_enable_ns(struct sysfs_dirent *sd) | 1021 | void 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 | ||
180 | void release_sysfs_dirent(struct sysfs_dirent *sd); | 180 | void release_sysfs_dirent(struct sysfs_dirent *sd); |
181 | 181 | ||
182 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | ||
183 | struct sysfs_dirent **p_sd); | ||
184 | |||
185 | static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd) | 182 | static 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 | ||
20 | struct sysfs_dirent *kernfs_create_dir_ns(struct sysfs_dirent *parent, | ||
21 | const char *name, void *priv, | ||
22 | const void *ns); | ||
20 | struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, | 23 | struct 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); |
26 | int kernfs_rename_ns(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent, | 29 | int 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); |
31 | void kernfs_enable_ns(struct sysfs_dirent *sd); | ||
28 | int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr); | 32 | int kernfs_setattr(struct sysfs_dirent *sd, const struct iattr *iattr); |
29 | 33 | ||
30 | #else /* CONFIG_SYSFS */ | 34 | #else /* CONFIG_SYSFS */ |
31 | 35 | ||
32 | static inline struct sysfs_dirent * | 36 | static inline struct sysfs_dirent * |
37 | kernfs_create_dir_ns(struct sysfs_dirent *parent, const char *name, void *priv, | ||
38 | const void *ns) | ||
39 | { return ERR_PTR(-ENOSYS); } | ||
40 | |||
41 | static inline struct sysfs_dirent * | ||
33 | kernfs_create_link(struct sysfs_dirent *parent, const char *name, | 42 | kernfs_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 | ||
57 | static inline void kernfs_enable_ns(struct sysfs_dirent *sd) { } | ||
58 | |||
48 | static inline int kernfs_setattr(struct sysfs_dirent *sd, | 59 | static 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 | ||
65 | static inline struct sysfs_dirent * | ||
66 | kernfs_create_dir(struct sysfs_dirent *parent, const char *name, void *priv) | ||
67 | { | ||
68 | return kernfs_create_dir_ns(parent, name, priv, NULL); | ||
69 | } | ||
70 | |||
54 | static inline int kernfs_remove_by_name(struct sysfs_dirent *parent, | 71 | static 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, | |||
219 | void sysfs_delete_link(struct kobject *dir, struct kobject *targ, | 219 | void sysfs_delete_link(struct kobject *dir, struct kobject *targ, |
220 | const char *name); | 220 | const char *name); |
221 | 221 | ||
222 | void sysfs_enable_ns(struct sysfs_dirent *sd); | ||
223 | |||
224 | int __must_check sysfs_create_group(struct kobject *kobj, | 222 | int __must_check sysfs_create_group(struct kobject *kobj, |
225 | const struct attribute_group *grp); | 223 | const struct attribute_group *grp); |
226 | int __must_check sysfs_create_groups(struct kobject *kobj, | 224 | int __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 | ||
357 | static inline void sysfs_enable_ns(struct sysfs_dirent *sd) | ||
358 | { | ||
359 | } | ||
360 | |||
361 | static inline int sysfs_create_group(struct kobject *kobj, | 355 | static 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; |