17063fbf2SJoel Becker /* -*- mode: c; c-basic-offset: 8; -*- 27063fbf2SJoel Becker * vim: noexpandtab sw=8 ts=8 sts=0: 37063fbf2SJoel Becker * 47063fbf2SJoel Becker * item.c - library routines for handling generic config items 57063fbf2SJoel Becker * 67063fbf2SJoel Becker * This program is free software; you can redistribute it and/or 77063fbf2SJoel Becker * modify it under the terms of the GNU General Public 87063fbf2SJoel Becker * License as published by the Free Software Foundation; either 97063fbf2SJoel Becker * version 2 of the License, or (at your option) any later version. 107063fbf2SJoel Becker * 117063fbf2SJoel Becker * This program is distributed in the hope that it will be useful, 127063fbf2SJoel Becker * but WITHOUT ANY WARRANTY; without even the implied warranty of 137063fbf2SJoel Becker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 147063fbf2SJoel Becker * General Public License for more details. 157063fbf2SJoel Becker * 167063fbf2SJoel Becker * You should have received a copy of the GNU General Public 177063fbf2SJoel Becker * License along with this program; if not, write to the 187063fbf2SJoel Becker * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 197063fbf2SJoel Becker * Boston, MA 021110-1307, USA. 207063fbf2SJoel Becker * 217063fbf2SJoel Becker * Based on kobject: 227063fbf2SJoel Becker * kobject is Copyright (c) 2002-2003 Patrick Mochel 237063fbf2SJoel Becker * 247063fbf2SJoel Becker * configfs Copyright (C) 2005 Oracle. All rights reserved. 257063fbf2SJoel Becker * 267063fbf2SJoel Becker * Please see the file Documentation/filesystems/configfs.txt for 277063fbf2SJoel Becker * critical information about using the config_item interface. 287063fbf2SJoel Becker */ 297063fbf2SJoel Becker 307063fbf2SJoel Becker #include <linux/string.h> 317063fbf2SJoel Becker #include <linux/module.h> 327063fbf2SJoel Becker #include <linux/stat.h> 337063fbf2SJoel Becker #include <linux/slab.h> 347063fbf2SJoel Becker 357063fbf2SJoel Becker #include <linux/configfs.h> 367063fbf2SJoel Becker 377063fbf2SJoel Becker 387063fbf2SJoel Becker static inline struct config_item * to_item(struct list_head * entry) 397063fbf2SJoel Becker { 407063fbf2SJoel Becker return container_of(entry,struct config_item,ci_entry); 417063fbf2SJoel Becker } 427063fbf2SJoel Becker 437063fbf2SJoel Becker /* Evil kernel */ 447063fbf2SJoel Becker static void config_item_release(struct kref *kref); 457063fbf2SJoel Becker 467063fbf2SJoel Becker /** 477063fbf2SJoel Becker * config_item_init - initialize item. 487063fbf2SJoel Becker * @item: item in question. 497063fbf2SJoel Becker */ 507063fbf2SJoel Becker void config_item_init(struct config_item * item) 517063fbf2SJoel Becker { 527063fbf2SJoel Becker kref_init(&item->ci_kref); 537063fbf2SJoel Becker INIT_LIST_HEAD(&item->ci_entry); 547063fbf2SJoel Becker } 557063fbf2SJoel Becker 567063fbf2SJoel Becker /** 577063fbf2SJoel Becker * config_item_set_name - Set the name of an item 587063fbf2SJoel Becker * @item: item. 597063fbf2SJoel Becker * @name: name. 607063fbf2SJoel Becker * 617063fbf2SJoel Becker * If strlen(name) >= CONFIGFS_ITEM_NAME_LEN, then use a 627063fbf2SJoel Becker * dynamically allocated string that @item->ci_name points to. 637063fbf2SJoel Becker * Otherwise, use the static @item->ci_namebuf array. 647063fbf2SJoel Becker */ 657063fbf2SJoel Becker int config_item_set_name(struct config_item * item, const char * fmt, ...) 667063fbf2SJoel Becker { 677063fbf2SJoel Becker int error = 0; 687063fbf2SJoel Becker int limit = CONFIGFS_ITEM_NAME_LEN; 697063fbf2SJoel Becker int need; 707063fbf2SJoel Becker va_list args; 717063fbf2SJoel Becker char * name; 727063fbf2SJoel Becker 737063fbf2SJoel Becker /* 747063fbf2SJoel Becker * First, try the static array 757063fbf2SJoel Becker */ 767063fbf2SJoel Becker va_start(args,fmt); 777063fbf2SJoel Becker need = vsnprintf(item->ci_namebuf,limit,fmt,args); 787063fbf2SJoel Becker va_end(args); 797063fbf2SJoel Becker if (need < limit) 807063fbf2SJoel Becker name = item->ci_namebuf; 817063fbf2SJoel Becker else { 827063fbf2SJoel Becker /* 837063fbf2SJoel Becker * Need more space? Allocate it and try again 847063fbf2SJoel Becker */ 857063fbf2SJoel Becker limit = need + 1; 867063fbf2SJoel Becker name = kmalloc(limit,GFP_KERNEL); 877063fbf2SJoel Becker if (!name) { 887063fbf2SJoel Becker error = -ENOMEM; 897063fbf2SJoel Becker goto Done; 907063fbf2SJoel Becker } 917063fbf2SJoel Becker va_start(args,fmt); 927063fbf2SJoel Becker need = vsnprintf(name,limit,fmt,args); 937063fbf2SJoel Becker va_end(args); 947063fbf2SJoel Becker 957063fbf2SJoel Becker /* Still? Give up. */ 967063fbf2SJoel Becker if (need >= limit) { 977063fbf2SJoel Becker kfree(name); 987063fbf2SJoel Becker error = -EFAULT; 997063fbf2SJoel Becker goto Done; 1007063fbf2SJoel Becker } 1017063fbf2SJoel Becker } 1027063fbf2SJoel Becker 1037063fbf2SJoel Becker /* Free the old name, if necessary. */ 1047063fbf2SJoel Becker if (item->ci_name && item->ci_name != item->ci_namebuf) 1057063fbf2SJoel Becker kfree(item->ci_name); 1067063fbf2SJoel Becker 1077063fbf2SJoel Becker /* Now, set the new name */ 1087063fbf2SJoel Becker item->ci_name = name; 1097063fbf2SJoel Becker Done: 1107063fbf2SJoel Becker return error; 1117063fbf2SJoel Becker } 1127063fbf2SJoel Becker 1137063fbf2SJoel Becker EXPORT_SYMBOL(config_item_set_name); 1147063fbf2SJoel Becker 1157063fbf2SJoel Becker void config_item_init_type_name(struct config_item *item, 1167063fbf2SJoel Becker const char *name, 1177063fbf2SJoel Becker struct config_item_type *type) 1187063fbf2SJoel Becker { 1197063fbf2SJoel Becker config_item_set_name(item, name); 1207063fbf2SJoel Becker item->ci_type = type; 1217063fbf2SJoel Becker config_item_init(item); 1227063fbf2SJoel Becker } 1237063fbf2SJoel Becker EXPORT_SYMBOL(config_item_init_type_name); 1247063fbf2SJoel Becker 1257063fbf2SJoel Becker void config_group_init_type_name(struct config_group *group, const char *name, 1267063fbf2SJoel Becker struct config_item_type *type) 1277063fbf2SJoel Becker { 1287063fbf2SJoel Becker config_item_set_name(&group->cg_item, name); 1297063fbf2SJoel Becker group->cg_item.ci_type = type; 1307063fbf2SJoel Becker config_group_init(group); 1317063fbf2SJoel Becker } 1327063fbf2SJoel Becker EXPORT_SYMBOL(config_group_init_type_name); 1337063fbf2SJoel Becker 1347063fbf2SJoel Becker struct config_item * config_item_get(struct config_item * item) 1357063fbf2SJoel Becker { 1367063fbf2SJoel Becker if (item) 1377063fbf2SJoel Becker kref_get(&item->ci_kref); 1387063fbf2SJoel Becker return item; 1397063fbf2SJoel Becker } 1407063fbf2SJoel Becker 1414c62b534SSatyam Sharma static void config_item_cleanup(struct config_item * item) 1427063fbf2SJoel Becker { 1437063fbf2SJoel Becker struct config_item_type * t = item->ci_type; 1447063fbf2SJoel Becker struct config_group * s = item->ci_group; 1457063fbf2SJoel Becker struct config_item * parent = item->ci_parent; 1467063fbf2SJoel Becker 1477063fbf2SJoel Becker pr_debug("config_item %s: cleaning up\n",config_item_name(item)); 1487063fbf2SJoel Becker if (item->ci_name != item->ci_namebuf) 1497063fbf2SJoel Becker kfree(item->ci_name); 1507063fbf2SJoel Becker item->ci_name = NULL; 1517063fbf2SJoel Becker if (t && t->ct_item_ops && t->ct_item_ops->release) 1527063fbf2SJoel Becker t->ct_item_ops->release(item); 1537063fbf2SJoel Becker if (s) 1547063fbf2SJoel Becker config_group_put(s); 1557063fbf2SJoel Becker if (parent) 1567063fbf2SJoel Becker config_item_put(parent); 1577063fbf2SJoel Becker } 1587063fbf2SJoel Becker 1597063fbf2SJoel Becker static void config_item_release(struct kref *kref) 1607063fbf2SJoel Becker { 1617063fbf2SJoel Becker config_item_cleanup(container_of(kref, struct config_item, ci_kref)); 1627063fbf2SJoel Becker } 1637063fbf2SJoel Becker 1647063fbf2SJoel Becker /** 1657063fbf2SJoel Becker * config_item_put - decrement refcount for item. 1667063fbf2SJoel Becker * @item: item. 1677063fbf2SJoel Becker * 1687063fbf2SJoel Becker * Decrement the refcount, and if 0, call config_item_cleanup(). 1697063fbf2SJoel Becker */ 1707063fbf2SJoel Becker void config_item_put(struct config_item * item) 1717063fbf2SJoel Becker { 1727063fbf2SJoel Becker if (item) 1737063fbf2SJoel Becker kref_put(&item->ci_kref, config_item_release); 1747063fbf2SJoel Becker } 1757063fbf2SJoel Becker 1767063fbf2SJoel Becker /** 1777063fbf2SJoel Becker * config_group_init - initialize a group for use 1787063fbf2SJoel Becker * @k: group 1797063fbf2SJoel Becker */ 1807063fbf2SJoel Becker void config_group_init(struct config_group *group) 1817063fbf2SJoel Becker { 1827063fbf2SJoel Becker config_item_init(&group->cg_item); 1837063fbf2SJoel Becker INIT_LIST_HEAD(&group->cg_children); 1847063fbf2SJoel Becker } 1857063fbf2SJoel Becker 1867063fbf2SJoel Becker 1877063fbf2SJoel Becker /** 1887063fbf2SJoel Becker * config_group_find_obj - search for item in group. 1897063fbf2SJoel Becker * @group: group we're looking in. 1907063fbf2SJoel Becker * @name: item's name. 1917063fbf2SJoel Becker * 1927063fbf2SJoel Becker * Lock group via @group->cg_subsys, and iterate over @group->cg_list, 1937063fbf2SJoel Becker * looking for a matching config_item. If matching item is found 1947063fbf2SJoel Becker * take a reference and return the item. 1957063fbf2SJoel Becker */ 1964c62b534SSatyam Sharma struct config_item *config_group_find_obj(struct config_group *group, 1974c62b534SSatyam Sharma const char * name) 1987063fbf2SJoel Becker { 1997063fbf2SJoel Becker struct list_head * entry; 2007063fbf2SJoel Becker struct config_item * ret = NULL; 2017063fbf2SJoel Becker 2027063fbf2SJoel Becker /* XXX LOCKING! */ 2037063fbf2SJoel Becker list_for_each(entry,&group->cg_children) { 2047063fbf2SJoel Becker struct config_item * item = to_item(entry); 2057063fbf2SJoel Becker if (config_item_name(item) && 2067063fbf2SJoel Becker !strcmp(config_item_name(item), name)) { 2077063fbf2SJoel Becker ret = config_item_get(item); 2087063fbf2SJoel Becker break; 2097063fbf2SJoel Becker } 2107063fbf2SJoel Becker } 2117063fbf2SJoel Becker return ret; 2127063fbf2SJoel Becker } 2137063fbf2SJoel Becker 2147063fbf2SJoel Becker EXPORT_SYMBOL(config_item_init); 2157063fbf2SJoel Becker EXPORT_SYMBOL(config_group_init); 2167063fbf2SJoel Becker EXPORT_SYMBOL(config_item_get); 2177063fbf2SJoel Becker EXPORT_SYMBOL(config_item_put); 218ec580024SDavid Teigland EXPORT_SYMBOL(config_group_find_obj); 219