From: Bartosz Golaszewski <bgolaszew...@baylibre.com>

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 <bgolaszew...@baylibre.com>
Acked-by: Linus Walleij <linus.wall...@linaro.org>
---
 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 f9008be7a8a1..9bef74e4369d 100644
--- a/samples/configfs/configfs_sample.c
+++ b/samples/configfs/configfs_sample.c
@@ -315,6 +315,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
@@ -326,6 +478,7 @@ static struct configfs_subsystem *example_subsys[] = {
        &childless_subsys.subsys,
        &simple_children_subsys,
        &group_children_subsys,
+       &committable_children_subsys,
        NULL,
 };
 
-- 
2.30.1

Reply via email to