[PATCH v5 4/8] samples: configfs: add a committable group

Bartosz Golaszewski
2021-09-20T14:06:41Z

Add an example of using committable items to configfs samples. Each
config item has two attributes: read-write 'storeme' which works
similarly to other examples in this file and a read-only 'committed'
attribute which changes its value between false and true depending on
whether it's committed or not at the moment.

Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
samples/configfs/configfs_sample.c | 153 +++++++++++++++++++++++++++++
1 file changed, 153 insertions(+)

diff --git a/samples/configfs/configfs_sample.c b/samples/configfs/configfs_sample.c
index 37a657b25d58..f0a1c4d847b1 100644
--- a/samples/configfs/configfs_sample.c
+++ b/samples/configfs/configfs_sample.c
@@ -313,6 +313,158 @@ static struct configfs_subsystem group_children_subsys = {

/* ----------------------------------------------------------------- */

+/*
+ * 04-committable-children
+ *
+ * This is an example of a committable group. It's similar to the simple
+ * children example but each config_item has an additional 'committed'
+ * attribute which is read-only and is only modified when the config_item
+ * is moved from the 'pending' to the 'live' directory.
+ */
+
+struct committable_child {
+ struct config_item item;
+ int storeme;
+ bool committed;
+};
+
+static inline struct committable_child *
+to_committable_child(struct config_item *item)
+{
+ return container_of(item, struct committable_child, item);
+}
+
+static ssize_t
+committable_child_storeme_show(struct config_item *item, char *page)
+{
+ return sprintf(page, "%d\n", to_committable_child(item)->storeme);
+}
+
+static ssize_t committable_child_storeme_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct committable_child *child = to_committable_child(item);
+ int ret;
+
+ if (child->committed)
+ return -EPERM;
+
+ ret = kstrtoint(page, 10, &child->storeme);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+CONFIGFS_ATTR(committable_child_, storeme);
+
+static ssize_t
+committable_child_committed_show(struct config_item *item, char *page)
+{
+ return sprintf(page, "%s\n",
+ to_committable_child(item)->committed ? "true" : "false");
+}
+
+CONFIGFS_ATTR_RO(committable_child_, committed);
+
+static struct configfs_attribute *committable_child_attrs[] = {
+ &committable_child_attr_storeme,
+ &committable_child_attr_committed,
+ NULL,
+};
+
+static void committable_child_release(struct config_item *item)
+{
+ kfree(to_committable_child(item));
+}
+
+static struct configfs_item_operations committable_child_item_ops = {
+ .release = committable_child_release,
+};
+
+static const struct config_item_type committable_child_type = {
+ .ct_item_ops = &committable_child_item_ops,
+ .ct_attrs = committable_child_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+struct committable_children {
+ struct config_group group;
+};
+
+static struct config_item *
+committable_children_make_item(struct config_group *group, const char *name)
+{
+ struct committable_child *child;
+
+ child = kzalloc(sizeof(*child), GFP_KERNEL);
+ if (!child)
+ return ERR_PTR(-ENOMEM);
+
+ config_item_init_type_name(&child->item, name, &committable_child_type);
+
+ return &child->item;
+}
+
+static ssize_t
+committable_children_description_show(struct config_item *item, char *page)
+{
+ return sprintf(page,
+"[04-committable-children]\n"
+"\n"
+"This subsystem allows creation of committable config_items. The subsystem\n"
+"has two subdirectories: pending and live. New config_items can only be\n"
+"created in pending/ and they have one writable and readable attribute as\n"
+"well as a single read-only attribute. The latter is only changed once the\n"
+"item is 'committed'. This is done by moving the config_item (using\n"
+"rename()) to the live/ directory. In this example, the storeme attribute\n"
+"becomes 'read-only' once committed.\n");
+}
+
+CONFIGFS_ATTR_RO(committable_children_, description);
+
+static struct configfs_attribute *committable_children_attrs[] = {
+ &committable_children_attr_description,
+ NULL,
+};
+
+static int committable_children_commit_item(struct config_item *item)
+{
+ to_committable_child(item)->committed = true;
+
+ return 0;
+}
+
+static int committable_children_uncommit_item(struct config_item *item)
+{
+ to_committable_child(item)->committed = false;
+
+ return 0;
+}
+
+static struct configfs_group_operations committable_children_group_ops = {
+ .make_item = committable_children_make_item,
+ .commit_item = committable_children_commit_item,
+ .uncommit_item = committable_children_uncommit_item,
+};
+
+static const struct config_item_type committable_children_type = {
+ .ct_group_ops = &committable_children_group_ops,
+ .ct_attrs = committable_children_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_subsystem committable_children_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "04-committable-children",
+ .ci_type = &committable_children_type,
+ },
+ },
+};
+
+/* ----------------------------------------------------------------- */
+
/*
* We're now done with our subsystem definitions.
* For convenience in this module, here's a list of them all. It
@@ -324,6 +476,7 @@ static struct configfs_subsystem *example_subsys[] = {
&childless_subsys.subsys,
&simple_children_subsys,
&group_children_subsys,
+ &committable_children_subsys,
NULL,
};

--
2.30.1