diff options
Diffstat (limited to 'fs/configfs')
-rw-r--r-- | fs/configfs/configfs_internal.h | 7 | ||||
-rw-r--r-- | fs/configfs/dir.c | 289 | ||||
-rw-r--r-- | fs/configfs/file.c | 28 | ||||
-rw-r--r-- | fs/configfs/item.c | 29 |
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 | ||
30 | struct configfs_dirent { | 30 | struct 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 | ||
568 | static void unlink_obj(struct config_item *item) | 572 | static 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 | */ | ||
729 | static 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 | ||
768 | static 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 | |||
783 | static 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 | */ | ||
858 | static 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 | |||
884 | out: | ||
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 | */ | ||
895 | static 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 | |||
908 | int 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 | |||
959 | out_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 | } | ||
970 | EXPORT_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 | */ | ||
977 | void 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 | } | ||
999 | EXPORT_SYMBOL(configfs_undepend_item); | ||
741 | 1000 | ||
742 | static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 1001 | static 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) | |||
841 | out_unlink: | 1100 | out_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 | ||
37 | struct configfs_buffer { | 44 | struct 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); |
114 | out: | 121 | out: |
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 | |||
66 | int config_item_set_name(struct config_item * item, const char * fmt, ...) | 65 | int 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 | /** | 141 | static void config_item_cleanup(struct config_item * item) |
143 | * config_item_cleanup - free config_item resources. | ||
144 | * @item: item. | ||
145 | */ | ||
146 | |||
147 | void 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 | |||
188 | void config_group_init(struct config_group *group) | 180 | void 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 | 195 | struct config_item *config_group_find_item(struct config_group *group, | |
205 | struct 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 | |||
223 | EXPORT_SYMBOL(config_item_init); | 212 | EXPORT_SYMBOL(config_item_init); |
224 | EXPORT_SYMBOL(config_group_init); | 213 | EXPORT_SYMBOL(config_group_init); |
225 | EXPORT_SYMBOL(config_item_get); | 214 | EXPORT_SYMBOL(config_item_get); |
226 | EXPORT_SYMBOL(config_item_put); | 215 | EXPORT_SYMBOL(config_item_put); |
227 | EXPORT_SYMBOL(config_group_find_obj); | 216 | EXPORT_SYMBOL(config_group_find_item); |