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.rst 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 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 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 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 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 } 82 EXPORT_SYMBOL(config_item_set_name); 83 84 void 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 } 92 EXPORT_SYMBOL(config_item_init_type_name); 93 94 void 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 } 101 EXPORT_SYMBOL(config_group_init_type_name); 102 103 struct config_item *config_item_get(struct config_item *item) 104 { 105 if (item) 106 kref_get(&item->ci_kref); 107 return item; 108 } 109 EXPORT_SYMBOL(config_item_get); 110 111 struct 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 } 117 EXPORT_SYMBOL(config_item_get_unless_zero); 118 119 static 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 137 static 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 */ 148 void config_item_put(struct config_item *item) 149 { 150 if (item) 151 kref_put(&item->ci_kref, config_item_release); 152 } 153 EXPORT_SYMBOL(config_item_put); 154 155 /** 156 * config_group_init - initialize a group for use 157 * @group: config_group 158 */ 159 void 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 } 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 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 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 } 192 EXPORT_SYMBOL(config_group_find_item); 193