2019-05-24 13:04:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-12-16 01:29:43 +03:00
/*
* vim : noexpandtab ts = 8 sts = 0 sw = 8 :
*
2008-06-19 06:29:05 +04:00
* configfs_example_macros . c - This file is a demonstration module
* containing a number of configfs subsystems . It uses the helper
* macros defined by configfs . h
2005-12-16 01:29:43 +03:00
*
* Based on sysfs :
2020-09-24 15:45:25 +03:00
* sysfs is Copyright ( C ) 2001 , 2002 , 2003 Patrick Mochel
2005-12-16 01:29:43 +03:00
*
* configfs Copyright ( C ) 2005 Oracle . All rights reserved .
*/
# include <linux/init.h>
2020-09-24 15:45:21 +03:00
# include <linux/kernel.h>
2005-12-16 01:29:43 +03:00
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/configfs.h>
/*
* 01 - childless
*
* This first example is a childless subsystem . It cannot create
* any config_items . It just has attributes .
*
* Note that we are enclosing the configfs_subsystem inside a container .
* This is not necessary if a subsystem has no attributes directly
* on the subsystem . See the next example , 02 - simple - children , for
* such a subsystem .
*/
struct childless {
struct configfs_subsystem subsys ;
int showme ;
int storeme ;
} ;
static inline struct childless * to_childless ( struct config_item * item )
{
2020-09-24 15:45:18 +03:00
return container_of ( to_configfs_subsystem ( to_config_group ( item ) ) ,
struct childless , subsys ) ;
2005-12-16 01:29:43 +03:00
}
2015-10-03 16:32:59 +03:00
static ssize_t childless_showme_show ( struct config_item * item , char * page )
2005-12-16 01:29:43 +03:00
{
2015-10-03 16:32:59 +03:00
struct childless * childless = to_childless ( item ) ;
2005-12-16 01:29:43 +03:00
ssize_t pos ;
pos = sprintf ( page , " %d \n " , childless - > showme ) ;
childless - > showme + + ;
return pos ;
}
2015-10-03 16:32:59 +03:00
static ssize_t childless_storeme_show ( struct config_item * item , char * page )
2005-12-16 01:29:43 +03:00
{
2015-10-03 16:32:59 +03:00
return sprintf ( page , " %d \n " , to_childless ( item ) - > storeme ) ;
2005-12-16 01:29:43 +03:00
}
2015-10-03 16:32:59 +03:00
static ssize_t childless_storeme_store ( struct config_item * item ,
const char * page , size_t count )
2005-12-16 01:29:43 +03:00
{
2015-10-03 16:32:59 +03:00
struct childless * childless = to_childless ( item ) ;
2020-09-24 15:45:21 +03:00
int ret ;
2005-12-16 01:29:43 +03:00
2020-09-24 15:45:21 +03:00
ret = kstrtoint ( page , 10 , & childless - > storeme ) ;
if ( ret )
return ret ;
2005-12-16 01:29:43 +03:00
return count ;
}
2015-10-03 16:32:59 +03:00
static ssize_t childless_description_show ( struct config_item * item , char * page )
2005-12-16 01:29:43 +03:00
{
return sprintf ( page ,
" [01-childless] \n "
" \n "
" The childless subsystem is the simplest possible subsystem in \n "
" configfs. It does not support the creation of child config_items. \n "
" It only has a few attributes. In fact, it isn't much different \n "
" than a directory in /proc. \n " ) ;
}
2015-10-03 16:32:59 +03:00
CONFIGFS_ATTR_RO ( childless_ , showme ) ;
CONFIGFS_ATTR ( childless_ , storeme ) ;
CONFIGFS_ATTR_RO ( childless_ , description ) ;
2005-12-16 01:29:43 +03:00
static struct configfs_attribute * childless_attrs [ ] = {
2015-10-03 16:32:59 +03:00
& childless_attr_showme ,
& childless_attr_storeme ,
& childless_attr_description ,
2005-12-16 01:29:43 +03:00
NULL ,
} ;
2017-10-16 18:18:54 +03:00
static const struct config_item_type childless_type = {
2005-12-16 01:29:43 +03:00
. ct_attrs = childless_attrs ,
. ct_owner = THIS_MODULE ,
} ;
static struct childless childless_subsys = {
. subsys = {
. su_group = {
. cg_item = {
. ci_namebuf = " 01-childless " ,
. ci_type = & childless_type ,
} ,
} ,
} ,
} ;
/* ----------------------------------------------------------------- */
/*
* 02 - simple - children
*
* This example merely has a simple one - attribute child . Note that
* there is no extra attribute structure , as the child ' s attribute is
* known from the get - go . Also , there is no container for the
* subsystem , as it has no attributes of its own .
*/
struct simple_child {
struct config_item item ;
int storeme ;
} ;
static inline struct simple_child * to_simple_child ( struct config_item * item )
{
2020-09-24 15:45:18 +03:00
return container_of ( item , struct simple_child , item ) ;
2005-12-16 01:29:43 +03:00
}
2015-10-03 16:32:59 +03:00
static ssize_t simple_child_storeme_show ( struct config_item * item , char * page )
2005-12-16 01:29:43 +03:00
{
2015-10-03 16:32:59 +03:00
return sprintf ( page , " %d \n " , to_simple_child ( item ) - > storeme ) ;
2005-12-16 01:29:43 +03:00
}
2015-10-03 16:32:59 +03:00
static ssize_t simple_child_storeme_store ( struct config_item * item ,
const char * page , size_t count )
2005-12-16 01:29:43 +03:00
{
struct simple_child * simple_child = to_simple_child ( item ) ;
2020-09-24 15:45:21 +03:00
int ret ;
2005-12-16 01:29:43 +03:00
2020-09-24 15:45:21 +03:00
ret = kstrtoint ( page , 10 , & simple_child - > storeme ) ;
if ( ret )
return ret ;
2005-12-16 01:29:43 +03:00
return count ;
}
2015-10-03 16:32:59 +03:00
CONFIGFS_ATTR ( simple_child_ , storeme ) ;
static struct configfs_attribute * simple_child_attrs [ ] = {
& simple_child_attr_storeme ,
NULL ,
} ;
2005-12-16 01:29:43 +03:00
static void simple_child_release ( struct config_item * item )
{
kfree ( to_simple_child ( item ) ) ;
}
static struct configfs_item_operations simple_child_item_ops = {
2020-09-24 15:45:20 +03:00
. release = simple_child_release ,
2005-12-16 01:29:43 +03:00
} ;
2017-10-16 18:18:54 +03:00
static const struct config_item_type simple_child_type = {
2005-12-16 01:29:43 +03:00
. ct_item_ops = & simple_child_item_ops ,
. ct_attrs = simple_child_attrs ,
. ct_owner = THIS_MODULE ,
} ;
2006-04-13 05:34:43 +04:00
struct simple_children {
struct config_group group ;
} ;
static inline struct simple_children * to_simple_children ( struct config_item * item )
{
2020-09-24 15:45:18 +03:00
return container_of ( to_config_group ( item ) ,
struct simple_children , group ) ;
2006-04-13 05:34:43 +04:00
}
2015-10-03 16:32:59 +03:00
static struct config_item * simple_children_make_item ( struct config_group * group ,
const char * name )
2005-12-16 01:29:43 +03:00
{
struct simple_child * simple_child ;
some kmalloc/memset ->kzalloc (tree wide)
Transform some calls to kmalloc/memset to a single kzalloc (or kcalloc).
Here is a short excerpt of the semantic patch performing
this transformation:
@@
type T2;
expression x;
identifier f,fld;
expression E;
expression E1,E2;
expression e1,e2,e3,y;
statement S;
@@
x =
- kmalloc
+ kzalloc
(E1,E2)
... when != \(x->fld=E;\|y=f(...,x,...);\|f(...,x,...);\|x=E;\|while(...) S\|for(e1;e2;e3) S\)
- memset((T2)x,0,E1);
@@
expression E1,E2,E3;
@@
- kzalloc(E1 * E2,E3)
+ kcalloc(E1,E2,E3)
[akpm@linux-foundation.org: get kcalloc args the right way around]
Signed-off-by: Yoann Padioleau <padator@wanadoo.fr>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <bryan.wu@analog.com>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Dave Airlie <airlied@linux.ie>
Acked-by: Roland Dreier <rolandd@cisco.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Acked-by: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Greg KH <greg@kroah.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 12:49:03 +04:00
simple_child = kzalloc ( sizeof ( struct simple_child ) , GFP_KERNEL ) ;
2005-12-16 01:29:43 +03:00
if ( ! simple_child )
2008-07-18 02:21:29 +04:00
return ERR_PTR ( - ENOMEM ) ;
2005-12-16 01:29:43 +03:00
config_item_init_type_name ( & simple_child - > item , name ,
& simple_child_type ) ;
2008-07-18 01:53:48 +04:00
return & simple_child - > item ;
2005-12-16 01:29:43 +03:00
}
2015-10-03 16:32:59 +03:00
static ssize_t simple_children_description_show ( struct config_item * item ,
char * page )
2005-12-16 01:29:43 +03:00
{
return sprintf ( page ,
" [02-simple-children] \n "
" \n "
" This subsystem allows the creation of child config_items. These \n "
" items have only one attribute that is readable and writeable. \n " ) ;
}
2015-10-03 16:32:59 +03:00
CONFIGFS_ATTR_RO ( simple_children_ , description ) ;
static struct configfs_attribute * simple_children_attrs [ ] = {
& simple_children_attr_description ,
NULL ,
} ;
2006-04-13 05:34:43 +04:00
static void simple_children_release ( struct config_item * item )
{
kfree ( to_simple_children ( item ) ) ;
}
2005-12-16 01:29:43 +03:00
static struct configfs_item_operations simple_children_item_ops = {
2008-06-19 06:29:05 +04:00
. release = simple_children_release ,
2005-12-16 01:29:43 +03:00
} ;
/*
* Note that , since no extra work is required on - > drop_item ( ) ,
* no - > drop_item ( ) is provided .
*/
static struct configfs_group_operations simple_children_group_ops = {
. make_item = simple_children_make_item ,
} ;
2017-10-16 18:18:54 +03:00
static const struct config_item_type simple_children_type = {
2005-12-16 01:29:43 +03:00
. ct_item_ops = & simple_children_item_ops ,
. ct_group_ops = & simple_children_group_ops ,
. ct_attrs = simple_children_attrs ,
2006-01-26 00:31:07 +03:00
. ct_owner = THIS_MODULE ,
2005-12-16 01:29:43 +03:00
} ;
static struct configfs_subsystem simple_children_subsys = {
. su_group = {
. cg_item = {
. ci_namebuf = " 02-simple-children " ,
. ci_type = & simple_children_type ,
} ,
} ,
} ;
/* ----------------------------------------------------------------- */
/*
* 03 - group - children
*
* This example reuses the simple_children group from above . However ,
* the simple_children group is not the subsystem itself , it is a
* child of the subsystem . Creation of a group in the subsystem creates
* a new simple_children group . That group can then have simple_child
* children of its own .
*/
2015-10-03 16:32:59 +03:00
static struct config_group * group_children_make_group (
struct config_group * group , const char * name )
2005-12-16 01:29:43 +03:00
{
struct simple_children * simple_children ;
some kmalloc/memset ->kzalloc (tree wide)
Transform some calls to kmalloc/memset to a single kzalloc (or kcalloc).
Here is a short excerpt of the semantic patch performing
this transformation:
@@
type T2;
expression x;
identifier f,fld;
expression E;
expression E1,E2;
expression e1,e2,e3,y;
statement S;
@@
x =
- kmalloc
+ kzalloc
(E1,E2)
... when != \(x->fld=E;\|y=f(...,x,...);\|f(...,x,...);\|x=E;\|while(...) S\|for(e1;e2;e3) S\)
- memset((T2)x,0,E1);
@@
expression E1,E2,E3;
@@
- kzalloc(E1 * E2,E3)
+ kcalloc(E1,E2,E3)
[akpm@linux-foundation.org: get kcalloc args the right way around]
Signed-off-by: Yoann Padioleau <padator@wanadoo.fr>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <bryan.wu@analog.com>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Dave Airlie <airlied@linux.ie>
Acked-by: Roland Dreier <rolandd@cisco.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Acked-by: Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Acked-by: Greg KH <greg@kroah.com>
Cc: James Bottomley <James.Bottomley@steeleye.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-07-19 12:49:03 +04:00
simple_children = kzalloc ( sizeof ( struct simple_children ) ,
2005-12-16 01:29:43 +03:00
GFP_KERNEL ) ;
if ( ! simple_children )
2008-07-18 02:21:29 +04:00
return ERR_PTR ( - ENOMEM ) ;
2005-12-16 01:29:43 +03:00
config_group_init_type_name ( & simple_children - > group , name ,
& simple_children_type ) ;
2008-07-18 01:53:48 +04:00
return & simple_children - > group ;
2005-12-16 01:29:43 +03:00
}
2015-10-03 16:32:59 +03:00
static ssize_t group_children_description_show ( struct config_item * item ,
char * page )
2005-12-16 01:29:43 +03:00
{
return sprintf ( page ,
" [03-group-children] \n "
" \n "
" This subsystem allows the creation of child config_groups. These \n "
" groups are like the subsystem simple-children. \n " ) ;
}
2015-10-03 16:32:59 +03:00
CONFIGFS_ATTR_RO ( group_children_ , description ) ;
static struct configfs_attribute * group_children_attrs [ ] = {
& group_children_attr_description ,
NULL ,
2005-12-16 01:29:43 +03:00
} ;
/*
* Note that , since no extra work is required on - > drop_item ( ) ,
* no - > drop_item ( ) is provided .
*/
static struct configfs_group_operations group_children_group_ops = {
. make_group = group_children_make_group ,
} ;
2017-10-16 18:18:54 +03:00
static const struct config_item_type group_children_type = {
2005-12-16 01:29:43 +03:00
. ct_group_ops = & group_children_group_ops ,
. ct_attrs = group_children_attrs ,
2006-01-26 00:31:07 +03:00
. ct_owner = THIS_MODULE ,
2005-12-16 01:29:43 +03:00
} ;
static struct configfs_subsystem group_children_subsys = {
. su_group = {
. cg_item = {
. ci_namebuf = " 03-group-children " ,
. ci_type = & group_children_type ,
} ,
} ,
} ;
/* ----------------------------------------------------------------- */
/*
* We ' re now done with our subsystem definitions .
* For convenience in this module , here ' s a list of them all . It
* allows the init function to easily register them . Most modules
* will only have one subsystem , and will only call register_subsystem
* on it directly .
*/
static struct configfs_subsystem * example_subsys [ ] = {
& childless_subsys . subsys ,
& simple_children_subsys ,
& group_children_subsys ,
NULL ,
} ;
static int __init configfs_example_init ( void )
{
struct configfs_subsystem * subsys ;
2020-09-24 15:45:24 +03:00
int ret , i ;
2005-12-16 01:29:43 +03:00
for ( i = 0 ; example_subsys [ i ] ; i + + ) {
subsys = example_subsys [ i ] ;
config_group_init ( & subsys - > su_group ) ;
2007-07-07 10:33:17 +04:00
mutex_init ( & subsys - > su_mutex ) ;
2005-12-16 01:29:43 +03:00
ret = configfs_register_subsystem ( subsys ) ;
if ( ret ) {
2020-09-24 15:45:26 +03:00
pr_err ( " Error %d while registering subsystem %s \n " ,
ret , subsys - > su_group . cg_item . ci_namebuf ) ;
2005-12-16 01:29:43 +03:00
goto out_unregister ;
}
}
return 0 ;
out_unregister :
2011-05-27 03:25:17 +04:00
for ( i - - ; i > = 0 ; i - - )
2005-12-16 01:29:43 +03:00
configfs_unregister_subsystem ( example_subsys [ i ] ) ;
return ret ;
}
static void __exit configfs_example_exit ( void )
{
int i ;
2011-05-27 03:25:17 +04:00
for ( i = 0 ; example_subsys [ i ] ; i + + )
2005-12-16 01:29:43 +03:00
configfs_unregister_subsystem ( example_subsys [ i ] ) ;
}
module_init ( configfs_example_init ) ;
module_exit ( configfs_example_exit ) ;
MODULE_LICENSE ( " GPL " ) ;