diff options
-rw-r--r-- | Documentation/filesystems/configfs/configfs.txt | 27 | ||||
-rw-r--r-- | fs/configfs/configfs_internal.h | 7 | ||||
-rw-r--r-- | fs/configfs/dir.c | 244 | ||||
-rw-r--r-- | include/linux/configfs.h | 5 |
4 files changed, 280 insertions, 3 deletions
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt index aef74cdecc21..d1b98257d000 100644 --- a/Documentation/filesystems/configfs/configfs.txt +++ b/Documentation/filesystems/configfs/configfs.txt | |||
@@ -398,6 +398,33 @@ As a consequence of this, default_groups cannot be removed directly via | |||
398 | rmdir(2). They also are not considered when rmdir(2) on the parent | 398 | rmdir(2). They also are not considered when rmdir(2) on the parent |
399 | group is checking for children. | 399 | group is checking for children. |
400 | 400 | ||
401 | [Dependant Subsystems] | ||
402 | |||
403 | Sometimes other drivers depend on particular configfs items. For | ||
404 | example, ocfs2 mounts depend on a heartbeat region item. If that | ||
405 | region item is removed with rmdir(2), the ocfs2 mount must BUG or go | ||
406 | readonly. Not happy. | ||
407 | |||
408 | configfs provides two additional API calls: configfs_depend_item() and | ||
409 | configfs_undepend_item(). A client driver can call | ||
410 | configfs_depend_item() on an existing item to tell configfs that it is | ||
411 | depended on. configfs will then return -EBUSY from rmdir(2) for that | ||
412 | item. When the item is no longer depended on, the client driver calls | ||
413 | configfs_undepend_item() on it. | ||
414 | |||
415 | These API cannot be called underneath any configfs callbacks, as | ||
416 | they will conflict. They can block and allocate. A client driver | ||
417 | probably shouldn't calling them of its own gumption. Rather it should | ||
418 | be providing an API that external subsystems call. | ||
419 | |||
420 | How does this work? Imagine the ocfs2 mount process. When it mounts, | ||
421 | it asks for a heartbeat region item. This is done via a call into the | ||
422 | heartbeat code. Inside the heartbeat code, the region item is looked | ||
423 | up. Here, the heartbeat code calls configfs_depend_item(). If it | ||
424 | succeeds, then heartbeat knows the region is safe to give to ocfs2. | ||
425 | If it fails, it was being torn down anyway, and heartbeat can gracefully | ||
426 | pass up an error. | ||
427 | |||
401 | [Committable Items] | 428 | [Committable Items] |
402 | 429 | ||
403 | NOTE: Committable items are currently unimplemented. | 430 | NOTE: Committable items are currently unimplemented. |
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 125954723eb7..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; |
@@ -760,6 +764,239 @@ static void client_drop_item(struct config_item *parent_item, | |||
760 | config_item_put(item); | 764 | config_item_put(item); |
761 | } | 765 | } |
762 | 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); | ||
763 | 1000 | ||
764 | 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) |
765 | { | 1002 | { |
@@ -906,6 +1143,13 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
906 | if (sd->s_type & CONFIGFS_USET_DEFAULT) | 1143 | if (sd->s_type & CONFIGFS_USET_DEFAULT) |
907 | return -EPERM; | 1144 | return -EPERM; |
908 | 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 | |||
909 | /* Get a working ref until we have the child */ | 1153 | /* Get a working ref until we have the child */ |
910 | parent_item = configfs_get_config_item(dentry->d_parent); | 1154 | parent_item = configfs_get_config_item(dentry->d_parent); |
911 | subsys = to_config_group(parent_item)->cg_subsys; | 1155 | subsys = to_config_group(parent_item)->cg_subsys; |
diff --git a/include/linux/configfs.h b/include/linux/configfs.h index 8227e730dac7..8c6967f3fb11 100644 --- a/include/linux/configfs.h +++ b/include/linux/configfs.h | |||
@@ -188,6 +188,11 @@ static inline struct configfs_subsystem *to_configfs_subsystem(struct config_gro | |||
188 | int configfs_register_subsystem(struct configfs_subsystem *subsys); | 188 | int configfs_register_subsystem(struct configfs_subsystem *subsys); |
189 | void configfs_unregister_subsystem(struct configfs_subsystem *subsys); | 189 | void configfs_unregister_subsystem(struct configfs_subsystem *subsys); |
190 | 190 | ||
191 | /* These functions can sleep and can alloc with GFP_KERNEL */ | ||
192 | /* WARNING: These cannot be called underneath configfs callbacks!! */ | ||
193 | int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target); | ||
194 | void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target); | ||
195 | |||
191 | #endif /* __KERNEL__ */ | 196 | #endif /* __KERNEL__ */ |
192 | 197 | ||
193 | #endif /* _CONFIGFS_H_ */ | 198 | #endif /* _CONFIGFS_H_ */ |