blob: 0871c3dadce1c4a16d469b9a03b511f3eadbb937 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/sysfs/group.c - Operations for adding/removing multiple files at once.
3 *
4 * Copyright (c) 2003 Patrick Mochel
5 * Copyright (c) 2003 Open Source Development Lab
6 *
7 * This file is released undert the GPL v2.
8 *
9 */
10
11#include <linux/kobject.h>
12#include <linux/module.h>
13#include <linux/dcache.h>
Christoph Hellwig5f45f1a2005-06-23 00:09:12 -070014#include <linux/namei.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/err.h>
16#include "sysfs.h"
17
18
James Bottomleyd4acd722007-10-31 09:38:04 -050019static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
Tejun Heo608e2662007-06-14 04:27:22 +090020 const struct attribute_group *grp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070021{
22 struct attribute *const* attr;
James Bottomleyd4acd722007-10-31 09:38:04 -050023 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
James Bottomleyd4acd722007-10-31 09:38:04 -050025 for (i = 0, attr = grp->attrs; *attr; i++, attr++)
26 if (!grp->is_visible ||
27 grp->is_visible(kobj, *attr, i))
28 sysfs_hash_and_remove(dir_sd, (*attr)->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -070029}
30
James Bottomleyd4acd722007-10-31 09:38:04 -050031static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
Tejun Heo608e2662007-06-14 04:27:22 +090032 const struct attribute_group *grp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033{
34 struct attribute *const* attr;
James Bottomleyd4acd722007-10-31 09:38:04 -050035 int error = 0, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
James Bottomleyd4acd722007-10-31 09:38:04 -050037 for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++)
38 if (!grp->is_visible ||
39 grp->is_visible(kobj, *attr, i))
40 error |=
41 sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 if (error)
James Bottomleyd4acd722007-10-31 09:38:04 -050043 remove_files(dir_sd, kobj, grp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 return error;
45}
46
47
48int sysfs_create_group(struct kobject * kobj,
49 const struct attribute_group * grp)
50{
Tejun Heo608e2662007-06-14 04:27:22 +090051 struct sysfs_dirent *sd;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 int error;
53
Tejun Heo608e2662007-06-14 04:27:22 +090054 BUG_ON(!kobj || !kobj->sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56 if (grp->name) {
Tejun Heo608e2662007-06-14 04:27:22 +090057 error = sysfs_create_subdir(kobj, grp->name, &sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 if (error)
59 return error;
60 } else
Tejun Heo608e2662007-06-14 04:27:22 +090061 sd = kobj->sd;
62 sysfs_get(sd);
James Bottomleyd4acd722007-10-31 09:38:04 -050063 error = create_files(sd, kobj, grp);
Tejun Heo608e2662007-06-14 04:27:22 +090064 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 if (grp->name)
Tejun Heo608e2662007-06-14 04:27:22 +090066 sysfs_remove_subdir(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 }
Tejun Heo608e2662007-06-14 04:27:22 +090068 sysfs_put(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 return error;
70}
71
72void sysfs_remove_group(struct kobject * kobj,
73 const struct attribute_group * grp)
74{
Tejun Heo608e2662007-06-14 04:27:22 +090075 struct sysfs_dirent *dir_sd = kobj->sd;
76 struct sysfs_dirent *sd;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
James Morris057f6c02007-04-26 00:12:05 -070078 if (grp->name) {
Tejun Heo608e2662007-06-14 04:27:22 +090079 sd = sysfs_get_dirent(dir_sd, grp->name);
80 BUG_ON(!sd);
81 } else
82 sd = sysfs_get(dir_sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
James Bottomleyd4acd722007-10-31 09:38:04 -050084 remove_files(sd, kobj, grp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 if (grp->name)
Tejun Heo608e2662007-06-14 04:27:22 +090086 sysfs_remove_subdir(sd);
87
88 sysfs_put(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089}
90
91
92EXPORT_SYMBOL_GPL(sysfs_create_group);
93EXPORT_SYMBOL_GPL(sysfs_remove_group);