aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/group.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 18:49:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-20 18:49:44 -0500
commitd3bad75a6d57416cf7478ca2a1e42f699bc17ec5 (patch)
treed79e9403e17aef5fee028fc550eec583dda38e0c /fs/sysfs/group.c
parent9f67627a0fea99b080a190d2d24cc1e2634aa2f7 (diff)
parentdb4aad209bc9aefd91f0a9aeb9e37364088b39ad (diff)
Merge tag 'driver-core-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core / sysfs patches from Greg KH: "Here's the big driver core and sysfs patch set for 3.14-rc1. There's a lot of work here moving sysfs logic out into a "kernfs" to allow other subsystems to also have a virtual filesystem with the same attributes of sysfs (handle device disconnect, dynamic creation / removal as needed / unneeded, etc) This is primarily being done for the cgroups filesystem, but the goal is to also move debugfs to it when it is ready, solving all of the known issues in that filesystem as well. The code isn't completed yet, but all should be stable now (there is a big section that was reverted due to problems found when testing) There's also some other smaller fixes, and a driver core addition that allows for a "collection" of objects, that the DRM people will be using soon (it's in this tree to make merges after -rc1 easier) All of this has been in linux-next with no reported issues" * tag 'driver-core-3.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (113 commits) kernfs: associate a new kernfs_node with its parent on creation kernfs: add struct dentry declaration in kernfs.h kernfs: fix get_active failure handling in kernfs_seq_*() Revert "kernfs: fix get_active failure handling in kernfs_seq_*()" Revert "kernfs: replace kernfs_node->u.completion with kernfs_root->deactivate_waitq" Revert "kernfs: remove KERNFS_ACTIVE_REF and add kernfs_lockdep()" Revert "kernfs: remove KERNFS_REMOVED" Revert "kernfs: restructure removal path to fix possible premature return" Revert "kernfs: invoke kernfs_unmap_bin_file() directly from __kernfs_remove()" Revert "kernfs: remove kernfs_addrm_cxt" Revert "kernfs: make kernfs_get_active() block if the node is deactivated but not removed" Revert "kernfs: implement kernfs_{de|re}activate[_self]()" Revert "kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers" Revert "pci: use device_remove_file_self() instead of device_schedule_callback()" Revert "scsi: use device_remove_file_self() instead of device_schedule_callback()" Revert "s390: use device_remove_file_self() instead of device_schedule_callback()" Revert "sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner()" Revert "kernfs: remove unnecessary NULL check in __kernfs_remove()" kernfs: remove unnecessary NULL check in __kernfs_remove() drivers/base: provide an infrastructure for componentised subsystems ...
Diffstat (limited to 'fs/sysfs/group.c')
-rw-r--r--fs/sysfs/group.c102
1 files changed, 53 insertions, 49 deletions
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 1898a10e38ce..6b579387c67a 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -18,7 +18,7 @@
18#include "sysfs.h" 18#include "sysfs.h"
19 19
20 20
21static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, 21static void remove_files(struct kernfs_node *parent, struct kobject *kobj,
22 const struct attribute_group *grp) 22 const struct attribute_group *grp)
23{ 23{
24 struct attribute *const *attr; 24 struct attribute *const *attr;
@@ -26,13 +26,13 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
26 26
27 if (grp->attrs) 27 if (grp->attrs)
28 for (attr = grp->attrs; *attr; attr++) 28 for (attr = grp->attrs; *attr; attr++)
29 sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL); 29 kernfs_remove_by_name(parent, (*attr)->name);
30 if (grp->bin_attrs) 30 if (grp->bin_attrs)
31 for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) 31 for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
32 sysfs_remove_bin_file(kobj, *bin_attr); 32 sysfs_remove_bin_file(kobj, *bin_attr);
33} 33}
34 34
35static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, 35static int create_files(struct kernfs_node *parent, struct kobject *kobj,
36 const struct attribute_group *grp, int update) 36 const struct attribute_group *grp, int update)
37{ 37{
38 struct attribute *const *attr; 38 struct attribute *const *attr;
@@ -49,22 +49,20 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
49 * re-adding (if required) the file. 49 * re-adding (if required) the file.
50 */ 50 */
51 if (update) 51 if (update)
52 sysfs_hash_and_remove(dir_sd, (*attr)->name, 52 kernfs_remove_by_name(parent, (*attr)->name);
53 NULL);
54 if (grp->is_visible) { 53 if (grp->is_visible) {
55 mode = grp->is_visible(kobj, *attr, i); 54 mode = grp->is_visible(kobj, *attr, i);
56 if (!mode) 55 if (!mode)
57 continue; 56 continue;
58 } 57 }
59 error = sysfs_add_file_mode_ns(dir_sd, *attr, 58 error = sysfs_add_file_mode_ns(parent, *attr, false,
60 SYSFS_KOBJ_ATTR,
61 (*attr)->mode | mode, 59 (*attr)->mode | mode,
62 NULL); 60 NULL);
63 if (unlikely(error)) 61 if (unlikely(error))
64 break; 62 break;
65 } 63 }
66 if (error) { 64 if (error) {
67 remove_files(dir_sd, kobj, grp); 65 remove_files(parent, kobj, grp);
68 goto exit; 66 goto exit;
69 } 67 }
70 } 68 }
@@ -78,7 +76,7 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
78 break; 76 break;
79 } 77 }
80 if (error) 78 if (error)
81 remove_files(dir_sd, kobj, grp); 79 remove_files(parent, kobj, grp);
82 } 80 }
83exit: 81exit:
84 return error; 82 return error;
@@ -88,7 +86,7 @@ exit:
88static int internal_create_group(struct kobject *kobj, int update, 86static int internal_create_group(struct kobject *kobj, int update,
89 const struct attribute_group *grp) 87 const struct attribute_group *grp)
90{ 88{
91 struct sysfs_dirent *sd; 89 struct kernfs_node *kn;
92 int error; 90 int error;
93 91
94 BUG_ON(!kobj || (!update && !kobj->sd)); 92 BUG_ON(!kobj || (!update && !kobj->sd));
@@ -102,18 +100,22 @@ static int internal_create_group(struct kobject *kobj, int update,
102 return -EINVAL; 100 return -EINVAL;
103 } 101 }
104 if (grp->name) { 102 if (grp->name) {
105 error = sysfs_create_subdir(kobj, grp->name, &sd); 103 kn = kernfs_create_dir(kobj->sd, grp->name,
106 if (error) 104 S_IRWXU | S_IRUGO | S_IXUGO, kobj);
107 return error; 105 if (IS_ERR(kn)) {
106 if (PTR_ERR(kn) == -EEXIST)
107 sysfs_warn_dup(kobj->sd, grp->name);
108 return PTR_ERR(kn);
109 }
108 } else 110 } else
109 sd = kobj->sd; 111 kn = kobj->sd;
110 sysfs_get(sd); 112 kernfs_get(kn);
111 error = create_files(sd, kobj, grp, update); 113 error = create_files(kn, kobj, grp, update);
112 if (error) { 114 if (error) {
113 if (grp->name) 115 if (grp->name)
114 sysfs_remove(sd); 116 kernfs_remove(kn);
115 } 117 }
116 sysfs_put(sd); 118 kernfs_put(kn);
117 return error; 119 return error;
118} 120}
119 121
@@ -203,25 +205,27 @@ EXPORT_SYMBOL_GPL(sysfs_update_group);
203void sysfs_remove_group(struct kobject *kobj, 205void sysfs_remove_group(struct kobject *kobj,
204 const struct attribute_group *grp) 206 const struct attribute_group *grp)
205{ 207{
206 struct sysfs_dirent *dir_sd = kobj->sd; 208 struct kernfs_node *parent = kobj->sd;
207 struct sysfs_dirent *sd; 209 struct kernfs_node *kn;
208 210
209 if (grp->name) { 211 if (grp->name) {
210 sd = sysfs_get_dirent(dir_sd, grp->name); 212 kn = kernfs_find_and_get(parent, grp->name);
211 if (!sd) { 213 if (!kn) {
212 WARN(!sd, KERN_WARNING 214 WARN(!kn, KERN_WARNING
213 "sysfs group %p not found for kobject '%s'\n", 215 "sysfs group %p not found for kobject '%s'\n",
214 grp, kobject_name(kobj)); 216 grp, kobject_name(kobj));
215 return; 217 return;
216 } 218 }
217 } else 219 } else {
218 sd = sysfs_get(dir_sd); 220 kn = parent;
221 kernfs_get(kn);
222 }
219 223
220 remove_files(sd, kobj, grp); 224 remove_files(kn, kobj, grp);
221 if (grp->name) 225 if (grp->name)
222 sysfs_remove(sd); 226 kernfs_remove(kn);
223 227
224 sysfs_put(sd); 228 kernfs_put(kn);
225} 229}
226EXPORT_SYMBOL_GPL(sysfs_remove_group); 230EXPORT_SYMBOL_GPL(sysfs_remove_group);
227 231
@@ -257,22 +261,22 @@ EXPORT_SYMBOL_GPL(sysfs_remove_groups);
257int sysfs_merge_group(struct kobject *kobj, 261int sysfs_merge_group(struct kobject *kobj,
258 const struct attribute_group *grp) 262 const struct attribute_group *grp)
259{ 263{
260 struct sysfs_dirent *dir_sd; 264 struct kernfs_node *parent;
261 int error = 0; 265 int error = 0;
262 struct attribute *const *attr; 266 struct attribute *const *attr;
263 int i; 267 int i;
264 268
265 dir_sd = sysfs_get_dirent(kobj->sd, grp->name); 269 parent = kernfs_find_and_get(kobj->sd, grp->name);
266 if (!dir_sd) 270 if (!parent)
267 return -ENOENT; 271 return -ENOENT;
268 272
269 for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr)) 273 for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
270 error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR); 274 error = sysfs_add_file(parent, *attr, false);
271 if (error) { 275 if (error) {
272 while (--i >= 0) 276 while (--i >= 0)
273 sysfs_hash_and_remove(dir_sd, (*--attr)->name, NULL); 277 kernfs_remove_by_name(parent, (*--attr)->name);
274 } 278 }
275 sysfs_put(dir_sd); 279 kernfs_put(parent);
276 280
277 return error; 281 return error;
278} 282}
@@ -286,14 +290,14 @@ EXPORT_SYMBOL_GPL(sysfs_merge_group);
286void sysfs_unmerge_group(struct kobject *kobj, 290void sysfs_unmerge_group(struct kobject *kobj,
287 const struct attribute_group *grp) 291 const struct attribute_group *grp)
288{ 292{
289 struct sysfs_dirent *dir_sd; 293 struct kernfs_node *parent;
290 struct attribute *const *attr; 294 struct attribute *const *attr;
291 295
292 dir_sd = sysfs_get_dirent(kobj->sd, grp->name); 296 parent = kernfs_find_and_get(kobj->sd, grp->name);
293 if (dir_sd) { 297 if (parent) {
294 for (attr = grp->attrs; *attr; ++attr) 298 for (attr = grp->attrs; *attr; ++attr)
295 sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL); 299 kernfs_remove_by_name(parent, (*attr)->name);
296 sysfs_put(dir_sd); 300 kernfs_put(parent);
297 } 301 }
298} 302}
299EXPORT_SYMBOL_GPL(sysfs_unmerge_group); 303EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
@@ -308,15 +312,15 @@ EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
308int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name, 312int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
309 struct kobject *target, const char *link_name) 313 struct kobject *target, const char *link_name)
310{ 314{
311 struct sysfs_dirent *dir_sd; 315 struct kernfs_node *parent;
312 int error = 0; 316 int error = 0;
313 317
314 dir_sd = sysfs_get_dirent(kobj->sd, group_name); 318 parent = kernfs_find_and_get(kobj->sd, group_name);
315 if (!dir_sd) 319 if (!parent)
316 return -ENOENT; 320 return -ENOENT;
317 321
318 error = sysfs_create_link_sd(dir_sd, target, link_name); 322 error = sysfs_create_link_sd(parent, target, link_name);
319 sysfs_put(dir_sd); 323 kernfs_put(parent);
320 324
321 return error; 325 return error;
322} 326}
@@ -331,12 +335,12 @@ EXPORT_SYMBOL_GPL(sysfs_add_link_to_group);
331void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name, 335void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
332 const char *link_name) 336 const char *link_name)
333{ 337{
334 struct sysfs_dirent *dir_sd; 338 struct kernfs_node *parent;
335 339
336 dir_sd = sysfs_get_dirent(kobj->sd, group_name); 340 parent = kernfs_find_and_get(kobj->sd, group_name);
337 if (dir_sd) { 341 if (parent) {
338 sysfs_hash_and_remove(dir_sd, link_name, NULL); 342 kernfs_remove_by_name(parent, link_name);
339 sysfs_put(dir_sd); 343 kernfs_put(parent);
340 } 344 }
341} 345}
342EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group); 346EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);