Blame view
fs/sysfs/group.c
5.3 KB
1da177e4c
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* * fs/sysfs/group.c - Operations for adding/removing multiple files at once. * * Copyright (c) 2003 Patrick Mochel * Copyright (c) 2003 Open Source Development Lab * * This file is released undert the GPL v2. * */ #include <linux/kobject.h> #include <linux/module.h> #include <linux/dcache.h> |
5f45f1a78
|
14 |
#include <linux/namei.h> |
1da177e4c
|
15 16 |
#include <linux/err.h> #include "sysfs.h" |
d4acd722b
|
17 |
static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, |
608e266a2
|
18 |
const struct attribute_group *grp) |
1da177e4c
|
19 20 |
{ struct attribute *const* attr; |
d4acd722b
|
21 |
int i; |
1da177e4c
|
22 |
|
d4acd722b
|
23 |
for (i = 0, attr = grp->attrs; *attr; i++, attr++) |
3ff195b01
|
24 |
sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); |
1da177e4c
|
25 |
} |
d4acd722b
|
26 |
static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj, |
0f4238958
|
27 |
const struct attribute_group *grp, int update) |
1da177e4c
|
28 29 |
{ struct attribute *const* attr; |
d4acd722b
|
30 |
int error = 0, i; |
1da177e4c
|
31 |
|
0f4238958
|
32 33 34 35 36 37 38 |
for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) { mode_t mode = 0; /* in update mode, we're changing the permissions or * visibility. Do this by first removing then * re-adding (if required) the file */ if (update) |
3ff195b01
|
39 |
sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); |
0f4238958
|
40 41 42 43 44 45 46 47 48 49 |
if (grp->is_visible) { mode = grp->is_visible(kobj, *attr, i); if (!mode) continue; } error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR, (*attr)->mode | mode); if (unlikely(error)) break; } |
1da177e4c
|
50 |
if (error) |
d4acd722b
|
51 |
remove_files(dir_sd, kobj, grp); |
1da177e4c
|
52 53 |
return error; } |
0f4238958
|
54 55 |
static int internal_create_group(struct kobject *kobj, int update, const struct attribute_group *grp) |
1da177e4c
|
56 |
{ |
608e266a2
|
57 |
struct sysfs_dirent *sd; |
1da177e4c
|
58 |
int error; |
0f4238958
|
59 60 61 62 63 |
BUG_ON(!kobj || (!update && !kobj->sd)); /* Updates may happen before the object has been instantiated */ if (unlikely(update && !kobj->sd)) return -EINVAL; |
1da177e4c
|
64 65 |
if (grp->name) { |
608e266a2
|
66 |
error = sysfs_create_subdir(kobj, grp->name, &sd); |
1da177e4c
|
67 68 69 |
if (error) return error; } else |
608e266a2
|
70 71 |
sd = kobj->sd; sysfs_get(sd); |
0f4238958
|
72 |
error = create_files(sd, kobj, grp, update); |
608e266a2
|
73 |
if (error) { |
1da177e4c
|
74 |
if (grp->name) |
608e266a2
|
75 |
sysfs_remove_subdir(sd); |
1da177e4c
|
76 |
} |
608e266a2
|
77 |
sysfs_put(sd); |
1da177e4c
|
78 79 |
return error; } |
0f4238958
|
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
/** * sysfs_create_group - given a directory kobject, create an attribute group * @kobj: The kobject to create the group on * @grp: The attribute group to create * * This function creates a group for the first time. It will explicitly * warn and error if any of the attribute files being created already exist. * * Returns 0 on success or error. */ int sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { return internal_create_group(kobj, 0, grp); } /** |
1f8e1cdac
|
97 98 99 |
* sysfs_update_group - given a directory kobject, update an attribute group * @kobj: The kobject to update the group on * @grp: The attribute group to update |
0f4238958
|
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
* * This function updates an attribute group. Unlike * sysfs_create_group(), it will explicitly not warn or error if any * of the attribute files being created already exist. Furthermore, * if the visibility of the files has changed through the is_visible() * callback, it will update the permissions and add or remove the * relevant files. * * The primary use for this function is to call it after making a change * that affects group visibility. * * Returns 0 on success or error. */ int sysfs_update_group(struct kobject *kobj, const struct attribute_group *grp) { return internal_create_group(kobj, 1, grp); } |
1da177e4c
|
118 119 120 |
void sysfs_remove_group(struct kobject * kobj, const struct attribute_group * grp) { |
608e266a2
|
121 122 |
struct sysfs_dirent *dir_sd = kobj->sd; struct sysfs_dirent *sd; |
1da177e4c
|
123 |
|
057f6c019
|
124 |
if (grp->name) { |
3ff195b01
|
125 |
sd = sysfs_get_dirent(dir_sd, NULL, grp->name); |
969affd27
|
126 |
if (!sd) { |
99fcd77d1
|
127 |
WARN(!sd, KERN_WARNING "sysfs group %p not found for " |
969affd27
|
128 129 |
"kobject '%s' ", grp, kobject_name(kobj)); |
969affd27
|
130 131 |
return; } |
608e266a2
|
132 133 |
} else sd = sysfs_get(dir_sd); |
1da177e4c
|
134 |
|
d4acd722b
|
135 |
remove_files(sd, kobj, grp); |
1da177e4c
|
136 |
if (grp->name) |
608e266a2
|
137 138 139 |
sysfs_remove_subdir(sd); sysfs_put(sd); |
1da177e4c
|
140 |
} |
69d44ffbd
|
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
/** * sysfs_merge_group - merge files into a pre-existing attribute group. * @kobj: The kobject containing the group. * @grp: The files to create and the attribute group they belong to. * * This function returns an error if the group doesn't exist or any of the * files already exist in that group, in which case none of the new files * are created. */ int sysfs_merge_group(struct kobject *kobj, const struct attribute_group *grp) { struct sysfs_dirent *dir_sd; int error = 0; struct attribute *const *attr; int i; |
e030d58e8
|
157 |
dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); |
69d44ffbd
|
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
if (!dir_sd) return -ENOENT; for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr)) error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR); if (error) { while (--i >= 0) sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name); } sysfs_put(dir_sd); return error; } EXPORT_SYMBOL_GPL(sysfs_merge_group); /** * sysfs_unmerge_group - remove files from a pre-existing attribute group. * @kobj: The kobject containing the group. * @grp: The files to remove and the attribute group they belong to. */ void sysfs_unmerge_group(struct kobject *kobj, const struct attribute_group *grp) { struct sysfs_dirent *dir_sd; struct attribute *const *attr; |
e030d58e8
|
183 |
dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name); |
69d44ffbd
|
184 185 186 187 188 189 190 |
if (dir_sd) { for (attr = grp->attrs; *attr; ++attr) sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name); sysfs_put(dir_sd); } } EXPORT_SYMBOL_GPL(sysfs_unmerge_group); |
1da177e4c
|
191 192 |
EXPORT_SYMBOL_GPL(sysfs_create_group); |
0f4238958
|
193 |
EXPORT_SYMBOL_GPL(sysfs_update_group); |
1da177e4c
|
194 |
EXPORT_SYMBOL_GPL(sysfs_remove_group); |