blob: f318b73c790c8d2b058bd68ac6646b2adb550802 [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>
Eric W. Biedermanb592fcf2007-01-24 12:35:52 -070016#include <linux/fs.h>
Oliver Neukum94bebf42006-12-20 10:52:44 +010017#include <asm/semaphore.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include "sysfs.h"
19
20
Tejun Heo608e2662007-06-14 04:27:22 +090021static void remove_files(struct sysfs_dirent *dir_sd,
22 const struct attribute_group *grp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070023{
24 struct attribute *const* attr;
25
26 for (attr = grp->attrs; *attr; attr++)
Tejun Heo608e2662007-06-14 04:27:22 +090027 sysfs_hash_and_remove(dir_sd, (*attr)->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -070028}
29
Tejun Heo608e2662007-06-14 04:27:22 +090030static int create_files(struct sysfs_dirent *dir_sd,
31 const struct attribute_group *grp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070032{
33 struct attribute *const* attr;
34 int error = 0;
35
Tejun Heo608e2662007-06-14 04:27:22 +090036 for (attr = grp->attrs; *attr && !error; attr++)
37 error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 if (error)
Tejun Heo608e2662007-06-14 04:27:22 +090039 remove_files(dir_sd, grp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 return error;
41}
42
43
44int sysfs_create_group(struct kobject * kobj,
45 const struct attribute_group * grp)
46{
Tejun Heo608e2662007-06-14 04:27:22 +090047 struct sysfs_dirent *sd;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 int error;
49
Tejun Heo608e2662007-06-14 04:27:22 +090050 BUG_ON(!kobj || !kobj->sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52 if (grp->name) {
Tejun Heo608e2662007-06-14 04:27:22 +090053 error = sysfs_create_subdir(kobj, grp->name, &sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 if (error)
55 return error;
56 } else
Tejun Heo608e2662007-06-14 04:27:22 +090057 sd = kobj->sd;
58 sysfs_get(sd);
59 error = create_files(sd, grp);
60 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 if (grp->name)
Tejun Heo608e2662007-06-14 04:27:22 +090062 sysfs_remove_subdir(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 }
Tejun Heo608e2662007-06-14 04:27:22 +090064 sysfs_put(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 return error;
66}
67
68void sysfs_remove_group(struct kobject * kobj,
69 const struct attribute_group * grp)
70{
Tejun Heo608e2662007-06-14 04:27:22 +090071 struct sysfs_dirent *dir_sd = kobj->sd;
72 struct sysfs_dirent *sd;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
James Morris057f6c02007-04-26 00:12:05 -070074 if (grp->name) {
Tejun Heo608e2662007-06-14 04:27:22 +090075 sd = sysfs_get_dirent(dir_sd, grp->name);
76 BUG_ON(!sd);
77 } else
78 sd = sysfs_get(dir_sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Tejun Heo608e2662007-06-14 04:27:22 +090080 remove_files(sd, grp);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 if (grp->name)
Tejun Heo608e2662007-06-14 04:27:22 +090082 sysfs_remove_subdir(sd);
83
84 sysfs_put(sd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070085}
86
87
88EXPORT_SYMBOL_GPL(sysfs_create_group);
89EXPORT_SYMBOL_GPL(sysfs_remove_group);