aboutsummaryrefslogtreecommitdiffstats
path: root/fs/configfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/configfs')
-rw-r--r--fs/configfs/configfs_internal.h7
-rw-r--r--fs/configfs/dir.c289
-rw-r--r--fs/configfs/file.c28
-rw-r--r--fs/configfs/item.c29
4 files changed, 311 insertions, 42 deletions
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index 7b48c034b312..3b0185fdf9a4 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -29,10 +29,11 @@
29 29
30struct configfs_dirent { 30struct configfs_dirent {
31 atomic_t s_count; 31 atomic_t s_count;
32 int s_dependent_count;
32 struct list_head s_sibling; 33 struct list_head s_sibling;
33 struct list_head s_children; 34 struct list_head s_children;
34 struct list_head s_links; 35 struct list_head s_links;
35 void * s_element; 36 void * s_element;
36 int s_type; 37 int s_type;
37 umode_t s_mode; 38 umode_t s_mode;
38 struct dentry * s_dentry; 39 struct dentry * s_dentry;
@@ -41,8 +42,8 @@ struct configfs_dirent {
41 42
42#define CONFIGFS_ROOT 0x0001 43#define CONFIGFS_ROOT 0x0001
43#define CONFIGFS_DIR 0x0002 44#define CONFIGFS_DIR 0x0002
44#define CONFIGFS_ITEM_ATTR 0x0004 45#define CONFIGFS_ITEM_ATTR 0x0004
45#define CONFIGFS_ITEM_LINK 0x0020 46#define CONFIGFS_ITEM_LINK 0x0020
46#define CONFIGFS_USET_DIR 0x0040 47#define CONFIGFS_USET_DIR 0x0040
47#define CONFIGFS_USET_DEFAULT 0x0080 48#define CONFIGFS_USET_DEFAULT 0x0080
48#define CONFIGFS_USET_DROPPING 0x0100 49#define CONFIGFS_USET_DROPPING 0x0100
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 5e6e37e58f36..2f436d4f1d6d 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -355,6 +355,10 @@ static int configfs_detach_prep(struct dentry *dentry)
355 /* Mark that we've taken i_mutex */ 355 /* Mark that we've taken i_mutex */
356 sd->s_type |= CONFIGFS_USET_DROPPING; 356 sd->s_type |= CONFIGFS_USET_DROPPING;
357 357
358 /*
359 * Yup, recursive. If there's a problem, blame
360 * deep nesting of default_groups
361 */
358 ret = configfs_detach_prep(sd->s_dentry); 362 ret = configfs_detach_prep(sd->s_dentry);
359 if (!ret) 363 if (!ret)
360 continue; 364 continue;
@@ -562,7 +566,7 @@ static int populate_groups(struct config_group *group)
562 566
563/* 567/*
564 * All of link_obj/unlink_obj/link_group/unlink_group require that 568 * All of link_obj/unlink_obj/link_group/unlink_group require that
565 * subsys->su_sem is held. 569 * subsys->su_mutex is held.
566 */ 570 */
567 571
568static void unlink_obj(struct config_item *item) 572static void unlink_obj(struct config_item *item)
@@ -714,6 +718,28 @@ static void configfs_detach_group(struct config_item *item)
714} 718}
715 719
716/* 720/*
721 * After the item has been detached from the filesystem view, we are
722 * ready to tear it out of the hierarchy. Notify the client before
723 * we do that so they can perform any cleanup that requires
724 * navigating the hierarchy. A client does not need to provide this
725 * callback. The subsystem semaphore MUST be held by the caller, and
726 * references must be valid for both items. It also assumes the
727 * caller has validated ci_type.
728 */
729static void client_disconnect_notify(struct config_item *parent_item,
730 struct config_item *item)
731{
732 struct config_item_type *type;
733
734 type = parent_item->ci_type;
735 BUG_ON(!type);
736
737 if (type->ct_group_ops && type->ct_group_ops->disconnect_notify)
738 type->ct_group_ops->disconnect_notify(to_config_group(parent_item),
739 item);
740}
741
742/*
717 * Drop the initial reference from make_item()/make_group() 743 * Drop the initial reference from make_item()/make_group()
718 * This function assumes that reference is held on item 744 * This function assumes that reference is held on item
719 * and that item holds a valid reference to the parent. Also, it 745 * and that item holds a valid reference to the parent. Also, it
@@ -733,11 +759,244 @@ static void client_drop_item(struct config_item *parent_item,
733 */ 759 */
734 if (type->ct_group_ops && type->ct_group_ops->drop_item) 760 if (type->ct_group_ops && type->ct_group_ops->drop_item)
735 type->ct_group_ops->drop_item(to_config_group(parent_item), 761 type->ct_group_ops->drop_item(to_config_group(parent_item),
736 item); 762 item);
737 else 763 else
738 config_item_put(item); 764 config_item_put(item);
739} 765}
740 766
767#ifdef DEBUG
768static void configfs_dump_one(struct configfs_dirent *sd, int level)
769{
770 printk(KERN_INFO "%*s\"%s\":\n", level, " ", configfs_get_name(sd));
771
772#define type_print(_type) if (sd->s_type & _type) printk(KERN_INFO "%*s %s\n", level, " ", #_type);
773 type_print(CONFIGFS_ROOT);
774 type_print(CONFIGFS_DIR);
775 type_print(CONFIGFS_ITEM_ATTR);
776 type_print(CONFIGFS_ITEM_LINK);
777 type_print(CONFIGFS_USET_DIR);
778 type_print(CONFIGFS_USET_DEFAULT);
779 type_print(CONFIGFS_USET_DROPPING);
780#undef type_print
781}
782
783static int configfs_dump(struct configfs_dirent *sd, int level)
784{
785 struct configfs_dirent *child_sd;
786 int ret = 0;
787
788 configfs_dump_one(sd, level);
789
790 if (!(sd->s_type & (CONFIGFS_DIR|CONFIGFS_ROOT)))
791 return 0;
792
793 list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
794 ret = configfs_dump(child_sd, level + 2);
795 if (ret)
796 break;
797 }
798
799 return ret;
800}
801#endif
802
803
804/*
805 * configfs_depend_item() and configfs_undepend_item()
806 *
807 * WARNING: Do not call these from a configfs callback!
808 *
809 * This describes these functions and their helpers.
810 *
811 * Allow another kernel system to depend on a config_item. If this
812 * happens, the item cannot go away until the dependant can live without
813 * it. The idea is to give client modules as simple an interface as
814 * possible. When a system asks them to depend on an item, they just
815 * call configfs_depend_item(). If the item is live and the client
816 * driver is in good shape, we'll happily do the work for them.
817 *
818 * Why is the locking complex? Because configfs uses the VFS to handle
819 * all locking, but this function is called outside the normal
820 * VFS->configfs path. So it must take VFS locks to prevent the
821 * VFS->configfs stuff (configfs_mkdir(), configfs_rmdir(), etc). This is
822 * why you can't call these functions underneath configfs callbacks.
823 *
824 * Note, btw, that this can be called at *any* time, even when a configfs
825 * subsystem isn't registered, or when configfs is loading or unloading.
826 * Just like configfs_register_subsystem(). So we take the same
827 * precautions. We pin the filesystem. We lock each i_mutex _in_order_
828 * on our way down the tree. If we can find the target item in the
829 * configfs tree, it must be part of the subsystem tree as well, so we
830 * do not need the subsystem semaphore. Holding the i_mutex chain locks
831 * out mkdir() and rmdir(), who might be racing us.
832 */
833
834/*
835 * configfs_depend_prep()
836 *
837 * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are
838 * attributes. This is similar but not the same to configfs_detach_prep().
839 * Note that configfs_detach_prep() expects the parent to be locked when it
840 * is called, but we lock the parent *inside* configfs_depend_prep(). We
841 * do that so we can unlock it if we find nothing.
842 *
843 * Here we do a depth-first search of the dentry hierarchy looking for
844 * our object. We take i_mutex on each step of the way down. IT IS
845 * ESSENTIAL THAT i_mutex LOCKING IS ORDERED. If we come back up a branch,
846 * we'll drop the i_mutex.
847 *
848 * If the target is not found, -ENOENT is bubbled up and we have released
849 * all locks. If the target was found, the locks will be cleared by
850 * configfs_depend_rollback().
851 *
852 * This adds a requirement that all config_items be unique!
853 *
854 * This is recursive because the locking traversal is tricky. There isn't
855 * much on the stack, though, so folks that need this function - be careful
856 * about your stack! Patches will be accepted to make it iterative.
857 */
858static int configfs_depend_prep(struct dentry *origin,
859 struct config_item *target)
860{
861 struct configfs_dirent *child_sd, *sd = origin->d_fsdata;
862 int ret = 0;
863
864 BUG_ON(!origin || !sd);
865
866 /* Lock this guy on the way down */
867 mutex_lock(&sd->s_dentry->d_inode->i_mutex);
868 if (sd->s_element == target) /* Boo-yah */
869 goto out;
870
871 list_for_each_entry(child_sd, &sd->s_children, s_sibling) {
872 if (child_sd->s_type & CONFIGFS_DIR) {
873 ret = configfs_depend_prep(child_sd->s_dentry,
874 target);
875 if (!ret)
876 goto out; /* Child path boo-yah */
877 }
878 }
879
880 /* We looped all our children and didn't find target */
881 mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
882 ret = -ENOENT;
883
884out:
885 return ret;
886}
887
888/*
889 * This is ONLY called if configfs_depend_prep() did its job. So we can
890 * trust the entire path from item back up to origin.
891 *
892 * We walk backwards from item, unlocking each i_mutex. We finish by
893 * unlocking origin.
894 */
895static void configfs_depend_rollback(struct dentry *origin,
896 struct config_item *item)
897{
898 struct dentry *dentry = item->ci_dentry;
899
900 while (dentry != origin) {
901 mutex_unlock(&dentry->d_inode->i_mutex);
902 dentry = dentry->d_parent;
903 }
904
905 mutex_unlock(&origin->d_inode->i_mutex);
906}
907
908int configfs_depend_item(struct configfs_subsystem *subsys,
909 struct config_item *target)
910{
911 int ret;
912 struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;
913 struct config_item *s_item = &subsys->su_group.cg_item;
914
915 /*
916 * Pin the configfs filesystem. This means we can safely access
917 * the root of the configfs filesystem.
918 */
919 ret = configfs_pin_fs();
920 if (ret)
921 return ret;
922
923 /*
924 * Next, lock the root directory. We're going to check that the
925 * subsystem is really registered, and so we need to lock out
926 * configfs_[un]register_subsystem().
927 */
928 mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
929
930 root_sd = configfs_sb->s_root->d_fsdata;
931
932 list_for_each_entry(p, &root_sd->s_children, s_sibling) {
933 if (p->s_type & CONFIGFS_DIR) {
934 if (p->s_element == s_item) {
935 subsys_sd = p;
936 break;
937 }
938 }
939 }
940
941 if (!subsys_sd) {
942 ret = -ENOENT;
943 goto out_unlock_fs;
944 }
945
946 /* Ok, now we can trust subsys/s_item */
947
948 /* Scan the tree, locking i_mutex recursively, return 0 if found */
949 ret = configfs_depend_prep(subsys_sd->s_dentry, target);
950 if (ret)
951 goto out_unlock_fs;
952
953 /* We hold all i_mutexes from the subsystem down to the target */
954 p = target->ci_dentry->d_fsdata;
955 p->s_dependent_count += 1;
956
957 configfs_depend_rollback(subsys_sd->s_dentry, target);
958
959out_unlock_fs:
960 mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
961
962 /*
963 * If we succeeded, the fs is pinned via other methods. If not,
964 * we're done with it anyway. So release_fs() is always right.
965 */
966 configfs_release_fs();
967
968 return ret;
969}
970EXPORT_SYMBOL(configfs_depend_item);
971
972/*
973 * Release the dependent linkage. This is much simpler than
974 * configfs_depend_item() because we know that that the client driver is
975 * pinned, thus the subsystem is pinned, and therefore configfs is pinned.
976 */
977void configfs_undepend_item(struct configfs_subsystem *subsys,
978 struct config_item *target)
979{
980 struct configfs_dirent *sd;
981
982 /*
983 * Since we can trust everything is pinned, we just need i_mutex
984 * on the item.
985 */
986 mutex_lock(&target->ci_dentry->d_inode->i_mutex);
987
988 sd = target->ci_dentry->d_fsdata;
989 BUG_ON(sd->s_dependent_count < 1);
990
991 sd->s_dependent_count -= 1;
992
993 /*
994 * After this unlock, we cannot trust the item to stay alive!
995 * DO NOT REFERENCE item after this unlock.
996 */
997 mutex_unlock(&target->ci_dentry->d_inode->i_mutex);
998}
999EXPORT_SYMBOL(configfs_undepend_item);
741 1000
742static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 1001static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
743{ 1002{
@@ -783,7 +1042,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
783 1042
784 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); 1043 snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
785 1044
786 down(&subsys->su_sem); 1045 mutex_lock(&subsys->su_mutex);
787 group = NULL; 1046 group = NULL;
788 item = NULL; 1047 item = NULL;
789 if (type->ct_group_ops->make_group) { 1048 if (type->ct_group_ops->make_group) {
@@ -797,7 +1056,7 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
797 if (item) 1056 if (item)
798 link_obj(parent_item, item); 1057 link_obj(parent_item, item);
799 } 1058 }
800 up(&subsys->su_sem); 1059 mutex_unlock(&subsys->su_mutex);
801 1060
802 kfree(name); 1061 kfree(name);
803 if (!item) { 1062 if (!item) {
@@ -841,13 +1100,16 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
841out_unlink: 1100out_unlink:
842 if (ret) { 1101 if (ret) {
843 /* Tear down everything we built up */ 1102 /* Tear down everything we built up */
844 down(&subsys->su_sem); 1103 mutex_lock(&subsys->su_mutex);
1104
1105 client_disconnect_notify(parent_item, item);
845 if (group) 1106 if (group)
846 unlink_group(group); 1107 unlink_group(group);
847 else 1108 else
848 unlink_obj(item); 1109 unlink_obj(item);
849 client_drop_item(parent_item, item); 1110 client_drop_item(parent_item, item);
850 up(&subsys->su_sem); 1111
1112 mutex_unlock(&subsys->su_mutex);
851 1113
852 if (module_got) 1114 if (module_got)
853 module_put(owner); 1115 module_put(owner);
@@ -881,6 +1143,13 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
881 if (sd->s_type & CONFIGFS_USET_DEFAULT) 1143 if (sd->s_type & CONFIGFS_USET_DEFAULT)
882 return -EPERM; 1144 return -EPERM;
883 1145
1146 /*
1147 * Here's where we check for dependents. We're protected by
1148 * i_mutex.
1149 */
1150 if (sd->s_dependent_count)
1151 return -EBUSY;
1152
884 /* Get a working ref until we have the child */ 1153 /* Get a working ref until we have the child */
885 parent_item = configfs_get_config_item(dentry->d_parent); 1154 parent_item = configfs_get_config_item(dentry->d_parent);
886 subsys = to_config_group(parent_item)->cg_subsys; 1155 subsys = to_config_group(parent_item)->cg_subsys;
@@ -910,17 +1179,19 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
910 if (sd->s_type & CONFIGFS_USET_DIR) { 1179 if (sd->s_type & CONFIGFS_USET_DIR) {
911 configfs_detach_group(item); 1180 configfs_detach_group(item);
912 1181
913 down(&subsys->su_sem); 1182 mutex_lock(&subsys->su_mutex);
1183 client_disconnect_notify(parent_item, item);
914 unlink_group(to_config_group(item)); 1184 unlink_group(to_config_group(item));
915 } else { 1185 } else {
916 configfs_detach_item(item); 1186 configfs_detach_item(item);
917 1187
918 down(&subsys->su_sem); 1188 mutex_lock(&subsys->su_mutex);
1189 client_disconnect_notify(parent_item, item);
919 unlink_obj(item); 1190 unlink_obj(item);
920 } 1191 }
921 1192
922 client_drop_item(parent_item, item); 1193 client_drop_item(parent_item, item);
923 up(&subsys->su_sem); 1194 mutex_unlock(&subsys->su_mutex);
924 1195
925 /* Drop our reference from above */ 1196 /* Drop our reference from above */
926 config_item_put(item); 1197 config_item_put(item);
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
index 3527c7c6def8..a3658f9a082c 100644
--- a/fs/configfs/file.c
+++ b/fs/configfs/file.c
@@ -27,19 +27,26 @@
27#include <linux/fs.h> 27#include <linux/fs.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/mutex.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
31#include <asm/semaphore.h>
32 32
33#include <linux/configfs.h> 33#include <linux/configfs.h>
34#include "configfs_internal.h" 34#include "configfs_internal.h"
35 35
36/*
37 * A simple attribute can only be 4096 characters. Why 4k? Because the
38 * original code limited it to PAGE_SIZE. That's a bad idea, though,
39 * because an attribute of 16k on ia64 won't work on x86. So we limit to
40 * 4k, our minimum common page size.
41 */
42#define SIMPLE_ATTR_SIZE 4096
36 43
37struct configfs_buffer { 44struct configfs_buffer {
38 size_t count; 45 size_t count;
39 loff_t pos; 46 loff_t pos;
40 char * page; 47 char * page;
41 struct configfs_item_operations * ops; 48 struct configfs_item_operations * ops;
42 struct semaphore sem; 49 struct mutex mutex;
43 int needs_read_fill; 50 int needs_read_fill;
44}; 51};
45 52
@@ -69,7 +76,7 @@ static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buf
69 76
70 count = ops->show_attribute(item,attr,buffer->page); 77 count = ops->show_attribute(item,attr,buffer->page);
71 buffer->needs_read_fill = 0; 78 buffer->needs_read_fill = 0;
72 BUG_ON(count > (ssize_t)PAGE_SIZE); 79 BUG_ON(count > (ssize_t)SIMPLE_ATTR_SIZE);
73 if (count >= 0) 80 if (count >= 0)
74 buffer->count = count; 81 buffer->count = count;
75 else 82 else
@@ -102,7 +109,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
102 struct configfs_buffer * buffer = file->private_data; 109 struct configfs_buffer * buffer = file->private_data;
103 ssize_t retval = 0; 110 ssize_t retval = 0;
104 111
105 down(&buffer->sem); 112 mutex_lock(&buffer->mutex);
106 if (buffer->needs_read_fill) { 113 if (buffer->needs_read_fill) {
107 if ((retval = fill_read_buffer(file->f_path.dentry,buffer))) 114 if ((retval = fill_read_buffer(file->f_path.dentry,buffer)))
108 goto out; 115 goto out;
@@ -112,7 +119,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
112 retval = simple_read_from_buffer(buf, count, ppos, buffer->page, 119 retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
113 buffer->count); 120 buffer->count);
114out: 121out:
115 up(&buffer->sem); 122 mutex_unlock(&buffer->mutex);
116 return retval; 123 return retval;
117} 124}
118 125
@@ -137,8 +144,8 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size
137 if (!buffer->page) 144 if (!buffer->page)
138 return -ENOMEM; 145 return -ENOMEM;
139 146
140 if (count >= PAGE_SIZE) 147 if (count >= SIMPLE_ATTR_SIZE)
141 count = PAGE_SIZE - 1; 148 count = SIMPLE_ATTR_SIZE - 1;
142 error = copy_from_user(buffer->page,buf,count); 149 error = copy_from_user(buffer->page,buf,count);
143 buffer->needs_read_fill = 1; 150 buffer->needs_read_fill = 1;
144 /* if buf is assumed to contain a string, terminate it by \0, 151 /* if buf is assumed to contain a string, terminate it by \0,
@@ -193,13 +200,13 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
193 struct configfs_buffer * buffer = file->private_data; 200 struct configfs_buffer * buffer = file->private_data;
194 ssize_t len; 201 ssize_t len;
195 202
196 down(&buffer->sem); 203 mutex_lock(&buffer->mutex);
197 len = fill_write_buffer(buffer, buf, count); 204 len = fill_write_buffer(buffer, buf, count);
198 if (len > 0) 205 if (len > 0)
199 len = flush_write_buffer(file->f_path.dentry, buffer, count); 206 len = flush_write_buffer(file->f_path.dentry, buffer, count);
200 if (len > 0) 207 if (len > 0)
201 *ppos += len; 208 *ppos += len;
202 up(&buffer->sem); 209 mutex_unlock(&buffer->mutex);
203 return len; 210 return len;
204} 211}
205 212
@@ -253,7 +260,7 @@ static int check_perm(struct inode * inode, struct file * file)
253 error = -ENOMEM; 260 error = -ENOMEM;
254 goto Enomem; 261 goto Enomem;
255 } 262 }
256 init_MUTEX(&buffer->sem); 263 mutex_init(&buffer->mutex);
257 buffer->needs_read_fill = 1; 264 buffer->needs_read_fill = 1;
258 buffer->ops = ops; 265 buffer->ops = ops;
259 file->private_data = buffer; 266 file->private_data = buffer;
@@ -292,6 +299,7 @@ static int configfs_release(struct inode * inode, struct file * filp)
292 if (buffer) { 299 if (buffer) {
293 if (buffer->page) 300 if (buffer->page)
294 free_page((unsigned long)buffer->page); 301 free_page((unsigned long)buffer->page);
302 mutex_destroy(&buffer->mutex);
295 kfree(buffer); 303 kfree(buffer);
296 } 304 }
297 return 0; 305 return 0;
diff --git a/fs/configfs/item.c b/fs/configfs/item.c
index 24421209f854..76dc4c3e5d51 100644
--- a/fs/configfs/item.c
+++ b/fs/configfs/item.c
@@ -62,7 +62,6 @@ void config_item_init(struct config_item * item)
62 * dynamically allocated string that @item->ci_name points to. 62 * dynamically allocated string that @item->ci_name points to.
63 * Otherwise, use the static @item->ci_namebuf array. 63 * Otherwise, use the static @item->ci_namebuf array.
64 */ 64 */
65
66int config_item_set_name(struct config_item * item, const char * fmt, ...) 65int config_item_set_name(struct config_item * item, const char * fmt, ...)
67{ 66{
68 int error = 0; 67 int error = 0;
@@ -139,12 +138,7 @@ struct config_item * config_item_get(struct config_item * item)
139 return item; 138 return item;
140} 139}
141 140
142/** 141static void config_item_cleanup(struct config_item * item)
143 * config_item_cleanup - free config_item resources.
144 * @item: item.
145 */
146
147void config_item_cleanup(struct config_item * item)
148{ 142{
149 struct config_item_type * t = item->ci_type; 143 struct config_item_type * t = item->ci_type;
150 struct config_group * s = item->ci_group; 144 struct config_group * s = item->ci_group;
@@ -179,39 +173,35 @@ void config_item_put(struct config_item * item)
179 kref_put(&item->ci_kref, config_item_release); 173 kref_put(&item->ci_kref, config_item_release);
180} 174}
181 175
182
183/** 176/**
184 * config_group_init - initialize a group for use 177 * config_group_init - initialize a group for use
185 * @k: group 178 * @k: group
186 */ 179 */
187
188void config_group_init(struct config_group *group) 180void config_group_init(struct config_group *group)
189{ 181{
190 config_item_init(&group->cg_item); 182 config_item_init(&group->cg_item);
191 INIT_LIST_HEAD(&group->cg_children); 183 INIT_LIST_HEAD(&group->cg_children);
192} 184}
193 185
194
195/** 186/**
196 * config_group_find_obj - search for item in group. 187 * config_group_find_item - search for item in group.
197 * @group: group we're looking in. 188 * @group: group we're looking in.
198 * @name: item's name. 189 * @name: item's name.
199 * 190 *
200 * Lock group via @group->cg_subsys, and iterate over @group->cg_list, 191 * Iterate over @group->cg_list, looking for a matching config_item.
201 * looking for a matching config_item. If matching item is found 192 * If matching item is found take a reference and return the item.
202 * take a reference and return the item. 193 * Caller must have locked group via @group->cg_subsys->su_mtx.
203 */ 194 */
204 195struct config_item *config_group_find_item(struct config_group *group,
205struct config_item * config_group_find_obj(struct config_group * group, const char * name) 196 const char *name)
206{ 197{
207 struct list_head * entry; 198 struct list_head * entry;
208 struct config_item * ret = NULL; 199 struct config_item * ret = NULL;
209 200
210 /* XXX LOCKING! */
211 list_for_each(entry,&group->cg_children) { 201 list_for_each(entry,&group->cg_children) {
212 struct config_item * item = to_item(entry); 202 struct config_item * item = to_item(entry);
213 if (config_item_name(item) && 203 if (config_item_name(item) &&
214 !strcmp(config_item_name(item), name)) { 204 !strcmp(config_item_name(item), name)) {
215 ret = config_item_get(item); 205 ret = config_item_get(item);
216 break; 206 break;
217 } 207 }
@@ -219,9 +209,8 @@ struct config_item * config_group_find_obj(struct config_group * group, const ch
219 return ret; 209 return ret;
220} 210}
221 211
222
223EXPORT_SYMBOL(config_item_init); 212EXPORT_SYMBOL(config_item_init);
224EXPORT_SYMBOL(config_group_init); 213EXPORT_SYMBOL(config_group_init);
225EXPORT_SYMBOL(config_item_get); 214EXPORT_SYMBOL(config_item_get);
226EXPORT_SYMBOL(config_item_put); 215EXPORT_SYMBOL(config_item_put);
227EXPORT_SYMBOL(config_group_find_obj); 216EXPORT_SYMBOL(config_group_find_item);