blob: d1972374655a22377e94186b62564aaa83f2299f [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
Tejun Heo608e2662007-06-14 04:27:22 +090019static void remove_files(struct sysfs_dirent *dir_sd,
20 const struct attribute_group *grp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070021{
22 struct attribute *const* attr;
23
24 for (attr = grp->attrs; *attr; attr++)
Tejun Heo608e2662007-06-14 04:27:22 +090025 sysfs_hash_and_remove(dir_sd, (*attr)->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -070026}
27
Tejun Heo608e2662007-06-14 04:27:22 +090028static int create_files(struct sysfs_dirent *dir_sd,
29 const struct attribute_group *grp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070030{
31 struct attribute *const* attr;
32 int error = 0;
33
Tejun Heo608e2662007-06-14 04:27:22 +090034 for (attr = grp->attrs; *attr && !error; attr++)
35 error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 if (error)
Tejun Heo608e2662007-06-14 04:27:22 +090037 remove_files(dir_sd, grp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 return error;
39}
40
41
42int sysfs_create_group(struct kobject * kobj,
43 const struct attribute_group * grp)
44{
Tejun Heo608e2662007-06-14 04:27:22 +090045 struct sysfs_dirent *sd;
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 int error;
47
Tejun Heo608e2662007-06-14 04:27:22 +090048 BUG_ON(!kobj || !kobj->sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50 if (grp->name) {
Tejun Heo608e2662007-06-14 04:27:22 +090051 error = sysfs_create_subdir(kobj, grp->name, &sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 if (error)
53 return error;
54 } else
Tejun Heo608e2662007-06-14 04:27:22 +090055 sd = kobj->sd;
56 sysfs_get(sd);
57 error = create_files(sd, grp);
58 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 if (grp->name)
Tejun Heo608e2662007-06-14 04:27:22 +090060 sysfs_remove_subdir(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 }
Tejun Heo608e2662007-06-14 04:27:22 +090062 sysfs_put(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 return error;
64}
65
66void sysfs_remove_group(struct kobject * kobj,
67 const struct attribute_group * grp)
68{
Tejun Heo608e2662007-06-14 04:27:22 +090069 struct sysfs_dirent *dir_sd = kobj->sd;
70 struct sysfs_dirent *sd;
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
James Morris057f6c02007-04-26 00:12:05 -070072 if (grp->name) {
Tejun Heo608e2662007-06-14 04:27:22 +090073 sd = sysfs_get_dirent(dir_sd, grp->name);
74 BUG_ON(!sd);
75 } else
76 sd = sysfs_get(dir_sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Tejun Heo608e2662007-06-14 04:27:22 +090078 remove_files(sd, grp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 if (grp->name)
Tejun Heo608e2662007-06-14 04:27:22 +090080 sysfs_remove_subdir(sd);
81
82 sysfs_put(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083}
84
85
86EXPORT_SYMBOL_GPL(sysfs_create_group);
87EXPORT_SYMBOL_GPL(sysfs_remove_group);