Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * item.c - library routines for handling generic config items
0004  *
0005  * Based on kobject:
0006  *  kobject is Copyright (c) 2002-2003 Patrick Mochel
0007  *
0008  * configfs Copyright (C) 2005 Oracle.  All rights reserved.
0009  *
0010  * Please see the file Documentation/filesystems/configfs.rst for
0011  * critical information about using the config_item interface.
0012  */
0013 
0014 #include <linux/string.h>
0015 #include <linux/module.h>
0016 #include <linux/stat.h>
0017 #include <linux/slab.h>
0018 
0019 #include <linux/configfs.h>
0020 
0021 
0022 static inline struct config_item *to_item(struct list_head *entry)
0023 {
0024     return container_of(entry, struct config_item, ci_entry);
0025 }
0026 
0027 /* Evil kernel */
0028 static void config_item_release(struct kref *kref);
0029 
0030 /**
0031  *  config_item_init - initialize item.
0032  *  @item:  item in question.
0033  */
0034 static void config_item_init(struct config_item *item)
0035 {
0036     kref_init(&item->ci_kref);
0037     INIT_LIST_HEAD(&item->ci_entry);
0038 }
0039 
0040 /**
0041  *  config_item_set_name - Set the name of an item
0042  *  @item:  item.
0043  *  @fmt:  The vsnprintf()'s format string.
0044  *
0045  *  If strlen(name) >= CONFIGFS_ITEM_NAME_LEN, then use a
0046  *  dynamically allocated string that @item->ci_name points to.
0047  *  Otherwise, use the static @item->ci_namebuf array.
0048  */
0049 int config_item_set_name(struct config_item *item, const char *fmt, ...)
0050 {
0051     int limit = CONFIGFS_ITEM_NAME_LEN;
0052     int need;
0053     va_list args;
0054     char *name;
0055 
0056     /*
0057      * First, try the static array
0058      */
0059     va_start(args, fmt);
0060     need = vsnprintf(item->ci_namebuf, limit, fmt, args);
0061     va_end(args);
0062     if (need < limit)
0063         name = item->ci_namebuf;
0064     else {
0065         va_start(args, fmt);
0066         name = kvasprintf(GFP_KERNEL, fmt, args);
0067         va_end(args);
0068         if (!name)
0069             return -EFAULT;
0070     }
0071 
0072     /* Free the old name, if necessary. */
0073     if (item->ci_name && item->ci_name != item->ci_namebuf)
0074         kfree(item->ci_name);
0075 
0076     /* Now, set the new name */
0077     item->ci_name = name;
0078     return 0;
0079 }
0080 EXPORT_SYMBOL(config_item_set_name);
0081 
0082 void config_item_init_type_name(struct config_item *item,
0083                 const char *name,
0084                 const struct config_item_type *type)
0085 {
0086     config_item_set_name(item, "%s", name);
0087     item->ci_type = type;
0088     config_item_init(item);
0089 }
0090 EXPORT_SYMBOL(config_item_init_type_name);
0091 
0092 void config_group_init_type_name(struct config_group *group, const char *name,
0093              const struct config_item_type *type)
0094 {
0095     config_item_set_name(&group->cg_item, "%s", name);
0096     group->cg_item.ci_type = type;
0097     config_group_init(group);
0098 }
0099 EXPORT_SYMBOL(config_group_init_type_name);
0100 
0101 struct config_item *config_item_get(struct config_item *item)
0102 {
0103     if (item)
0104         kref_get(&item->ci_kref);
0105     return item;
0106 }
0107 EXPORT_SYMBOL(config_item_get);
0108 
0109 struct config_item *config_item_get_unless_zero(struct config_item *item)
0110 {
0111     if (item && kref_get_unless_zero(&item->ci_kref))
0112         return item;
0113     return NULL;
0114 }
0115 EXPORT_SYMBOL(config_item_get_unless_zero);
0116 
0117 static void config_item_cleanup(struct config_item *item)
0118 {
0119     const struct config_item_type *t = item->ci_type;
0120     struct config_group *s = item->ci_group;
0121     struct config_item *parent = item->ci_parent;
0122 
0123     pr_debug("config_item %s: cleaning up\n", config_item_name(item));
0124     if (item->ci_name != item->ci_namebuf)
0125         kfree(item->ci_name);
0126     item->ci_name = NULL;
0127     if (t && t->ct_item_ops && t->ct_item_ops->release)
0128         t->ct_item_ops->release(item);
0129     if (s)
0130         config_group_put(s);
0131     if (parent)
0132         config_item_put(parent);
0133 }
0134 
0135 static void config_item_release(struct kref *kref)
0136 {
0137     config_item_cleanup(container_of(kref, struct config_item, ci_kref));
0138 }
0139 
0140 /**
0141  *  config_item_put - decrement refcount for item.
0142  *  @item:  item.
0143  *
0144  *  Decrement the refcount, and if 0, call config_item_cleanup().
0145  */
0146 void config_item_put(struct config_item *item)
0147 {
0148     if (item)
0149         kref_put(&item->ci_kref, config_item_release);
0150 }
0151 EXPORT_SYMBOL(config_item_put);
0152 
0153 /**
0154  *  config_group_init - initialize a group for use
0155  *  @group: config_group
0156  */
0157 void config_group_init(struct config_group *group)
0158 {
0159     config_item_init(&group->cg_item);
0160     INIT_LIST_HEAD(&group->cg_children);
0161     INIT_LIST_HEAD(&group->default_groups);
0162 }
0163 EXPORT_SYMBOL(config_group_init);
0164 
0165 /**
0166  *  config_group_find_item - search for item in group.
0167  *  @group: group we're looking in.
0168  *  @name:  item's name.
0169  *
0170  *  Iterate over @group->cg_list, looking for a matching config_item.
0171  *  If matching item is found take a reference and return the item.
0172  *  Caller must have locked group via @group->cg_subsys->su_mtx.
0173  */
0174 struct config_item *config_group_find_item(struct config_group *group,
0175                        const char *name)
0176 {
0177     struct list_head *entry;
0178     struct config_item *ret = NULL;
0179 
0180     list_for_each(entry, &group->cg_children) {
0181         struct config_item *item = to_item(entry);
0182         if (config_item_name(item) &&
0183             !strcmp(config_item_name(item), name)) {
0184             ret = config_item_get(item);
0185             break;
0186         }
0187     }
0188     return ret;
0189 }
0190 EXPORT_SYMBOL(config_group_find_item);