Commit | Line | Data |
---|---|---|
328970de | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
7063fbf2 | 2 | /* |
ecb3d28c JB |
3 | * configfs_example_macros.c - This file is a demonstration module |
4 | * containing a number of configfs subsystems. It uses the helper | |
5 | * macros defined by configfs.h | |
7063fbf2 | 6 | * |
7063fbf2 | 7 | * Based on sysfs: |
288f295e | 8 | * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel |
7063fbf2 JB |
9 | * |
10 | * configfs Copyright (C) 2005 Oracle. All rights reserved. | |
11 | */ | |
12 | ||
13 | #include <linux/init.h> | |
b86ff67d | 14 | #include <linux/kernel.h> |
7063fbf2 JB |
15 | #include <linux/module.h> |
16 | #include <linux/slab.h> | |
7063fbf2 JB |
17 | #include <linux/configfs.h> |
18 | ||
7063fbf2 JB |
19 | /* |
20 | * 01-childless | |
21 | * | |
22 | * This first example is a childless subsystem. It cannot create | |
23 | * any config_items. It just has attributes. | |
24 | * | |
25 | * Note that we are enclosing the configfs_subsystem inside a container. | |
26 | * This is not necessary if a subsystem has no attributes directly | |
27 | * on the subsystem. See the next example, 02-simple-children, for | |
28 | * such a subsystem. | |
29 | */ | |
30 | ||
31 | struct childless { | |
32 | struct configfs_subsystem subsys; | |
33 | int showme; | |
34 | int storeme; | |
35 | }; | |
36 | ||
7063fbf2 JB |
37 | static inline struct childless *to_childless(struct config_item *item) |
38 | { | |
e0ee1fdb BG |
39 | return container_of(to_configfs_subsystem(to_config_group(item)), |
40 | struct childless, subsys); | |
7063fbf2 JB |
41 | } |
42 | ||
51798222 | 43 | static ssize_t childless_showme_show(struct config_item *item, char *page) |
7063fbf2 | 44 | { |
51798222 | 45 | struct childless *childless = to_childless(item); |
7063fbf2 JB |
46 | ssize_t pos; |
47 | ||
48 | pos = sprintf(page, "%d\n", childless->showme); | |
49 | childless->showme++; | |
50 | ||
51 | return pos; | |
52 | } | |
53 | ||
51798222 | 54 | static ssize_t childless_storeme_show(struct config_item *item, char *page) |
7063fbf2 | 55 | { |
51798222 | 56 | return sprintf(page, "%d\n", to_childless(item)->storeme); |
7063fbf2 JB |
57 | } |
58 | ||
51798222 CH |
59 | static ssize_t childless_storeme_store(struct config_item *item, |
60 | const char *page, size_t count) | |
7063fbf2 | 61 | { |
51798222 | 62 | struct childless *childless = to_childless(item); |
b86ff67d | 63 | int ret; |
7063fbf2 | 64 | |
b86ff67d BG |
65 | ret = kstrtoint(page, 10, &childless->storeme); |
66 | if (ret) | |
67 | return ret; | |
7063fbf2 JB |
68 | |
69 | return count; | |
70 | } | |
71 | ||
51798222 | 72 | static ssize_t childless_description_show(struct config_item *item, char *page) |
7063fbf2 JB |
73 | { |
74 | return sprintf(page, | |
75 | "[01-childless]\n" | |
76 | "\n" | |
77 | "The childless subsystem is the simplest possible subsystem in\n" | |
78 | "configfs. It does not support the creation of child config_items.\n" | |
79 | "It only has a few attributes. In fact, it isn't much different\n" | |
80 | "than a directory in /proc.\n"); | |
81 | } | |
82 | ||
51798222 CH |
83 | CONFIGFS_ATTR_RO(childless_, showme); |
84 | CONFIGFS_ATTR(childless_, storeme); | |
85 | CONFIGFS_ATTR_RO(childless_, description); | |
7063fbf2 JB |
86 | |
87 | static struct configfs_attribute *childless_attrs[] = { | |
51798222 CH |
88 | &childless_attr_showme, |
89 | &childless_attr_storeme, | |
90 | &childless_attr_description, | |
7063fbf2 JB |
91 | NULL, |
92 | }; | |
93 | ||
84c43674 | 94 | static const struct config_item_type childless_type = { |
7063fbf2 JB |
95 | .ct_attrs = childless_attrs, |
96 | .ct_owner = THIS_MODULE, | |
97 | }; | |
98 | ||
99 | static struct childless childless_subsys = { | |
100 | .subsys = { | |
101 | .su_group = { | |
102 | .cg_item = { | |
103 | .ci_namebuf = "01-childless", | |
104 | .ci_type = &childless_type, | |
105 | }, | |
106 | }, | |
107 | }, | |
108 | }; | |
109 | ||
7063fbf2 JB |
110 | /* ----------------------------------------------------------------- */ |
111 | ||
112 | /* | |
113 | * 02-simple-children | |
114 | * | |
115 | * This example merely has a simple one-attribute child. Note that | |
116 | * there is no extra attribute structure, as the child's attribute is | |
117 | * known from the get-go. Also, there is no container for the | |
118 | * subsystem, as it has no attributes of its own. | |
119 | */ | |
120 | ||
121 | struct simple_child { | |
122 | struct config_item item; | |
123 | int storeme; | |
124 | }; | |
125 | ||
126 | static inline struct simple_child *to_simple_child(struct config_item *item) | |
127 | { | |
e0ee1fdb | 128 | return container_of(item, struct simple_child, item); |
7063fbf2 JB |
129 | } |
130 | ||
51798222 | 131 | static ssize_t simple_child_storeme_show(struct config_item *item, char *page) |
7063fbf2 | 132 | { |
51798222 | 133 | return sprintf(page, "%d\n", to_simple_child(item)->storeme); |
7063fbf2 JB |
134 | } |
135 | ||
51798222 CH |
136 | static ssize_t simple_child_storeme_store(struct config_item *item, |
137 | const char *page, size_t count) | |
7063fbf2 JB |
138 | { |
139 | struct simple_child *simple_child = to_simple_child(item); | |
b86ff67d | 140 | int ret; |
7063fbf2 | 141 | |
b86ff67d BG |
142 | ret = kstrtoint(page, 10, &simple_child->storeme); |
143 | if (ret) | |
144 | return ret; | |
7063fbf2 JB |
145 | |
146 | return count; | |
147 | } | |
148 | ||
51798222 CH |
149 | CONFIGFS_ATTR(simple_child_, storeme); |
150 | ||
151 | static struct configfs_attribute *simple_child_attrs[] = { | |
152 | &simple_child_attr_storeme, | |
153 | NULL, | |
154 | }; | |
155 | ||
7063fbf2 JB |
156 | static void simple_child_release(struct config_item *item) |
157 | { | |
158 | kfree(to_simple_child(item)); | |
159 | } | |
160 | ||
161 | static struct configfs_item_operations simple_child_item_ops = { | |
1b0d36e8 | 162 | .release = simple_child_release, |
7063fbf2 JB |
163 | }; |
164 | ||
84c43674 | 165 | static const struct config_item_type simple_child_type = { |
7063fbf2 JB |
166 | .ct_item_ops = &simple_child_item_ops, |
167 | .ct_attrs = simple_child_attrs, | |
168 | .ct_owner = THIS_MODULE, | |
169 | }; | |
170 | ||
22dd0e88 JB |
171 | struct simple_children { |
172 | struct config_group group; | |
173 | }; | |
174 | ||
175 | static inline struct simple_children *to_simple_children(struct config_item *item) | |
176 | { | |
e0ee1fdb BG |
177 | return container_of(to_config_group(item), |
178 | struct simple_children, group); | |
22dd0e88 JB |
179 | } |
180 | ||
51798222 CH |
181 | static struct config_item *simple_children_make_item(struct config_group *group, |
182 | const char *name) | |
7063fbf2 JB |
183 | { |
184 | struct simple_child *simple_child; | |
185 | ||
dd00cc48 | 186 | simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL); |
7063fbf2 | 187 | if (!simple_child) |
a6795e9e | 188 | return ERR_PTR(-ENOMEM); |
7063fbf2 | 189 | |
7063fbf2 JB |
190 | config_item_init_type_name(&simple_child->item, name, |
191 | &simple_child_type); | |
192 | ||
f89ab861 | 193 | return &simple_child->item; |
7063fbf2 JB |
194 | } |
195 | ||
51798222 CH |
196 | static ssize_t simple_children_description_show(struct config_item *item, |
197 | char *page) | |
7063fbf2 JB |
198 | { |
199 | return sprintf(page, | |
200 | "[02-simple-children]\n" | |
201 | "\n" | |
202 | "This subsystem allows the creation of child config_items. These\n" | |
203 | "items have only one attribute that is readable and writeable.\n"); | |
204 | } | |
205 | ||
51798222 CH |
206 | CONFIGFS_ATTR_RO(simple_children_, description); |
207 | ||
208 | static struct configfs_attribute *simple_children_attrs[] = { | |
209 | &simple_children_attr_description, | |
210 | NULL, | |
211 | }; | |
212 | ||
22dd0e88 JB |
213 | static void simple_children_release(struct config_item *item) |
214 | { | |
215 | kfree(to_simple_children(item)); | |
216 | } | |
217 | ||
7063fbf2 | 218 | static struct configfs_item_operations simple_children_item_ops = { |
ecb3d28c | 219 | .release = simple_children_release, |
7063fbf2 JB |
220 | }; |
221 | ||
222 | /* | |
223 | * Note that, since no extra work is required on ->drop_item(), | |
224 | * no ->drop_item() is provided. | |
225 | */ | |
226 | static struct configfs_group_operations simple_children_group_ops = { | |
227 | .make_item = simple_children_make_item, | |
228 | }; | |
229 | ||
84c43674 | 230 | static const struct config_item_type simple_children_type = { |
7063fbf2 JB |
231 | .ct_item_ops = &simple_children_item_ops, |
232 | .ct_group_ops = &simple_children_group_ops, | |
233 | .ct_attrs = simple_children_attrs, | |
3d0f89bb | 234 | .ct_owner = THIS_MODULE, |
7063fbf2 JB |
235 | }; |
236 | ||
237 | static struct configfs_subsystem simple_children_subsys = { | |
238 | .su_group = { | |
239 | .cg_item = { | |
240 | .ci_namebuf = "02-simple-children", | |
241 | .ci_type = &simple_children_type, | |
242 | }, | |
243 | }, | |
244 | }; | |
245 | ||
7063fbf2 JB |
246 | /* ----------------------------------------------------------------- */ |
247 | ||
248 | /* | |
249 | * 03-group-children | |
250 | * | |
251 | * This example reuses the simple_children group from above. However, | |
252 | * the simple_children group is not the subsystem itself, it is a | |
253 | * child of the subsystem. Creation of a group in the subsystem creates | |
254 | * a new simple_children group. That group can then have simple_child | |
255 | * children of its own. | |
256 | */ | |
257 | ||
51798222 CH |
258 | static struct config_group *group_children_make_group( |
259 | struct config_group *group, const char *name) | |
7063fbf2 JB |
260 | { |
261 | struct simple_children *simple_children; | |
262 | ||
dd00cc48 | 263 | simple_children = kzalloc(sizeof(struct simple_children), |
7063fbf2 JB |
264 | GFP_KERNEL); |
265 | if (!simple_children) | |
a6795e9e | 266 | return ERR_PTR(-ENOMEM); |
7063fbf2 | 267 | |
7063fbf2 JB |
268 | config_group_init_type_name(&simple_children->group, name, |
269 | &simple_children_type); | |
270 | ||
f89ab861 | 271 | return &simple_children->group; |
7063fbf2 JB |
272 | } |
273 | ||
51798222 CH |
274 | static ssize_t group_children_description_show(struct config_item *item, |
275 | char *page) | |
7063fbf2 JB |
276 | { |
277 | return sprintf(page, | |
278 | "[03-group-children]\n" | |
279 | "\n" | |
280 | "This subsystem allows the creation of child config_groups. These\n" | |
281 | "groups are like the subsystem simple-children.\n"); | |
282 | } | |
283 | ||
51798222 CH |
284 | CONFIGFS_ATTR_RO(group_children_, description); |
285 | ||
286 | static struct configfs_attribute *group_children_attrs[] = { | |
287 | &group_children_attr_description, | |
288 | NULL, | |
7063fbf2 JB |
289 | }; |
290 | ||
291 | /* | |
292 | * Note that, since no extra work is required on ->drop_item(), | |
293 | * no ->drop_item() is provided. | |
294 | */ | |
295 | static struct configfs_group_operations group_children_group_ops = { | |
296 | .make_group = group_children_make_group, | |
297 | }; | |
298 | ||
84c43674 | 299 | static const struct config_item_type group_children_type = { |
7063fbf2 JB |
300 | .ct_group_ops = &group_children_group_ops, |
301 | .ct_attrs = group_children_attrs, | |
3d0f89bb | 302 | .ct_owner = THIS_MODULE, |
7063fbf2 JB |
303 | }; |
304 | ||
305 | static struct configfs_subsystem group_children_subsys = { | |
306 | .su_group = { | |
307 | .cg_item = { | |
308 | .ci_namebuf = "03-group-children", | |
309 | .ci_type = &group_children_type, | |
310 | }, | |
311 | }, | |
312 | }; | |
313 | ||
314 | /* ----------------------------------------------------------------- */ | |
315 | ||
316 | /* | |
317 | * We're now done with our subsystem definitions. | |
318 | * For convenience in this module, here's a list of them all. It | |
319 | * allows the init function to easily register them. Most modules | |
320 | * will only have one subsystem, and will only call register_subsystem | |
321 | * on it directly. | |
322 | */ | |
323 | static struct configfs_subsystem *example_subsys[] = { | |
324 | &childless_subsys.subsys, | |
325 | &simple_children_subsys, | |
326 | &group_children_subsys, | |
327 | NULL, | |
328 | }; | |
329 | ||
330 | static int __init configfs_example_init(void) | |
331 | { | |
7063fbf2 | 332 | struct configfs_subsystem *subsys; |
4e415a84 | 333 | int ret, i; |
7063fbf2 JB |
334 | |
335 | for (i = 0; example_subsys[i]; i++) { | |
336 | subsys = example_subsys[i]; | |
337 | ||
338 | config_group_init(&subsys->su_group); | |
e6bd07ae | 339 | mutex_init(&subsys->su_mutex); |
7063fbf2 JB |
340 | ret = configfs_register_subsystem(subsys); |
341 | if (ret) { | |
76ecfcb0 BG |
342 | pr_err("Error %d while registering subsystem %s\n", |
343 | ret, subsys->su_group.cg_item.ci_namebuf); | |
7063fbf2 JB |
344 | goto out_unregister; |
345 | } | |
346 | } | |
347 | ||
348 | return 0; | |
349 | ||
350 | out_unregister: | |
dcb3a08e | 351 | for (i--; i >= 0; i--) |
7063fbf2 | 352 | configfs_unregister_subsystem(example_subsys[i]); |
7063fbf2 JB |
353 | |
354 | return ret; | |
355 | } | |
356 | ||
357 | static void __exit configfs_example_exit(void) | |
358 | { | |
359 | int i; | |
360 | ||
dcb3a08e | 361 | for (i = 0; example_subsys[i]; i++) |
7063fbf2 | 362 | configfs_unregister_subsystem(example_subsys[i]); |
7063fbf2 JB |
363 | } |
364 | ||
365 | module_init(configfs_example_init); | |
366 | module_exit(configfs_example_exit); | |
367 | MODULE_LICENSE("GPL"); |