Branch data Line data Source code
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 : : 24 : : static inline struct config_item *to_item(struct list_head *entry) 25 : : { 26 : 0 : return container_of(entry, struct config_item, ci_entry); 27 : : } 28 : : 29 : : /* Evil kernel */ 30 : : static void config_item_release(struct kref *kref); 31 : : 32 : : /** 33 : : * config_item_init - initialize item. 34 : : * @item: item in question. 35 : : */ 36 : : static void config_item_init(struct config_item *item) 37 : : { 38 : : kref_init(&item->ci_kref); 39 : 1212 : 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 : : */ 51 : 404 : int 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 : 404 : va_start(args, fmt); 62 : 404 : need = vsnprintf(item->ci_namebuf, limit, fmt, args); 63 : 404 : va_end(args); 64 [ - + ]: 404 : if (need < limit) 65 : : name = item->ci_namebuf; 66 : : else { 67 : 0 : va_start(args, fmt); 68 : 0 : name = kvasprintf(GFP_KERNEL, fmt, args); 69 : 0 : va_end(args); 70 [ # # ]: 0 : if (!name) 71 : : return -EFAULT; 72 : : } 73 : : 74 : : /* Free the old name, if necessary. */ 75 [ - + # # ]: 404 : if (item->ci_name && item->ci_name != item->ci_namebuf) 76 : 0 : kfree(item->ci_name); 77 : : 78 : : /* Now, set the new name */ 79 : 404 : item->ci_name = name; 80 : 404 : return 0; 81 : : } 82 : : EXPORT_SYMBOL(config_item_set_name); 83 : : 84 : 0 : void config_item_init_type_name(struct config_item *item, 85 : : const char *name, 86 : : const struct config_item_type *type) 87 : : { 88 : 0 : config_item_set_name(item, "%s", name); 89 : 0 : item->ci_type = type; 90 : : config_item_init(item); 91 : 0 : } 92 : : EXPORT_SYMBOL(config_item_init_type_name); 93 : : 94 : 404 : void config_group_init_type_name(struct config_group *group, const char *name, 95 : : const struct config_item_type *type) 96 : : { 97 : 404 : config_item_set_name(&group->cg_item, "%s", name); 98 : 404 : group->cg_item.ci_type = type; 99 : : config_group_init(group); 100 : 404 : } 101 : : EXPORT_SYMBOL(config_group_init_type_name); 102 : : 103 : 1616 : struct config_item *config_item_get(struct config_item *item) 104 : : { 105 [ # # + - ]: 1616 : if (item) 106 : : kref_get(&item->ci_kref); 107 : 1616 : return item; 108 : : } 109 : : EXPORT_SYMBOL(config_item_get); 110 : : 111 : 0 : struct config_item *config_item_get_unless_zero(struct config_item *item) 112 : : { 113 [ # # # # ]: 0 : if (item && kref_get_unless_zero(&item->ci_kref)) 114 : 0 : return item; 115 : : return NULL; 116 : : } 117 : : EXPORT_SYMBOL(config_item_get_unless_zero); 118 : : 119 : 0 : static void config_item_cleanup(struct config_item *item) 120 : : { 121 : 0 : const struct config_item_type *t = item->ci_type; 122 : 0 : struct config_group *s = item->ci_group; 123 : 0 : struct config_item *parent = item->ci_parent; 124 : : 125 : : pr_debug("config_item %s: cleaning up\n", config_item_name(item)); 126 [ # # ]: 0 : if (item->ci_name != item->ci_namebuf) 127 : 0 : kfree(item->ci_name); 128 : 0 : item->ci_name = NULL; 129 [ # # # # : 0 : if (t && t->ct_item_ops && t->ct_item_ops->release) # # ] 130 : 0 : t->ct_item_ops->release(item); 131 [ # # ]: 0 : if (s) 132 : : config_group_put(s); 133 [ # # ]: 0 : if (parent) 134 : : config_item_put(parent); 135 : 0 : } 136 : : 137 : 0 : static void config_item_release(struct kref *kref) 138 : : { 139 : 0 : config_item_cleanup(container_of(kref, struct config_item, ci_kref)); 140 : 0 : } 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 : : */ 148 : 0 : void config_item_put(struct config_item *item) 149 : : { 150 [ # # # # : 0 : if (item) # # ] 151 : 0 : kref_put(&item->ci_kref, config_item_release); 152 : 0 : } 153 : : EXPORT_SYMBOL(config_item_put); 154 : : 155 : : /** 156 : : * config_group_init - initialize a group for use 157 : : * @group: config_group 158 : : */ 159 : 808 : void config_group_init(struct config_group *group) 160 : : { 161 : : config_item_init(&group->cg_item); 162 : 1212 : INIT_LIST_HEAD(&group->cg_children); 163 : 1212 : INIT_LIST_HEAD(&group->default_groups); 164 : 808 : } 165 : : EXPORT_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 : : */ 176 : 0 : struct 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 [ # # ]: 0 : list_for_each(entry, &group->cg_children) { 183 : : struct config_item *item = to_item(entry); 184 [ # # # # ]: 0 : if (config_item_name(item) && 185 : 0 : !strcmp(config_item_name(item), name)) { 186 : : ret = config_item_get(item); 187 : 0 : break; 188 : : } 189 : : } 190 : 0 : return ret; 191 : : } 192 : : EXPORT_SYMBOL(config_group_find_item);