[PATCH] configfs: Convenience macros for attribute definition.

Sysfs has the _ATTR() and _ATTR_RO() macros to make defining extended
form attributes easier.  configfs should have something similiar.

- _CONFIGFS_ATTR() and _CONFIGFS_ATTR_RO() are the counterparts to the
  sysfs macros.
- CONFIGFS_ATTR_STRUCT() creates the extended form attribute structure.
- CONFIGFS_ATTR_OPS() defines the show_attribute()/store_attribute()
  operations that call the show()/store() operations of the extended
  form configfs_attributes.

Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
index 44c97e6..fabcb0e 100644
--- a/Documentation/filesystems/configfs/configfs.txt
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -311,9 +311,20 @@
 [An Example]
 
 The best example of these basic concepts is the simple_children
-subsystem/group and the simple_child item in configfs_example.c  It
-shows a trivial object displaying and storing an attribute, and a simple
-group creating and destroying these children.
+subsystem/group and the simple_child item in configfs_example_explicit.c
+and configfs_example_macros.c.  It shows a trivial object displaying and
+storing an attribute, and a simple group creating and destroying these
+children.
+
+The only difference between configfs_example_explicit.c and
+configfs_example_macros.c is how the attributes of the childless item
+are defined.  The childless item has extended attributes, each with
+their own show()/store() operation.  This follows a convention commonly
+used in sysfs.  configfs_example_explicit.c creates these attributes
+by explicitly defining the structures involved.  Conversely
+configfs_example_macros.c uses some convenience macros from configfs.h
+to define the attributes.  These macros are similar to their sysfs
+counterparts.
 
 [Hierarchy Navigation and the Subsystem Mutex]
 
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example_explicit.c
similarity index 96%
rename from Documentation/filesystems/configfs/configfs_example.c
rename to Documentation/filesystems/configfs/configfs_example_explicit.c
index 03964879..d428cc9 100644
--- a/Documentation/filesystems/configfs/configfs_example.c
+++ b/Documentation/filesystems/configfs/configfs_example_explicit.c
@@ -1,8 +1,10 @@
 /*
  * vim: noexpandtab ts=8 sts=0 sw=8:
  *
- * configfs_example.c - This file is a demonstration module containing
- *      a number of configfs subsystems.
+ * configfs_example_explicit.c - This file is a demonstration module
+ *      containing a number of configfs subsystems.  It explicitly defines
+ *      each structure without using the helper macros defined in
+ *      configfs.h.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -281,7 +283,6 @@
 	if (!simple_child)
 		return ERR_PTR(-ENOMEM);
 
-
 	config_item_init_type_name(&simple_child->item, name,
 				   &simple_child_type);
 
@@ -302,8 +303,8 @@
 };
 
 static ssize_t simple_children_attr_show(struct config_item *item,
-			   		 struct configfs_attribute *attr,
-			   		 char *page)
+					 struct configfs_attribute *attr,
+					 char *page)
 {
 	return sprintf(page,
 "[02-simple-children]\n"
@@ -318,7 +319,7 @@
 }
 
 static struct configfs_item_operations simple_children_item_ops = {
-	.release 	= simple_children_release,
+	.release	= simple_children_release,
 	.show_attribute	= simple_children_attr_show,
 };
 
@@ -368,7 +369,6 @@
 	if (!simple_children)
 		return ERR_PTR(-ENOMEM);
 
-
 	config_group_init_type_name(&simple_children->group, name,
 				    &simple_children_type);
 
@@ -387,8 +387,8 @@
 };
 
 static ssize_t group_children_attr_show(struct config_item *item,
-			   		struct configfs_attribute *attr,
-			   		char *page)
+					struct configfs_attribute *attr,
+					char *page)
 {
 	return sprintf(page,
 "[03-group-children]\n"
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example_macros.c
similarity index 84%
copy from Documentation/filesystems/configfs/configfs_example.c
copy to Documentation/filesystems/configfs/configfs_example_macros.c
index 03964879..d8e30a0 100644
--- a/Documentation/filesystems/configfs/configfs_example.c
+++ b/Documentation/filesystems/configfs/configfs_example_macros.c
@@ -1,8 +1,9 @@
 /*
  * vim: noexpandtab ts=8 sts=0 sw=8:
  *
- * configfs_example.c - This file is a demonstration module containing
- *      a number of configfs subsystems.
+ * 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
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -51,17 +52,17 @@
 	int storeme;
 };
 
-struct childless_attribute {
-	struct configfs_attribute attr;
-	ssize_t (*show)(struct childless *, char *);
-	ssize_t (*store)(struct childless *, const char *, size_t);
-};
-
 static inline struct childless *to_childless(struct config_item *item)
 {
 	return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
 }
 
+CONFIGFS_ATTR_STRUCT(childless);
+#define CHILDLESS_ATTR(_name, _mode, _show, _store)	\
+struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
+#define CHILDLESS_ATTR_RO(_name, _show)	\
+struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR_RO(_name, _show);
+
 static ssize_t childless_showme_read(struct childless *childless,
 				     char *page)
 {
@@ -110,19 +111,10 @@
 "than a directory in /proc.\n");
 }
 
-static struct childless_attribute childless_attr_showme = {
-	.attr	= { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
-	.show	= childless_showme_read,
-};
-static struct childless_attribute childless_attr_storeme = {
-	.attr	= { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
-	.show	= childless_storeme_read,
-	.store	= childless_storeme_write,
-};
-static struct childless_attribute childless_attr_description = {
-	.attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
-	.show = childless_description_read,
-};
+CHILDLESS_ATTR_RO(showme, childless_showme_read);
+CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read,
+	       childless_storeme_write);
+CHILDLESS_ATTR_RO(description, childless_description_read);
 
 static struct configfs_attribute *childless_attrs[] = {
 	&childless_attr_showme.attr,
@@ -131,34 +123,7 @@
 	NULL,
 };
 
-static ssize_t childless_attr_show(struct config_item *item,
-				   struct configfs_attribute *attr,
-				   char *page)
-{
-	struct childless *childless = to_childless(item);
-	struct childless_attribute *childless_attr =
-		container_of(attr, struct childless_attribute, attr);
-	ssize_t ret = 0;
-
-	if (childless_attr->show)
-		ret = childless_attr->show(childless, page);
-	return ret;
-}
-
-static ssize_t childless_attr_store(struct config_item *item,
-				    struct configfs_attribute *attr,
-				    const char *page, size_t count)
-{
-	struct childless *childless = to_childless(item);
-	struct childless_attribute *childless_attr =
-		container_of(attr, struct childless_attribute, attr);
-	ssize_t ret = -EINVAL;
-
-	if (childless_attr->store)
-		ret = childless_attr->store(childless, page, count);
-	return ret;
-}
-
+CONFIGFS_ATTR_OPS(childless);
 static struct configfs_item_operations childless_item_ops = {
 	.show_attribute		= childless_attr_show,
 	.store_attribute	= childless_attr_store,
@@ -281,7 +246,6 @@
 	if (!simple_child)
 		return ERR_PTR(-ENOMEM);
 
-
 	config_item_init_type_name(&simple_child->item, name,
 				   &simple_child_type);
 
@@ -302,8 +266,8 @@
 };
 
 static ssize_t simple_children_attr_show(struct config_item *item,
-			   		 struct configfs_attribute *attr,
-			   		 char *page)
+					 struct configfs_attribute *attr,
+					 char *page)
 {
 	return sprintf(page,
 "[02-simple-children]\n"
@@ -318,7 +282,7 @@
 }
 
 static struct configfs_item_operations simple_children_item_ops = {
-	.release 	= simple_children_release,
+	.release	= simple_children_release,
 	.show_attribute	= simple_children_attr_show,
 };
 
@@ -368,7 +332,6 @@
 	if (!simple_children)
 		return ERR_PTR(-ENOMEM);
 
-
 	config_group_init_type_name(&simple_children->group, name,
 				    &simple_children_type);
 
@@ -387,8 +350,8 @@
 };
 
 static ssize_t group_children_attr_show(struct config_item *item,
-			   		struct configfs_attribute *attr,
-			   		char *page)
+					struct configfs_attribute *attr,
+					char *page)
 {
 	return sprintf(page,
 "[03-group-children]\n"
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index 0a5491b..7f62777 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -130,8 +130,25 @@
 /*
  * Users often need to create attribute structures for their configurable
  * attributes, containing a configfs_attribute member and function pointers
- * for the show() and store() operations on that attribute. They can use
- * this macro (similar to sysfs' __ATTR) to make defining attributes easier.
+ * for the show() and store() operations on that attribute. If they don't
+ * need anything else on the extended attribute structure, they can use
+ * this macro to define it  The argument _item is the name of the
+ * config_item structure.
+ */
+#define CONFIGFS_ATTR_STRUCT(_item)					\
+struct _item##_attribute {						\
+	struct configfs_attribute attr;					\
+	ssize_t (*show)(struct _item *, char *);			\
+	ssize_t (*store)(struct _item *, const char *, size_t);		\
+}
+
+/*
+ * With the extended attribute structure, users can use this macro
+ * (similar to sysfs' __ATTR) to make defining attributes easier.
+ * An example:
+ * #define MYITEM_ATTR(_name, _mode, _show, _store)	\
+ * struct myitem_attribute childless_attr_##_name =	\
+ *         __CONFIGFS_ATTR(_name, _mode, _show, _store)
  */
 #define __CONFIGFS_ATTR(_name, _mode, _show, _store)			\
 {									\
@@ -143,6 +160,52 @@
 	.show	= _show,						\
 	.store	= _store,						\
 }
+/* Here is a readonly version, only requiring a show() operation */
+#define __CONFIGFS_ATTR_RO(_name, _show)				\
+{									\
+	.attr	= {							\
+			.ca_name = __stringify(_name),			\
+			.ca_mode = 0444,				\
+			.ca_owner = THIS_MODULE,			\
+	},								\
+	.show	= _show,						\
+}
+
+/*
+ * With these extended attributes, the simple show_attribute() and
+ * store_attribute() operations need to call the show() and store() of the
+ * attributes.  This is a common pattern, so we provide a macro to define
+ * them.  The argument _item is the name of the config_item structure.
+ * This macro expects the attributes to be named "struct <name>_attribute"
+ * and the function to_<name>() to exist;
+ */
+#define CONFIGFS_ATTR_OPS(_item)					\
+static ssize_t _item##_attr_show(struct config_item *item,		\
+				 struct configfs_attribute *attr,	\
+				 char *page)				\
+{									\
+	struct _item *_item = to_##_item(item);				\
+	struct _item##_attribute *_item##_attr =			\
+		container_of(attr, struct _item##_attribute, attr);	\
+	ssize_t ret = 0;						\
+									\
+	if (_item##_attr->show)						\
+		ret = _item##_attr->show(_item, page);			\
+	return ret;							\
+}									\
+static ssize_t _item##_attr_store(struct config_item *item,		\
+				  struct configfs_attribute *attr,	\
+				  const char *page, size_t count)	\
+{									\
+	struct _item *_item = to_##_item(item);				\
+	struct _item##_attribute *_item##_attr =			\
+		container_of(attr, struct _item##_attribute, attr);	\
+	ssize_t ret = -EINVAL;						\
+									\
+	if (_item##_attr->store)					\
+		ret = _item##_attr->store(_item, page, count);		\
+	return ret;							\
+}
 
 /*
  * If allow_link() exists, the item can symlink(2) out to other