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