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