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