1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
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 |
6 | * |
7 | * Based on sysfs: |
8 | * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel |
9 | * |
10 | * configfs Copyright (C) 2005 Oracle. All rights reserved. |
11 | */ |
12 | |
13 | #include <linux/init.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> |
16 | #include <linux/slab.h> |
17 | #include <linux/configfs.h> |
18 | |
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 | |
37 | static inline struct childless *to_childless(struct config_item *item) |
38 | { |
39 | return container_of(to_configfs_subsystem(to_config_group(item)), |
40 | struct childless, subsys); |
41 | } |
42 | |
43 | static ssize_t childless_showme_show(struct config_item *item, char *page) |
44 | { |
45 | struct childless *childless = to_childless(item); |
46 | ssize_t pos; |
47 | |
48 | pos = sprintf(buf: page, fmt: "%d\n" , childless->showme); |
49 | childless->showme++; |
50 | |
51 | return pos; |
52 | } |
53 | |
54 | static ssize_t childless_storeme_show(struct config_item *item, char *page) |
55 | { |
56 | return sprintf(buf: page, fmt: "%d\n" , to_childless(item)->storeme); |
57 | } |
58 | |
59 | static ssize_t childless_storeme_store(struct config_item *item, |
60 | const char *page, size_t count) |
61 | { |
62 | struct childless *childless = to_childless(item); |
63 | int ret; |
64 | |
65 | ret = kstrtoint(s: page, base: 10, res: &childless->storeme); |
66 | if (ret) |
67 | return ret; |
68 | |
69 | return count; |
70 | } |
71 | |
72 | static ssize_t childless_description_show(struct config_item *item, char *page) |
73 | { |
74 | return sprintf(buf: page, |
75 | fmt: "[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 | |
83 | CONFIGFS_ATTR_RO(childless_, showme); |
84 | CONFIGFS_ATTR(childless_, storeme); |
85 | CONFIGFS_ATTR_RO(childless_, description); |
86 | |
87 | static struct configfs_attribute *childless_attrs[] = { |
88 | &childless_attr_showme, |
89 | &childless_attr_storeme, |
90 | &childless_attr_description, |
91 | NULL, |
92 | }; |
93 | |
94 | static const struct config_item_type childless_type = { |
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 | |
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 | { |
128 | return container_of(item, struct simple_child, item); |
129 | } |
130 | |
131 | static ssize_t simple_child_storeme_show(struct config_item *item, char *page) |
132 | { |
133 | return sprintf(buf: page, fmt: "%d\n" , to_simple_child(item)->storeme); |
134 | } |
135 | |
136 | static ssize_t simple_child_storeme_store(struct config_item *item, |
137 | const char *page, size_t count) |
138 | { |
139 | struct simple_child *simple_child = to_simple_child(item); |
140 | int ret; |
141 | |
142 | ret = kstrtoint(s: page, base: 10, res: &simple_child->storeme); |
143 | if (ret) |
144 | return ret; |
145 | |
146 | return count; |
147 | } |
148 | |
149 | CONFIGFS_ATTR(simple_child_, storeme); |
150 | |
151 | static struct configfs_attribute *simple_child_attrs[] = { |
152 | &simple_child_attr_storeme, |
153 | NULL, |
154 | }; |
155 | |
156 | static void simple_child_release(struct config_item *item) |
157 | { |
158 | kfree(objp: to_simple_child(item)); |
159 | } |
160 | |
161 | static struct configfs_item_operations simple_child_item_ops = { |
162 | .release = simple_child_release, |
163 | }; |
164 | |
165 | static const struct config_item_type simple_child_type = { |
166 | .ct_item_ops = &simple_child_item_ops, |
167 | .ct_attrs = simple_child_attrs, |
168 | .ct_owner = THIS_MODULE, |
169 | }; |
170 | |
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 | { |
177 | return container_of(to_config_group(item), |
178 | struct simple_children, group); |
179 | } |
180 | |
181 | static struct config_item *simple_children_make_item(struct config_group *group, |
182 | const char *name) |
183 | { |
184 | struct simple_child *simple_child; |
185 | |
186 | simple_child = kzalloc(size: sizeof(struct simple_child), GFP_KERNEL); |
187 | if (!simple_child) |
188 | return ERR_PTR(error: -ENOMEM); |
189 | |
190 | config_item_init_type_name(item: &simple_child->item, name, |
191 | type: &simple_child_type); |
192 | |
193 | return &simple_child->item; |
194 | } |
195 | |
196 | static ssize_t simple_children_description_show(struct config_item *item, |
197 | char *page) |
198 | { |
199 | return sprintf(buf: page, |
200 | fmt: "[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 | |
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 | |
213 | static void simple_children_release(struct config_item *item) |
214 | { |
215 | kfree(objp: to_simple_children(item)); |
216 | } |
217 | |
218 | static struct configfs_item_operations simple_children_item_ops = { |
219 | .release = simple_children_release, |
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 | |
230 | static const struct config_item_type simple_children_type = { |
231 | .ct_item_ops = &simple_children_item_ops, |
232 | .ct_group_ops = &simple_children_group_ops, |
233 | .ct_attrs = simple_children_attrs, |
234 | .ct_owner = THIS_MODULE, |
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 | |
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 | |
258 | static struct config_group *group_children_make_group( |
259 | struct config_group *group, const char *name) |
260 | { |
261 | struct simple_children *simple_children; |
262 | |
263 | simple_children = kzalloc(size: sizeof(struct simple_children), |
264 | GFP_KERNEL); |
265 | if (!simple_children) |
266 | return ERR_PTR(error: -ENOMEM); |
267 | |
268 | config_group_init_type_name(group: &simple_children->group, name, |
269 | type: &simple_children_type); |
270 | |
271 | return &simple_children->group; |
272 | } |
273 | |
274 | static ssize_t group_children_description_show(struct config_item *item, |
275 | char *page) |
276 | { |
277 | return sprintf(buf: page, |
278 | fmt: "[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 | |
284 | CONFIGFS_ATTR_RO(group_children_, description); |
285 | |
286 | static struct configfs_attribute *group_children_attrs[] = { |
287 | &group_children_attr_description, |
288 | NULL, |
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 | |
299 | static const struct config_item_type group_children_type = { |
300 | .ct_group_ops = &group_children_group_ops, |
301 | .ct_attrs = group_children_attrs, |
302 | .ct_owner = THIS_MODULE, |
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 | { |
332 | struct configfs_subsystem *subsys; |
333 | int ret, i; |
334 | |
335 | for (i = 0; example_subsys[i]; i++) { |
336 | subsys = example_subsys[i]; |
337 | |
338 | config_group_init(group: &subsys->su_group); |
339 | mutex_init(&subsys->su_mutex); |
340 | ret = configfs_register_subsystem(subsys); |
341 | if (ret) { |
342 | pr_err("Error %d while registering subsystem %s\n" , |
343 | ret, subsys->su_group.cg_item.ci_namebuf); |
344 | goto out_unregister; |
345 | } |
346 | } |
347 | |
348 | return 0; |
349 | |
350 | out_unregister: |
351 | for (i--; i >= 0; i--) |
352 | configfs_unregister_subsystem(subsys: example_subsys[i]); |
353 | |
354 | return ret; |
355 | } |
356 | |
357 | static void __exit configfs_example_exit(void) |
358 | { |
359 | int i; |
360 | |
361 | for (i = 0; example_subsys[i]; i++) |
362 | configfs_unregister_subsystem(subsys: example_subsys[i]); |
363 | } |
364 | |
365 | module_init(configfs_example_init); |
366 | module_exit(configfs_example_exit); |
367 | MODULE_LICENSE("GPL" ); |
368 | |