linux/fs/configfs/item.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* -*- mode: c; c-basic-offset: 8; -*-
   3 * vim: noexpandtab sw=8 ts=8 sts=0:
   4 *
   5 * item.c - library routines for handling generic config items
   6 *
   7 * Based on kobject:
   8 *      kobject is Copyright (c) 2002-2003 Patrick Mochel
   9 *
  10 * configfs Copyright (C) 2005 Oracle.  All rights reserved.
  11 *
  12 * Please see the file Documentation/filesystems/configfs/configfs.txt for
  13 * critical information about using the config_item interface.
  14 */
  15
  16#include <linux/string.h>
  17#include <linux/module.h>
  18#include <linux/stat.h>
  19#include <linux/slab.h>
  20
  21#include <linux/configfs.h>
  22
  23
  24static inline struct config_item *to_item(struct list_head *entry)
  25{
  26        return container_of(entry, struct config_item, ci_entry);
  27}
  28
  29/* Evil kernel */
  30static void config_item_release(struct kref *kref);
  31
  32/**
  33 *      config_item_init - initialize item.
  34 *      @item:  item in question.
  35 */
  36static void config_item_init(struct config_item *item)
  37{
  38        kref_init(&item->ci_kref);
  39        INIT_LIST_HEAD(&item->ci_entry);
  40}
  41
  42/**
  43 *      config_item_set_name - Set the name of an item
  44 *      @item:  item.
  45 *      @fmt:  The vsnprintf()'s format string.
  46 *
  47 *      If strlen(name) >= CONFIGFS_ITEM_NAME_LEN, then use a
  48 *      dynamically allocated string that @item->ci_name points to.
  49 *      Otherwise, use the static @item->ci_namebuf array.
  50 */
  51int config_item_set_name(struct config_item *item, const char *fmt, ...)
  52{
  53        int limit = CONFIGFS_ITEM_NAME_LEN;
  54        int need;
  55        va_list args;
  56        char *name;
  57
  58        /*
  59         * First, try the static array
  60         */
  61        va_start(args, fmt);
  62        need = vsnprintf(item->ci_namebuf, limit, fmt, args);
  63        va_end(args);
  64        if (need < limit)
  65                name = item->ci_namebuf;
  66        else {
  67                va_start(args, fmt);
  68                name = kvasprintf(GFP_KERNEL, fmt, args);
  69                va_end(args);
  70                if (!name)
  71                        return -EFAULT;
  72        }
  73
  74        /* Free the old name, if necessary. */
  75        if (item->ci_name && item->ci_name != item->ci_namebuf)
  76                kfree(item->ci_name);
  77
  78        /* Now, set the new name */
  79        item->ci_name = name;
  80        return 0;
  81}
  82EXPORT_SYMBOL(config_item_set_name);
  83
  84void config_item_init_type_name(struct config_item *item,
  85                                const char *name,
  86                                const struct config_item_type *type)
  87{
  88        config_item_set_name(item, "%s", name);
  89        item->ci_type = type;
  90        config_item_init(item);
  91}
  92EXPORT_SYMBOL(config_item_init_type_name);
  93
  94void config_group_init_type_name(struct config_group *group, const char *name,
  95                         const struct config_item_type *type)
  96{
  97        config_item_set_name(&group->cg_item, "%s", name);
  98        group->cg_item.ci_type = type;
  99        config_group_init(group);
 100}
 101EXPORT_SYMBOL(config_group_init_type_name);
 102
 103struct config_item *config_item_get(struct config_item *item)
 104{
 105        if (item)
 106                kref_get(&item->ci_kref);
 107        return item;
 108}
 109EXPORT_SYMBOL(config_item_get);
 110
 111struct config_item *config_item_get_unless_zero(struct config_item *item)
 112{
 113        if (item && kref_get_unless_zero(&item->ci_kref))
 114                return item;
 115        return NULL;
 116}
 117EXPORT_SYMBOL(config_item_get_unless_zero);
 118
 119static void config_item_cleanup(struct config_item *item)
 120{
 121        const struct config_item_type *t = item->ci_type;
 122        struct config_group *s = item->ci_group;
 123        struct config_item *parent = item->ci_parent;
 124
 125        pr_debug("config_item %s: cleaning up\n", config_item_name(item));
 126        if (item->ci_name != item->ci_namebuf)
 127                kfree(item->ci_name);
 128        item->ci_name = NULL;
 129        if (t && t->ct_item_ops && t->ct_item_ops->release)
 130                t->ct_item_ops->release(item);
 131        if (s)
 132                config_group_put(s);
 133        if (parent)
 134                config_item_put(parent);
 135}
 136
 137static void config_item_release(struct kref *kref)
 138{
 139        config_item_cleanup(container_of(kref, struct config_item, ci_kref));
 140}
 141
 142/**
 143 *      config_item_put - decrement refcount for item.
 144 *      @item:  item.
 145 *
 146 *      Decrement the refcount, and if 0, call config_item_cleanup().
 147 */
 148void config_item_put(struct config_item *item)
 149{
 150        if (item)
 151                kref_put(&item->ci_kref, config_item_release);
 152}
 153EXPORT_SYMBOL(config_item_put);
 154
 155/**
 156 *      config_group_init - initialize a group for use
 157 *      @group: config_group
 158 */
 159void config_group_init(struct config_group *group)
 160{
 161        config_item_init(&group->cg_item);
 162        INIT_LIST_HEAD(&group->cg_children);
 163        INIT_LIST_HEAD(&group->default_groups);
 164}
 165EXPORT_SYMBOL(config_group_init);
 166
 167/**
 168 *      config_group_find_item - search for item in group.
 169 *      @group: group we're looking in.
 170 *      @name:  item's name.
 171 *
 172 *      Iterate over @group->cg_list, looking for a matching config_item.
 173 *      If matching item is found take a reference and return the item.
 174 *      Caller must have locked group via @group->cg_subsys->su_mtx.
 175 */
 176struct config_item *config_group_find_item(struct config_group *group,
 177                                           const char *name)
 178{
 179        struct list_head *entry;
 180        struct config_item *ret = NULL;
 181
 182        list_for_each(entry, &group->cg_children) {
 183                struct config_item *item = to_item(entry);
 184                if (config_item_name(item) &&
 185                    !strcmp(config_item_name(item), name)) {
 186                        ret = config_item_get(item);
 187                        break;
 188                }
 189        }
 190        return ret;
 191}
 192EXPORT_SYMBOL(config_group_find_item);
 193