diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-09 16:07:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-09 16:07:40 -0400 |
commit | 983a5f84a4a11c8706ca70615125db711336b684 (patch) | |
tree | bbf16b836903aaf523e7c637a0d7191ba8fa172d /fs/btrfs/qgroup.c | |
parent | 8769e078a9a2bce13d39c08e0e5a513f5320e1de (diff) | |
parent | 667e7d94a1683661cff5fe9a0fa0d7f8fdd2c007 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs update from Chris Mason:
"These are mostly fixes. The biggest exceptions are Josef's skinny
extents and Jan Schmidt's code to rebuild our quota indexes if they
get out of sync (or you enable quotas on an existing filesystem).
The skinny extents are off by default because they are a new variation
on the extent allocation tree format. btrfstune -x enables them, and
the new format makes the extent allocation tree about 30% smaller.
I rebased this a few days ago to rework Dave Sterba's crc checks on
the super block, but almost all of these go back to rc6, since I
though 3.9 was due any minute.
The biggest missing fix is the tracepoint bug that was hit late in
3.9. I ran into problems with that in overnight testing and I'm still
tracking it down. I'll definitely have that fixed for rc2."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (101 commits)
Btrfs: allow superblock mismatch from older mkfs
btrfs: enhance superblock checks
btrfs: fix misleading variable name for flags
btrfs: use unsigned long type for extent state bits
Btrfs: improve the loop of scrub_stripe
btrfs: read entire device info under lock
btrfs: remove unused gfp mask parameter from release_extent_buffer callchain
btrfs: handle errors returned from get_tree_block_key
btrfs: make static code static & remove dead code
Btrfs: deal with errors in write_dev_supers
Btrfs: remove almost all of the BUG()'s from tree-log.c
Btrfs: deal with free space cache errors while replaying log
Btrfs: automatic rescan after "quota enable" command
Btrfs: rescan for qgroups
Btrfs: split btrfs_qgroup_account_ref into four functions
Btrfs: allocate new chunks if the space is not enough for global rsv
Btrfs: separate sequence numbers for delayed ref tracking and tree mod log
btrfs: move leak debug code to functions
Btrfs: return free space in cow error path
Btrfs: set UUID in root_item for created trees
...
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r-- | fs/btrfs/qgroup.c | 840 |
1 files changed, 671 insertions, 169 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index b44124dd2370..9d49c586995a 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -31,13 +31,13 @@ | |||
31 | #include "locking.h" | 31 | #include "locking.h" |
32 | #include "ulist.h" | 32 | #include "ulist.h" |
33 | #include "backref.h" | 33 | #include "backref.h" |
34 | #include "extent_io.h" | ||
34 | 35 | ||
35 | /* TODO XXX FIXME | 36 | /* TODO XXX FIXME |
36 | * - subvol delete -> delete when ref goes to 0? delete limits also? | 37 | * - subvol delete -> delete when ref goes to 0? delete limits also? |
37 | * - reorganize keys | 38 | * - reorganize keys |
38 | * - compressed | 39 | * - compressed |
39 | * - sync | 40 | * - sync |
40 | * - rescan | ||
41 | * - copy also limits on subvol creation | 41 | * - copy also limits on subvol creation |
42 | * - limit | 42 | * - limit |
43 | * - caches fuer ulists | 43 | * - caches fuer ulists |
@@ -98,7 +98,15 @@ struct btrfs_qgroup_list { | |||
98 | struct btrfs_qgroup *member; | 98 | struct btrfs_qgroup *member; |
99 | }; | 99 | }; |
100 | 100 | ||
101 | /* must be called with qgroup_lock held */ | 101 | struct qgroup_rescan { |
102 | struct btrfs_work work; | ||
103 | struct btrfs_fs_info *fs_info; | ||
104 | }; | ||
105 | |||
106 | static void qgroup_rescan_start(struct btrfs_fs_info *fs_info, | ||
107 | struct qgroup_rescan *qscan); | ||
108 | |||
109 | /* must be called with qgroup_ioctl_lock held */ | ||
102 | static struct btrfs_qgroup *find_qgroup_rb(struct btrfs_fs_info *fs_info, | 110 | static struct btrfs_qgroup *find_qgroup_rb(struct btrfs_fs_info *fs_info, |
103 | u64 qgroupid) | 111 | u64 qgroupid) |
104 | { | 112 | { |
@@ -298,7 +306,20 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info) | |||
298 | } | 306 | } |
299 | fs_info->qgroup_flags = btrfs_qgroup_status_flags(l, | 307 | fs_info->qgroup_flags = btrfs_qgroup_status_flags(l, |
300 | ptr); | 308 | ptr); |
301 | /* FIXME read scan element */ | 309 | fs_info->qgroup_rescan_progress.objectid = |
310 | btrfs_qgroup_status_rescan(l, ptr); | ||
311 | if (fs_info->qgroup_flags & | ||
312 | BTRFS_QGROUP_STATUS_FLAG_RESCAN) { | ||
313 | struct qgroup_rescan *qscan = | ||
314 | kmalloc(sizeof(*qscan), GFP_NOFS); | ||
315 | if (!qscan) { | ||
316 | ret = -ENOMEM; | ||
317 | goto out; | ||
318 | } | ||
319 | fs_info->qgroup_rescan_progress.type = 0; | ||
320 | fs_info->qgroup_rescan_progress.offset = 0; | ||
321 | qgroup_rescan_start(fs_info, qscan); | ||
322 | } | ||
302 | goto next1; | 323 | goto next1; |
303 | } | 324 | } |
304 | 325 | ||
@@ -420,8 +441,6 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info) | |||
420 | qgroup = rb_entry(n, struct btrfs_qgroup, node); | 441 | qgroup = rb_entry(n, struct btrfs_qgroup, node); |
421 | rb_erase(n, &fs_info->qgroup_tree); | 442 | rb_erase(n, &fs_info->qgroup_tree); |
422 | 443 | ||
423 | WARN_ON(!list_empty(&qgroup->dirty)); | ||
424 | |||
425 | while (!list_empty(&qgroup->groups)) { | 444 | while (!list_empty(&qgroup->groups)) { |
426 | list = list_first_entry(&qgroup->groups, | 445 | list = list_first_entry(&qgroup->groups, |
427 | struct btrfs_qgroup_list, | 446 | struct btrfs_qgroup_list, |
@@ -721,7 +740,8 @@ static int update_qgroup_status_item(struct btrfs_trans_handle *trans, | |||
721 | ptr = btrfs_item_ptr(l, slot, struct btrfs_qgroup_status_item); | 740 | ptr = btrfs_item_ptr(l, slot, struct btrfs_qgroup_status_item); |
722 | btrfs_set_qgroup_status_flags(l, ptr, fs_info->qgroup_flags); | 741 | btrfs_set_qgroup_status_flags(l, ptr, fs_info->qgroup_flags); |
723 | btrfs_set_qgroup_status_generation(l, ptr, trans->transid); | 742 | btrfs_set_qgroup_status_generation(l, ptr, trans->transid); |
724 | /* XXX scan */ | 743 | btrfs_set_qgroup_status_rescan(l, ptr, |
744 | fs_info->qgroup_rescan_progress.objectid); | ||
725 | 745 | ||
726 | btrfs_mark_buffer_dirty(l); | 746 | btrfs_mark_buffer_dirty(l); |
727 | 747 | ||
@@ -783,19 +803,21 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
783 | struct btrfs_fs_info *fs_info) | 803 | struct btrfs_fs_info *fs_info) |
784 | { | 804 | { |
785 | struct btrfs_root *quota_root; | 805 | struct btrfs_root *quota_root; |
806 | struct btrfs_root *tree_root = fs_info->tree_root; | ||
786 | struct btrfs_path *path = NULL; | 807 | struct btrfs_path *path = NULL; |
787 | struct btrfs_qgroup_status_item *ptr; | 808 | struct btrfs_qgroup_status_item *ptr; |
788 | struct extent_buffer *leaf; | 809 | struct extent_buffer *leaf; |
789 | struct btrfs_key key; | 810 | struct btrfs_key key; |
811 | struct btrfs_key found_key; | ||
812 | struct btrfs_qgroup *qgroup = NULL; | ||
790 | int ret = 0; | 813 | int ret = 0; |
814 | int slot; | ||
791 | 815 | ||
792 | spin_lock(&fs_info->qgroup_lock); | 816 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
793 | if (fs_info->quota_root) { | 817 | if (fs_info->quota_root) { |
794 | fs_info->pending_quota_state = 1; | 818 | fs_info->pending_quota_state = 1; |
795 | spin_unlock(&fs_info->qgroup_lock); | ||
796 | goto out; | 819 | goto out; |
797 | } | 820 | } |
798 | spin_unlock(&fs_info->qgroup_lock); | ||
799 | 821 | ||
800 | /* | 822 | /* |
801 | * initially create the quota tree | 823 | * initially create the quota tree |
@@ -830,10 +852,57 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
830 | fs_info->qgroup_flags = BTRFS_QGROUP_STATUS_FLAG_ON | | 852 | fs_info->qgroup_flags = BTRFS_QGROUP_STATUS_FLAG_ON | |
831 | BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; | 853 | BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; |
832 | btrfs_set_qgroup_status_flags(leaf, ptr, fs_info->qgroup_flags); | 854 | btrfs_set_qgroup_status_flags(leaf, ptr, fs_info->qgroup_flags); |
833 | btrfs_set_qgroup_status_scan(leaf, ptr, 0); | 855 | btrfs_set_qgroup_status_rescan(leaf, ptr, 0); |
834 | 856 | ||
835 | btrfs_mark_buffer_dirty(leaf); | 857 | btrfs_mark_buffer_dirty(leaf); |
836 | 858 | ||
859 | key.objectid = 0; | ||
860 | key.type = BTRFS_ROOT_REF_KEY; | ||
861 | key.offset = 0; | ||
862 | |||
863 | btrfs_release_path(path); | ||
864 | ret = btrfs_search_slot_for_read(tree_root, &key, path, 1, 0); | ||
865 | if (ret > 0) | ||
866 | goto out_add_root; | ||
867 | if (ret < 0) | ||
868 | goto out_free_path; | ||
869 | |||
870 | |||
871 | while (1) { | ||
872 | slot = path->slots[0]; | ||
873 | leaf = path->nodes[0]; | ||
874 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
875 | |||
876 | if (found_key.type == BTRFS_ROOT_REF_KEY) { | ||
877 | ret = add_qgroup_item(trans, quota_root, | ||
878 | found_key.offset); | ||
879 | if (ret) | ||
880 | goto out_free_path; | ||
881 | |||
882 | qgroup = add_qgroup_rb(fs_info, found_key.offset); | ||
883 | if (IS_ERR(qgroup)) { | ||
884 | ret = PTR_ERR(qgroup); | ||
885 | goto out_free_path; | ||
886 | } | ||
887 | } | ||
888 | ret = btrfs_next_item(tree_root, path); | ||
889 | if (ret < 0) | ||
890 | goto out_free_path; | ||
891 | if (ret) | ||
892 | break; | ||
893 | } | ||
894 | |||
895 | out_add_root: | ||
896 | btrfs_release_path(path); | ||
897 | ret = add_qgroup_item(trans, quota_root, BTRFS_FS_TREE_OBJECTID); | ||
898 | if (ret) | ||
899 | goto out_free_path; | ||
900 | |||
901 | qgroup = add_qgroup_rb(fs_info, BTRFS_FS_TREE_OBJECTID); | ||
902 | if (IS_ERR(qgroup)) { | ||
903 | ret = PTR_ERR(qgroup); | ||
904 | goto out_free_path; | ||
905 | } | ||
837 | spin_lock(&fs_info->qgroup_lock); | 906 | spin_lock(&fs_info->qgroup_lock); |
838 | fs_info->quota_root = quota_root; | 907 | fs_info->quota_root = quota_root; |
839 | fs_info->pending_quota_state = 1; | 908 | fs_info->pending_quota_state = 1; |
@@ -847,6 +916,7 @@ out_free_root: | |||
847 | kfree(quota_root); | 916 | kfree(quota_root); |
848 | } | 917 | } |
849 | out: | 918 | out: |
919 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
850 | return ret; | 920 | return ret; |
851 | } | 921 | } |
852 | 922 | ||
@@ -857,11 +927,10 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans, | |||
857 | struct btrfs_root *quota_root; | 927 | struct btrfs_root *quota_root; |
858 | int ret = 0; | 928 | int ret = 0; |
859 | 929 | ||
930 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
931 | if (!fs_info->quota_root) | ||
932 | goto out; | ||
860 | spin_lock(&fs_info->qgroup_lock); | 933 | spin_lock(&fs_info->qgroup_lock); |
861 | if (!fs_info->quota_root) { | ||
862 | spin_unlock(&fs_info->qgroup_lock); | ||
863 | return 0; | ||
864 | } | ||
865 | fs_info->quota_enabled = 0; | 934 | fs_info->quota_enabled = 0; |
866 | fs_info->pending_quota_state = 0; | 935 | fs_info->pending_quota_state = 0; |
867 | quota_root = fs_info->quota_root; | 936 | quota_root = fs_info->quota_root; |
@@ -869,8 +938,10 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans, | |||
869 | btrfs_free_qgroup_config(fs_info); | 938 | btrfs_free_qgroup_config(fs_info); |
870 | spin_unlock(&fs_info->qgroup_lock); | 939 | spin_unlock(&fs_info->qgroup_lock); |
871 | 940 | ||
872 | if (!quota_root) | 941 | if (!quota_root) { |
873 | return -EINVAL; | 942 | ret = -EINVAL; |
943 | goto out; | ||
944 | } | ||
874 | 945 | ||
875 | ret = btrfs_clean_quota_tree(trans, quota_root); | 946 | ret = btrfs_clean_quota_tree(trans, quota_root); |
876 | if (ret) | 947 | if (ret) |
@@ -891,39 +962,62 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans, | |||
891 | free_extent_buffer(quota_root->commit_root); | 962 | free_extent_buffer(quota_root->commit_root); |
892 | kfree(quota_root); | 963 | kfree(quota_root); |
893 | out: | 964 | out: |
965 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
894 | return ret; | 966 | return ret; |
895 | } | 967 | } |
896 | 968 | ||
897 | int btrfs_quota_rescan(struct btrfs_fs_info *fs_info) | 969 | static void qgroup_dirty(struct btrfs_fs_info *fs_info, |
970 | struct btrfs_qgroup *qgroup) | ||
898 | { | 971 | { |
899 | /* FIXME */ | 972 | if (list_empty(&qgroup->dirty)) |
900 | return 0; | 973 | list_add(&qgroup->dirty, &fs_info->dirty_qgroups); |
901 | } | 974 | } |
902 | 975 | ||
903 | int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, | 976 | int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans, |
904 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) | 977 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) |
905 | { | 978 | { |
906 | struct btrfs_root *quota_root; | 979 | struct btrfs_root *quota_root; |
980 | struct btrfs_qgroup *parent; | ||
981 | struct btrfs_qgroup *member; | ||
982 | struct btrfs_qgroup_list *list; | ||
907 | int ret = 0; | 983 | int ret = 0; |
908 | 984 | ||
985 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
909 | quota_root = fs_info->quota_root; | 986 | quota_root = fs_info->quota_root; |
910 | if (!quota_root) | 987 | if (!quota_root) { |
911 | return -EINVAL; | 988 | ret = -EINVAL; |
989 | goto out; | ||
990 | } | ||
991 | member = find_qgroup_rb(fs_info, src); | ||
992 | parent = find_qgroup_rb(fs_info, dst); | ||
993 | if (!member || !parent) { | ||
994 | ret = -EINVAL; | ||
995 | goto out; | ||
996 | } | ||
997 | |||
998 | /* check if such qgroup relation exist firstly */ | ||
999 | list_for_each_entry(list, &member->groups, next_group) { | ||
1000 | if (list->group == parent) { | ||
1001 | ret = -EEXIST; | ||
1002 | goto out; | ||
1003 | } | ||
1004 | } | ||
912 | 1005 | ||
913 | ret = add_qgroup_relation_item(trans, quota_root, src, dst); | 1006 | ret = add_qgroup_relation_item(trans, quota_root, src, dst); |
914 | if (ret) | 1007 | if (ret) |
915 | return ret; | 1008 | goto out; |
916 | 1009 | ||
917 | ret = add_qgroup_relation_item(trans, quota_root, dst, src); | 1010 | ret = add_qgroup_relation_item(trans, quota_root, dst, src); |
918 | if (ret) { | 1011 | if (ret) { |
919 | del_qgroup_relation_item(trans, quota_root, src, dst); | 1012 | del_qgroup_relation_item(trans, quota_root, src, dst); |
920 | return ret; | 1013 | goto out; |
921 | } | 1014 | } |
922 | 1015 | ||
923 | spin_lock(&fs_info->qgroup_lock); | 1016 | spin_lock(&fs_info->qgroup_lock); |
924 | ret = add_relation_rb(quota_root->fs_info, src, dst); | 1017 | ret = add_relation_rb(quota_root->fs_info, src, dst); |
925 | spin_unlock(&fs_info->qgroup_lock); | 1018 | spin_unlock(&fs_info->qgroup_lock); |
926 | 1019 | out: | |
1020 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
927 | return ret; | 1021 | return ret; |
928 | } | 1022 | } |
929 | 1023 | ||
@@ -931,13 +1025,34 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | |||
931 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) | 1025 | struct btrfs_fs_info *fs_info, u64 src, u64 dst) |
932 | { | 1026 | { |
933 | struct btrfs_root *quota_root; | 1027 | struct btrfs_root *quota_root; |
1028 | struct btrfs_qgroup *parent; | ||
1029 | struct btrfs_qgroup *member; | ||
1030 | struct btrfs_qgroup_list *list; | ||
934 | int ret = 0; | 1031 | int ret = 0; |
935 | int err; | 1032 | int err; |
936 | 1033 | ||
1034 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
937 | quota_root = fs_info->quota_root; | 1035 | quota_root = fs_info->quota_root; |
938 | if (!quota_root) | 1036 | if (!quota_root) { |
939 | return -EINVAL; | 1037 | ret = -EINVAL; |
1038 | goto out; | ||
1039 | } | ||
940 | 1040 | ||
1041 | member = find_qgroup_rb(fs_info, src); | ||
1042 | parent = find_qgroup_rb(fs_info, dst); | ||
1043 | if (!member || !parent) { | ||
1044 | ret = -EINVAL; | ||
1045 | goto out; | ||
1046 | } | ||
1047 | |||
1048 | /* check if such qgroup relation exist firstly */ | ||
1049 | list_for_each_entry(list, &member->groups, next_group) { | ||
1050 | if (list->group == parent) | ||
1051 | goto exist; | ||
1052 | } | ||
1053 | ret = -ENOENT; | ||
1054 | goto out; | ||
1055 | exist: | ||
941 | ret = del_qgroup_relation_item(trans, quota_root, src, dst); | 1056 | ret = del_qgroup_relation_item(trans, quota_root, src, dst); |
942 | err = del_qgroup_relation_item(trans, quota_root, dst, src); | 1057 | err = del_qgroup_relation_item(trans, quota_root, dst, src); |
943 | if (err && !ret) | 1058 | if (err && !ret) |
@@ -945,9 +1060,9 @@ int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans, | |||
945 | 1060 | ||
946 | spin_lock(&fs_info->qgroup_lock); | 1061 | spin_lock(&fs_info->qgroup_lock); |
947 | del_relation_rb(fs_info, src, dst); | 1062 | del_relation_rb(fs_info, src, dst); |
948 | |||
949 | spin_unlock(&fs_info->qgroup_lock); | 1063 | spin_unlock(&fs_info->qgroup_lock); |
950 | 1064 | out: | |
1065 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
951 | return ret; | 1066 | return ret; |
952 | } | 1067 | } |
953 | 1068 | ||
@@ -958,11 +1073,21 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, | |||
958 | struct btrfs_qgroup *qgroup; | 1073 | struct btrfs_qgroup *qgroup; |
959 | int ret = 0; | 1074 | int ret = 0; |
960 | 1075 | ||
1076 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
961 | quota_root = fs_info->quota_root; | 1077 | quota_root = fs_info->quota_root; |
962 | if (!quota_root) | 1078 | if (!quota_root) { |
963 | return -EINVAL; | 1079 | ret = -EINVAL; |
1080 | goto out; | ||
1081 | } | ||
1082 | qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
1083 | if (qgroup) { | ||
1084 | ret = -EEXIST; | ||
1085 | goto out; | ||
1086 | } | ||
964 | 1087 | ||
965 | ret = add_qgroup_item(trans, quota_root, qgroupid); | 1088 | ret = add_qgroup_item(trans, quota_root, qgroupid); |
1089 | if (ret) | ||
1090 | goto out; | ||
966 | 1091 | ||
967 | spin_lock(&fs_info->qgroup_lock); | 1092 | spin_lock(&fs_info->qgroup_lock); |
968 | qgroup = add_qgroup_rb(fs_info, qgroupid); | 1093 | qgroup = add_qgroup_rb(fs_info, qgroupid); |
@@ -970,7 +1095,8 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, | |||
970 | 1095 | ||
971 | if (IS_ERR(qgroup)) | 1096 | if (IS_ERR(qgroup)) |
972 | ret = PTR_ERR(qgroup); | 1097 | ret = PTR_ERR(qgroup); |
973 | 1098 | out: | |
1099 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
974 | return ret; | 1100 | return ret; |
975 | } | 1101 | } |
976 | 1102 | ||
@@ -981,27 +1107,32 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, | |||
981 | struct btrfs_qgroup *qgroup; | 1107 | struct btrfs_qgroup *qgroup; |
982 | int ret = 0; | 1108 | int ret = 0; |
983 | 1109 | ||
1110 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
984 | quota_root = fs_info->quota_root; | 1111 | quota_root = fs_info->quota_root; |
985 | if (!quota_root) | 1112 | if (!quota_root) { |
986 | return -EINVAL; | 1113 | ret = -EINVAL; |
1114 | goto out; | ||
1115 | } | ||
987 | 1116 | ||
988 | /* check if there are no relations to this qgroup */ | ||
989 | spin_lock(&fs_info->qgroup_lock); | ||
990 | qgroup = find_qgroup_rb(fs_info, qgroupid); | 1117 | qgroup = find_qgroup_rb(fs_info, qgroupid); |
991 | if (qgroup) { | 1118 | if (!qgroup) { |
992 | if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) { | 1119 | ret = -ENOENT; |
993 | spin_unlock(&fs_info->qgroup_lock); | 1120 | goto out; |
994 | return -EBUSY; | 1121 | } else { |
1122 | /* check if there are no relations to this qgroup */ | ||
1123 | if (!list_empty(&qgroup->groups) || | ||
1124 | !list_empty(&qgroup->members)) { | ||
1125 | ret = -EBUSY; | ||
1126 | goto out; | ||
995 | } | 1127 | } |
996 | } | 1128 | } |
997 | spin_unlock(&fs_info->qgroup_lock); | ||
998 | |||
999 | ret = del_qgroup_item(trans, quota_root, qgroupid); | 1129 | ret = del_qgroup_item(trans, quota_root, qgroupid); |
1000 | 1130 | ||
1001 | spin_lock(&fs_info->qgroup_lock); | 1131 | spin_lock(&fs_info->qgroup_lock); |
1002 | del_qgroup_rb(quota_root->fs_info, qgroupid); | 1132 | del_qgroup_rb(quota_root->fs_info, qgroupid); |
1003 | spin_unlock(&fs_info->qgroup_lock); | 1133 | spin_unlock(&fs_info->qgroup_lock); |
1004 | 1134 | out: | |
1135 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
1005 | return ret; | 1136 | return ret; |
1006 | } | 1137 | } |
1007 | 1138 | ||
@@ -1009,13 +1140,22 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, | |||
1009 | struct btrfs_fs_info *fs_info, u64 qgroupid, | 1140 | struct btrfs_fs_info *fs_info, u64 qgroupid, |
1010 | struct btrfs_qgroup_limit *limit) | 1141 | struct btrfs_qgroup_limit *limit) |
1011 | { | 1142 | { |
1012 | struct btrfs_root *quota_root = fs_info->quota_root; | 1143 | struct btrfs_root *quota_root; |
1013 | struct btrfs_qgroup *qgroup; | 1144 | struct btrfs_qgroup *qgroup; |
1014 | int ret = 0; | 1145 | int ret = 0; |
1015 | 1146 | ||
1016 | if (!quota_root) | 1147 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
1017 | return -EINVAL; | 1148 | quota_root = fs_info->quota_root; |
1149 | if (!quota_root) { | ||
1150 | ret = -EINVAL; | ||
1151 | goto out; | ||
1152 | } | ||
1018 | 1153 | ||
1154 | qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
1155 | if (!qgroup) { | ||
1156 | ret = -ENOENT; | ||
1157 | goto out; | ||
1158 | } | ||
1019 | ret = update_qgroup_limit_item(trans, quota_root, qgroupid, | 1159 | ret = update_qgroup_limit_item(trans, quota_root, qgroupid, |
1020 | limit->flags, limit->max_rfer, | 1160 | limit->flags, limit->max_rfer, |
1021 | limit->max_excl, limit->rsv_rfer, | 1161 | limit->max_excl, limit->rsv_rfer, |
@@ -1027,31 +1167,17 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, | |||
1027 | } | 1167 | } |
1028 | 1168 | ||
1029 | spin_lock(&fs_info->qgroup_lock); | 1169 | spin_lock(&fs_info->qgroup_lock); |
1030 | |||
1031 | qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
1032 | if (!qgroup) { | ||
1033 | ret = -ENOENT; | ||
1034 | goto unlock; | ||
1035 | } | ||
1036 | qgroup->lim_flags = limit->flags; | 1170 | qgroup->lim_flags = limit->flags; |
1037 | qgroup->max_rfer = limit->max_rfer; | 1171 | qgroup->max_rfer = limit->max_rfer; |
1038 | qgroup->max_excl = limit->max_excl; | 1172 | qgroup->max_excl = limit->max_excl; |
1039 | qgroup->rsv_rfer = limit->rsv_rfer; | 1173 | qgroup->rsv_rfer = limit->rsv_rfer; |
1040 | qgroup->rsv_excl = limit->rsv_excl; | 1174 | qgroup->rsv_excl = limit->rsv_excl; |
1041 | |||
1042 | unlock: | ||
1043 | spin_unlock(&fs_info->qgroup_lock); | 1175 | spin_unlock(&fs_info->qgroup_lock); |
1044 | 1176 | out: | |
1177 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
1045 | return ret; | 1178 | return ret; |
1046 | } | 1179 | } |
1047 | 1180 | ||
1048 | static void qgroup_dirty(struct btrfs_fs_info *fs_info, | ||
1049 | struct btrfs_qgroup *qgroup) | ||
1050 | { | ||
1051 | if (list_empty(&qgroup->dirty)) | ||
1052 | list_add(&qgroup->dirty, &fs_info->dirty_qgroups); | ||
1053 | } | ||
1054 | |||
1055 | /* | 1181 | /* |
1056 | * btrfs_qgroup_record_ref is called when the ref is added or deleted. it puts | 1182 | * btrfs_qgroup_record_ref is called when the ref is added or deleted. it puts |
1057 | * the modification into a list that's later used by btrfs_end_transaction to | 1183 | * the modification into a list that's later used by btrfs_end_transaction to |
@@ -1075,6 +1201,144 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans, | |||
1075 | return 0; | 1201 | return 0; |
1076 | } | 1202 | } |
1077 | 1203 | ||
1204 | static int qgroup_account_ref_step1(struct btrfs_fs_info *fs_info, | ||
1205 | struct ulist *roots, struct ulist *tmp, | ||
1206 | u64 seq) | ||
1207 | { | ||
1208 | struct ulist_node *unode; | ||
1209 | struct ulist_iterator uiter; | ||
1210 | struct ulist_node *tmp_unode; | ||
1211 | struct ulist_iterator tmp_uiter; | ||
1212 | struct btrfs_qgroup *qg; | ||
1213 | int ret; | ||
1214 | |||
1215 | ULIST_ITER_INIT(&uiter); | ||
1216 | while ((unode = ulist_next(roots, &uiter))) { | ||
1217 | qg = find_qgroup_rb(fs_info, unode->val); | ||
1218 | if (!qg) | ||
1219 | continue; | ||
1220 | |||
1221 | ulist_reinit(tmp); | ||
1222 | /* XXX id not needed */ | ||
1223 | ret = ulist_add(tmp, qg->qgroupid, | ||
1224 | (u64)(uintptr_t)qg, GFP_ATOMIC); | ||
1225 | if (ret < 0) | ||
1226 | return ret; | ||
1227 | ULIST_ITER_INIT(&tmp_uiter); | ||
1228 | while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { | ||
1229 | struct btrfs_qgroup_list *glist; | ||
1230 | |||
1231 | qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; | ||
1232 | if (qg->refcnt < seq) | ||
1233 | qg->refcnt = seq + 1; | ||
1234 | else | ||
1235 | ++qg->refcnt; | ||
1236 | |||
1237 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
1238 | ret = ulist_add(tmp, glist->group->qgroupid, | ||
1239 | (u64)(uintptr_t)glist->group, | ||
1240 | GFP_ATOMIC); | ||
1241 | if (ret < 0) | ||
1242 | return ret; | ||
1243 | } | ||
1244 | } | ||
1245 | } | ||
1246 | |||
1247 | return 0; | ||
1248 | } | ||
1249 | |||
1250 | static int qgroup_account_ref_step2(struct btrfs_fs_info *fs_info, | ||
1251 | struct ulist *roots, struct ulist *tmp, | ||
1252 | u64 seq, int sgn, u64 num_bytes, | ||
1253 | struct btrfs_qgroup *qgroup) | ||
1254 | { | ||
1255 | struct ulist_node *unode; | ||
1256 | struct ulist_iterator uiter; | ||
1257 | struct btrfs_qgroup *qg; | ||
1258 | struct btrfs_qgroup_list *glist; | ||
1259 | int ret; | ||
1260 | |||
1261 | ulist_reinit(tmp); | ||
1262 | ret = ulist_add(tmp, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC); | ||
1263 | if (ret < 0) | ||
1264 | return ret; | ||
1265 | |||
1266 | ULIST_ITER_INIT(&uiter); | ||
1267 | while ((unode = ulist_next(tmp, &uiter))) { | ||
1268 | qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux; | ||
1269 | if (qg->refcnt < seq) { | ||
1270 | /* not visited by step 1 */ | ||
1271 | qg->rfer += sgn * num_bytes; | ||
1272 | qg->rfer_cmpr += sgn * num_bytes; | ||
1273 | if (roots->nnodes == 0) { | ||
1274 | qg->excl += sgn * num_bytes; | ||
1275 | qg->excl_cmpr += sgn * num_bytes; | ||
1276 | } | ||
1277 | qgroup_dirty(fs_info, qg); | ||
1278 | } | ||
1279 | WARN_ON(qg->tag >= seq); | ||
1280 | qg->tag = seq; | ||
1281 | |||
1282 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
1283 | ret = ulist_add(tmp, glist->group->qgroupid, | ||
1284 | (uintptr_t)glist->group, GFP_ATOMIC); | ||
1285 | if (ret < 0) | ||
1286 | return ret; | ||
1287 | } | ||
1288 | } | ||
1289 | |||
1290 | return 0; | ||
1291 | } | ||
1292 | |||
1293 | static int qgroup_account_ref_step3(struct btrfs_fs_info *fs_info, | ||
1294 | struct ulist *roots, struct ulist *tmp, | ||
1295 | u64 seq, int sgn, u64 num_bytes) | ||
1296 | { | ||
1297 | struct ulist_node *unode; | ||
1298 | struct ulist_iterator uiter; | ||
1299 | struct btrfs_qgroup *qg; | ||
1300 | struct ulist_node *tmp_unode; | ||
1301 | struct ulist_iterator tmp_uiter; | ||
1302 | int ret; | ||
1303 | |||
1304 | ULIST_ITER_INIT(&uiter); | ||
1305 | while ((unode = ulist_next(roots, &uiter))) { | ||
1306 | qg = find_qgroup_rb(fs_info, unode->val); | ||
1307 | if (!qg) | ||
1308 | continue; | ||
1309 | |||
1310 | ulist_reinit(tmp); | ||
1311 | ret = ulist_add(tmp, qg->qgroupid, (uintptr_t)qg, GFP_ATOMIC); | ||
1312 | if (ret < 0) | ||
1313 | return ret; | ||
1314 | |||
1315 | ULIST_ITER_INIT(&tmp_uiter); | ||
1316 | while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { | ||
1317 | struct btrfs_qgroup_list *glist; | ||
1318 | |||
1319 | qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; | ||
1320 | if (qg->tag == seq) | ||
1321 | continue; | ||
1322 | |||
1323 | if (qg->refcnt - seq == roots->nnodes) { | ||
1324 | qg->excl -= sgn * num_bytes; | ||
1325 | qg->excl_cmpr -= sgn * num_bytes; | ||
1326 | qgroup_dirty(fs_info, qg); | ||
1327 | } | ||
1328 | |||
1329 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
1330 | ret = ulist_add(tmp, glist->group->qgroupid, | ||
1331 | (uintptr_t)glist->group, | ||
1332 | GFP_ATOMIC); | ||
1333 | if (ret < 0) | ||
1334 | return ret; | ||
1335 | } | ||
1336 | } | ||
1337 | } | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1078 | /* | 1342 | /* |
1079 | * btrfs_qgroup_account_ref is called for every ref that is added to or deleted | 1343 | * btrfs_qgroup_account_ref is called for every ref that is added to or deleted |
1080 | * from the fs. First, all roots referencing the extent are searched, and | 1344 | * from the fs. First, all roots referencing the extent are searched, and |
@@ -1090,10 +1354,8 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans, | |||
1090 | struct btrfs_root *quota_root; | 1354 | struct btrfs_root *quota_root; |
1091 | u64 ref_root; | 1355 | u64 ref_root; |
1092 | struct btrfs_qgroup *qgroup; | 1356 | struct btrfs_qgroup *qgroup; |
1093 | struct ulist_node *unode; | ||
1094 | struct ulist *roots = NULL; | 1357 | struct ulist *roots = NULL; |
1095 | struct ulist *tmp = NULL; | 1358 | struct ulist *tmp = NULL; |
1096 | struct ulist_iterator uiter; | ||
1097 | u64 seq; | 1359 | u64 seq; |
1098 | int ret = 0; | 1360 | int ret = 0; |
1099 | int sgn; | 1361 | int sgn; |
@@ -1132,9 +1394,11 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans, | |||
1132 | case BTRFS_ADD_DELAYED_REF: | 1394 | case BTRFS_ADD_DELAYED_REF: |
1133 | case BTRFS_ADD_DELAYED_EXTENT: | 1395 | case BTRFS_ADD_DELAYED_EXTENT: |
1134 | sgn = 1; | 1396 | sgn = 1; |
1397 | seq = btrfs_tree_mod_seq_prev(node->seq); | ||
1135 | break; | 1398 | break; |
1136 | case BTRFS_DROP_DELAYED_REF: | 1399 | case BTRFS_DROP_DELAYED_REF: |
1137 | sgn = -1; | 1400 | sgn = -1; |
1401 | seq = node->seq; | ||
1138 | break; | 1402 | break; |
1139 | case BTRFS_UPDATE_DELAYED_HEAD: | 1403 | case BTRFS_UPDATE_DELAYED_HEAD: |
1140 | return 0; | 1404 | return 0; |
@@ -1142,20 +1406,37 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans, | |||
1142 | BUG(); | 1406 | BUG(); |
1143 | } | 1407 | } |
1144 | 1408 | ||
1409 | mutex_lock(&fs_info->qgroup_rescan_lock); | ||
1410 | if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) { | ||
1411 | if (fs_info->qgroup_rescan_progress.objectid <= node->bytenr) { | ||
1412 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
1413 | return 0; | ||
1414 | } | ||
1415 | } | ||
1416 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
1417 | |||
1145 | /* | 1418 | /* |
1146 | * the delayed ref sequence number we pass depends on the direction of | 1419 | * the delayed ref sequence number we pass depends on the direction of |
1147 | * the operation. for add operations, we pass (node->seq - 1) to skip | 1420 | * the operation. for add operations, we pass |
1421 | * tree_mod_log_prev_seq(node->seq) to skip | ||
1148 | * the delayed ref's current sequence number, because we need the state | 1422 | * the delayed ref's current sequence number, because we need the state |
1149 | * of the tree before the add operation. for delete operations, we pass | 1423 | * of the tree before the add operation. for delete operations, we pass |
1150 | * (node->seq) to include the delayed ref's current sequence number, | 1424 | * (node->seq) to include the delayed ref's current sequence number, |
1151 | * because we need the state of the tree after the delete operation. | 1425 | * because we need the state of the tree after the delete operation. |
1152 | */ | 1426 | */ |
1153 | ret = btrfs_find_all_roots(trans, fs_info, node->bytenr, | 1427 | ret = btrfs_find_all_roots(trans, fs_info, node->bytenr, seq, &roots); |
1154 | sgn > 0 ? node->seq - 1 : node->seq, &roots); | ||
1155 | if (ret < 0) | 1428 | if (ret < 0) |
1156 | return ret; | 1429 | return ret; |
1157 | 1430 | ||
1431 | mutex_lock(&fs_info->qgroup_rescan_lock); | ||
1158 | spin_lock(&fs_info->qgroup_lock); | 1432 | spin_lock(&fs_info->qgroup_lock); |
1433 | if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) { | ||
1434 | if (fs_info->qgroup_rescan_progress.objectid <= node->bytenr) { | ||
1435 | ret = 0; | ||
1436 | goto unlock; | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1159 | quota_root = fs_info->quota_root; | 1440 | quota_root = fs_info->quota_root; |
1160 | if (!quota_root) | 1441 | if (!quota_root) |
1161 | goto unlock; | 1442 | goto unlock; |
@@ -1175,106 +1456,29 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans, | |||
1175 | seq = fs_info->qgroup_seq; | 1456 | seq = fs_info->qgroup_seq; |
1176 | fs_info->qgroup_seq += roots->nnodes + 1; /* max refcnt */ | 1457 | fs_info->qgroup_seq += roots->nnodes + 1; /* max refcnt */ |
1177 | 1458 | ||
1178 | ULIST_ITER_INIT(&uiter); | 1459 | ret = qgroup_account_ref_step1(fs_info, roots, tmp, seq); |
1179 | while ((unode = ulist_next(roots, &uiter))) { | 1460 | if (ret) |
1180 | struct ulist_node *tmp_unode; | 1461 | goto unlock; |
1181 | struct ulist_iterator tmp_uiter; | ||
1182 | struct btrfs_qgroup *qg; | ||
1183 | |||
1184 | qg = find_qgroup_rb(fs_info, unode->val); | ||
1185 | if (!qg) | ||
1186 | continue; | ||
1187 | |||
1188 | ulist_reinit(tmp); | ||
1189 | /* XXX id not needed */ | ||
1190 | ulist_add(tmp, qg->qgroupid, (u64)(uintptr_t)qg, GFP_ATOMIC); | ||
1191 | ULIST_ITER_INIT(&tmp_uiter); | ||
1192 | while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { | ||
1193 | struct btrfs_qgroup_list *glist; | ||
1194 | |||
1195 | qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; | ||
1196 | if (qg->refcnt < seq) | ||
1197 | qg->refcnt = seq + 1; | ||
1198 | else | ||
1199 | ++qg->refcnt; | ||
1200 | |||
1201 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
1202 | ulist_add(tmp, glist->group->qgroupid, | ||
1203 | (u64)(uintptr_t)glist->group, | ||
1204 | GFP_ATOMIC); | ||
1205 | } | ||
1206 | } | ||
1207 | } | ||
1208 | 1462 | ||
1209 | /* | 1463 | /* |
1210 | * step 2: walk from the new root | 1464 | * step 2: walk from the new root |
1211 | */ | 1465 | */ |
1212 | ulist_reinit(tmp); | 1466 | ret = qgroup_account_ref_step2(fs_info, roots, tmp, seq, sgn, |
1213 | ulist_add(tmp, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC); | 1467 | node->num_bytes, qgroup); |
1214 | ULIST_ITER_INIT(&uiter); | 1468 | if (ret) |
1215 | while ((unode = ulist_next(tmp, &uiter))) { | 1469 | goto unlock; |
1216 | struct btrfs_qgroup *qg; | ||
1217 | struct btrfs_qgroup_list *glist; | ||
1218 | |||
1219 | qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux; | ||
1220 | if (qg->refcnt < seq) { | ||
1221 | /* not visited by step 1 */ | ||
1222 | qg->rfer += sgn * node->num_bytes; | ||
1223 | qg->rfer_cmpr += sgn * node->num_bytes; | ||
1224 | if (roots->nnodes == 0) { | ||
1225 | qg->excl += sgn * node->num_bytes; | ||
1226 | qg->excl_cmpr += sgn * node->num_bytes; | ||
1227 | } | ||
1228 | qgroup_dirty(fs_info, qg); | ||
1229 | } | ||
1230 | WARN_ON(qg->tag >= seq); | ||
1231 | qg->tag = seq; | ||
1232 | |||
1233 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
1234 | ulist_add(tmp, glist->group->qgroupid, | ||
1235 | (uintptr_t)glist->group, GFP_ATOMIC); | ||
1236 | } | ||
1237 | } | ||
1238 | 1470 | ||
1239 | /* | 1471 | /* |
1240 | * step 3: walk again from old refs | 1472 | * step 3: walk again from old refs |
1241 | */ | 1473 | */ |
1242 | ULIST_ITER_INIT(&uiter); | 1474 | ret = qgroup_account_ref_step3(fs_info, roots, tmp, seq, sgn, |
1243 | while ((unode = ulist_next(roots, &uiter))) { | 1475 | node->num_bytes); |
1244 | struct btrfs_qgroup *qg; | 1476 | if (ret) |
1245 | struct ulist_node *tmp_unode; | 1477 | goto unlock; |
1246 | struct ulist_iterator tmp_uiter; | ||
1247 | |||
1248 | qg = find_qgroup_rb(fs_info, unode->val); | ||
1249 | if (!qg) | ||
1250 | continue; | ||
1251 | |||
1252 | ulist_reinit(tmp); | ||
1253 | ulist_add(tmp, qg->qgroupid, (uintptr_t)qg, GFP_ATOMIC); | ||
1254 | ULIST_ITER_INIT(&tmp_uiter); | ||
1255 | while ((tmp_unode = ulist_next(tmp, &tmp_uiter))) { | ||
1256 | struct btrfs_qgroup_list *glist; | ||
1257 | |||
1258 | qg = (struct btrfs_qgroup *)(uintptr_t)tmp_unode->aux; | ||
1259 | if (qg->tag == seq) | ||
1260 | continue; | ||
1261 | |||
1262 | if (qg->refcnt - seq == roots->nnodes) { | ||
1263 | qg->excl -= sgn * node->num_bytes; | ||
1264 | qg->excl_cmpr -= sgn * node->num_bytes; | ||
1265 | qgroup_dirty(fs_info, qg); | ||
1266 | } | ||
1267 | 1478 | ||
1268 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
1269 | ulist_add(tmp, glist->group->qgroupid, | ||
1270 | (uintptr_t)glist->group, | ||
1271 | GFP_ATOMIC); | ||
1272 | } | ||
1273 | } | ||
1274 | } | ||
1275 | ret = 0; | ||
1276 | unlock: | 1479 | unlock: |
1277 | spin_unlock(&fs_info->qgroup_lock); | 1480 | spin_unlock(&fs_info->qgroup_lock); |
1481 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
1278 | ulist_free(roots); | 1482 | ulist_free(roots); |
1279 | ulist_free(tmp); | 1483 | ulist_free(tmp); |
1280 | 1484 | ||
@@ -1289,10 +1493,14 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans, | |||
1289 | { | 1493 | { |
1290 | struct btrfs_root *quota_root = fs_info->quota_root; | 1494 | struct btrfs_root *quota_root = fs_info->quota_root; |
1291 | int ret = 0; | 1495 | int ret = 0; |
1496 | int start_rescan_worker = 0; | ||
1292 | 1497 | ||
1293 | if (!quota_root) | 1498 | if (!quota_root) |
1294 | goto out; | 1499 | goto out; |
1295 | 1500 | ||
1501 | if (!fs_info->quota_enabled && fs_info->pending_quota_state) | ||
1502 | start_rescan_worker = 1; | ||
1503 | |||
1296 | fs_info->quota_enabled = fs_info->pending_quota_state; | 1504 | fs_info->quota_enabled = fs_info->pending_quota_state; |
1297 | 1505 | ||
1298 | spin_lock(&fs_info->qgroup_lock); | 1506 | spin_lock(&fs_info->qgroup_lock); |
@@ -1318,6 +1526,13 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans, | |||
1318 | if (ret) | 1526 | if (ret) |
1319 | fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; | 1527 | fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; |
1320 | 1528 | ||
1529 | if (!ret && start_rescan_worker) { | ||
1530 | ret = btrfs_qgroup_rescan(fs_info); | ||
1531 | if (ret) | ||
1532 | pr_err("btrfs: start rescan quota failed: %d\n", ret); | ||
1533 | ret = 0; | ||
1534 | } | ||
1535 | |||
1321 | out: | 1536 | out: |
1322 | 1537 | ||
1323 | return ret; | 1538 | return ret; |
@@ -1338,12 +1553,30 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | |||
1338 | struct btrfs_qgroup *srcgroup; | 1553 | struct btrfs_qgroup *srcgroup; |
1339 | struct btrfs_qgroup *dstgroup; | 1554 | struct btrfs_qgroup *dstgroup; |
1340 | u32 level_size = 0; | 1555 | u32 level_size = 0; |
1556 | u64 nums; | ||
1341 | 1557 | ||
1558 | mutex_lock(&fs_info->qgroup_ioctl_lock); | ||
1342 | if (!fs_info->quota_enabled) | 1559 | if (!fs_info->quota_enabled) |
1343 | return 0; | 1560 | goto out; |
1344 | 1561 | ||
1345 | if (!quota_root) | 1562 | if (!quota_root) { |
1346 | return -EINVAL; | 1563 | ret = -EINVAL; |
1564 | goto out; | ||
1565 | } | ||
1566 | |||
1567 | if (inherit) { | ||
1568 | i_qgroups = (u64 *)(inherit + 1); | ||
1569 | nums = inherit->num_qgroups + 2 * inherit->num_ref_copies + | ||
1570 | 2 * inherit->num_excl_copies; | ||
1571 | for (i = 0; i < nums; ++i) { | ||
1572 | srcgroup = find_qgroup_rb(fs_info, *i_qgroups); | ||
1573 | if (!srcgroup) { | ||
1574 | ret = -EINVAL; | ||
1575 | goto out; | ||
1576 | } | ||
1577 | ++i_qgroups; | ||
1578 | } | ||
1579 | } | ||
1347 | 1580 | ||
1348 | /* | 1581 | /* |
1349 | * create a tracking group for the subvol itself | 1582 | * create a tracking group for the subvol itself |
@@ -1470,6 +1703,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, | |||
1470 | unlock: | 1703 | unlock: |
1471 | spin_unlock(&fs_info->qgroup_lock); | 1704 | spin_unlock(&fs_info->qgroup_lock); |
1472 | out: | 1705 | out: |
1706 | mutex_unlock(&fs_info->qgroup_ioctl_lock); | ||
1473 | return ret; | 1707 | return ret; |
1474 | } | 1708 | } |
1475 | 1709 | ||
@@ -1514,7 +1748,10 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) | |||
1514 | ret = -ENOMEM; | 1748 | ret = -ENOMEM; |
1515 | goto out; | 1749 | goto out; |
1516 | } | 1750 | } |
1517 | ulist_add(ulist, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC); | 1751 | ret = ulist_add(ulist, qgroup->qgroupid, |
1752 | (uintptr_t)qgroup, GFP_ATOMIC); | ||
1753 | if (ret < 0) | ||
1754 | goto out; | ||
1518 | ULIST_ITER_INIT(&uiter); | 1755 | ULIST_ITER_INIT(&uiter); |
1519 | while ((unode = ulist_next(ulist, &uiter))) { | 1756 | while ((unode = ulist_next(ulist, &uiter))) { |
1520 | struct btrfs_qgroup *qg; | 1757 | struct btrfs_qgroup *qg; |
@@ -1523,25 +1760,27 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes) | |||
1523 | qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux; | 1760 | qg = (struct btrfs_qgroup *)(uintptr_t)unode->aux; |
1524 | 1761 | ||
1525 | if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) && | 1762 | if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) && |
1526 | qg->reserved + qg->rfer + num_bytes > | 1763 | qg->reserved + (s64)qg->rfer + num_bytes > |
1527 | qg->max_rfer) { | 1764 | qg->max_rfer) { |
1528 | ret = -EDQUOT; | 1765 | ret = -EDQUOT; |
1529 | goto out; | 1766 | goto out; |
1530 | } | 1767 | } |
1531 | 1768 | ||
1532 | if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) && | 1769 | if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) && |
1533 | qg->reserved + qg->excl + num_bytes > | 1770 | qg->reserved + (s64)qg->excl + num_bytes > |
1534 | qg->max_excl) { | 1771 | qg->max_excl) { |
1535 | ret = -EDQUOT; | 1772 | ret = -EDQUOT; |
1536 | goto out; | 1773 | goto out; |
1537 | } | 1774 | } |
1538 | 1775 | ||
1539 | list_for_each_entry(glist, &qg->groups, next_group) { | 1776 | list_for_each_entry(glist, &qg->groups, next_group) { |
1540 | ulist_add(ulist, glist->group->qgroupid, | 1777 | ret = ulist_add(ulist, glist->group->qgroupid, |
1541 | (uintptr_t)glist->group, GFP_ATOMIC); | 1778 | (uintptr_t)glist->group, GFP_ATOMIC); |
1779 | if (ret < 0) | ||
1780 | goto out; | ||
1542 | } | 1781 | } |
1543 | } | 1782 | } |
1544 | 1783 | ret = 0; | |
1545 | /* | 1784 | /* |
1546 | * no limits exceeded, now record the reservation into all qgroups | 1785 | * no limits exceeded, now record the reservation into all qgroups |
1547 | */ | 1786 | */ |
@@ -1570,6 +1809,7 @@ void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) | |||
1570 | struct ulist_node *unode; | 1809 | struct ulist_node *unode; |
1571 | struct ulist_iterator uiter; | 1810 | struct ulist_iterator uiter; |
1572 | u64 ref_root = root->root_key.objectid; | 1811 | u64 ref_root = root->root_key.objectid; |
1812 | int ret = 0; | ||
1573 | 1813 | ||
1574 | if (!is_fstree(ref_root)) | 1814 | if (!is_fstree(ref_root)) |
1575 | return; | 1815 | return; |
@@ -1592,7 +1832,10 @@ void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) | |||
1592 | btrfs_std_error(fs_info, -ENOMEM); | 1832 | btrfs_std_error(fs_info, -ENOMEM); |
1593 | goto out; | 1833 | goto out; |
1594 | } | 1834 | } |
1595 | ulist_add(ulist, qgroup->qgroupid, (uintptr_t)qgroup, GFP_ATOMIC); | 1835 | ret = ulist_add(ulist, qgroup->qgroupid, |
1836 | (uintptr_t)qgroup, GFP_ATOMIC); | ||
1837 | if (ret < 0) | ||
1838 | goto out; | ||
1596 | ULIST_ITER_INIT(&uiter); | 1839 | ULIST_ITER_INIT(&uiter); |
1597 | while ((unode = ulist_next(ulist, &uiter))) { | 1840 | while ((unode = ulist_next(ulist, &uiter))) { |
1598 | struct btrfs_qgroup *qg; | 1841 | struct btrfs_qgroup *qg; |
@@ -1603,8 +1846,10 @@ void btrfs_qgroup_free(struct btrfs_root *root, u64 num_bytes) | |||
1603 | qg->reserved -= num_bytes; | 1846 | qg->reserved -= num_bytes; |
1604 | 1847 | ||
1605 | list_for_each_entry(glist, &qg->groups, next_group) { | 1848 | list_for_each_entry(glist, &qg->groups, next_group) { |
1606 | ulist_add(ulist, glist->group->qgroupid, | 1849 | ret = ulist_add(ulist, glist->group->qgroupid, |
1607 | (uintptr_t)glist->group, GFP_ATOMIC); | 1850 | (uintptr_t)glist->group, GFP_ATOMIC); |
1851 | if (ret < 0) | ||
1852 | goto out; | ||
1608 | } | 1853 | } |
1609 | } | 1854 | } |
1610 | 1855 | ||
@@ -1617,8 +1862,265 @@ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans) | |||
1617 | { | 1862 | { |
1618 | if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq) | 1863 | if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq) |
1619 | return; | 1864 | return; |
1620 | printk(KERN_ERR "btrfs: qgroups not uptodate in trans handle %p: list is%s empty, seq is %llu\n", | 1865 | pr_err("btrfs: qgroups not uptodate in trans handle %p: list is%s empty, seq is %#x.%x\n", |
1621 | trans, list_empty(&trans->qgroup_ref_list) ? "" : " not", | 1866 | trans, list_empty(&trans->qgroup_ref_list) ? "" : " not", |
1622 | trans->delayed_ref_elem.seq); | 1867 | (u32)(trans->delayed_ref_elem.seq >> 32), |
1868 | (u32)trans->delayed_ref_elem.seq); | ||
1623 | BUG(); | 1869 | BUG(); |
1624 | } | 1870 | } |
1871 | |||
1872 | /* | ||
1873 | * returns < 0 on error, 0 when more leafs are to be scanned. | ||
1874 | * returns 1 when done, 2 when done and FLAG_INCONSISTENT was cleared. | ||
1875 | */ | ||
1876 | static int | ||
1877 | qgroup_rescan_leaf(struct qgroup_rescan *qscan, struct btrfs_path *path, | ||
1878 | struct btrfs_trans_handle *trans, struct ulist *tmp, | ||
1879 | struct extent_buffer *scratch_leaf) | ||
1880 | { | ||
1881 | struct btrfs_key found; | ||
1882 | struct btrfs_fs_info *fs_info = qscan->fs_info; | ||
1883 | struct ulist *roots = NULL; | ||
1884 | struct ulist_node *unode; | ||
1885 | struct ulist_iterator uiter; | ||
1886 | struct seq_list tree_mod_seq_elem = {}; | ||
1887 | u64 seq; | ||
1888 | int slot; | ||
1889 | int ret; | ||
1890 | |||
1891 | path->leave_spinning = 1; | ||
1892 | mutex_lock(&fs_info->qgroup_rescan_lock); | ||
1893 | ret = btrfs_search_slot_for_read(fs_info->extent_root, | ||
1894 | &fs_info->qgroup_rescan_progress, | ||
1895 | path, 1, 0); | ||
1896 | |||
1897 | pr_debug("current progress key (%llu %u %llu), search_slot ret %d\n", | ||
1898 | (unsigned long long)fs_info->qgroup_rescan_progress.objectid, | ||
1899 | fs_info->qgroup_rescan_progress.type, | ||
1900 | (unsigned long long)fs_info->qgroup_rescan_progress.offset, | ||
1901 | ret); | ||
1902 | |||
1903 | if (ret) { | ||
1904 | /* | ||
1905 | * The rescan is about to end, we will not be scanning any | ||
1906 | * further blocks. We cannot unset the RESCAN flag here, because | ||
1907 | * we want to commit the transaction if everything went well. | ||
1908 | * To make the live accounting work in this phase, we set our | ||
1909 | * scan progress pointer such that every real extent objectid | ||
1910 | * will be smaller. | ||
1911 | */ | ||
1912 | fs_info->qgroup_rescan_progress.objectid = (u64)-1; | ||
1913 | btrfs_release_path(path); | ||
1914 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
1915 | return ret; | ||
1916 | } | ||
1917 | |||
1918 | btrfs_item_key_to_cpu(path->nodes[0], &found, | ||
1919 | btrfs_header_nritems(path->nodes[0]) - 1); | ||
1920 | fs_info->qgroup_rescan_progress.objectid = found.objectid + 1; | ||
1921 | |||
1922 | btrfs_get_tree_mod_seq(fs_info, &tree_mod_seq_elem); | ||
1923 | memcpy(scratch_leaf, path->nodes[0], sizeof(*scratch_leaf)); | ||
1924 | slot = path->slots[0]; | ||
1925 | btrfs_release_path(path); | ||
1926 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
1927 | |||
1928 | for (; slot < btrfs_header_nritems(scratch_leaf); ++slot) { | ||
1929 | btrfs_item_key_to_cpu(scratch_leaf, &found, slot); | ||
1930 | if (found.type != BTRFS_EXTENT_ITEM_KEY) | ||
1931 | continue; | ||
1932 | ret = btrfs_find_all_roots(trans, fs_info, found.objectid, | ||
1933 | tree_mod_seq_elem.seq, &roots); | ||
1934 | if (ret < 0) | ||
1935 | goto out; | ||
1936 | spin_lock(&fs_info->qgroup_lock); | ||
1937 | seq = fs_info->qgroup_seq; | ||
1938 | fs_info->qgroup_seq += roots->nnodes + 1; /* max refcnt */ | ||
1939 | |||
1940 | ret = qgroup_account_ref_step1(fs_info, roots, tmp, seq); | ||
1941 | if (ret) { | ||
1942 | spin_unlock(&fs_info->qgroup_lock); | ||
1943 | ulist_free(roots); | ||
1944 | goto out; | ||
1945 | } | ||
1946 | |||
1947 | /* | ||
1948 | * step2 of btrfs_qgroup_account_ref works from a single root, | ||
1949 | * we're doing all at once here. | ||
1950 | */ | ||
1951 | ulist_reinit(tmp); | ||
1952 | ULIST_ITER_INIT(&uiter); | ||
1953 | while ((unode = ulist_next(roots, &uiter))) { | ||
1954 | struct btrfs_qgroup *qg; | ||
1955 | |||
1956 | qg = find_qgroup_rb(fs_info, unode->val); | ||
1957 | if (!qg) | ||
1958 | continue; | ||
1959 | |||
1960 | ret = ulist_add(tmp, qg->qgroupid, (uintptr_t)qg, | ||
1961 | GFP_ATOMIC); | ||
1962 | if (ret < 0) { | ||
1963 | spin_unlock(&fs_info->qgroup_lock); | ||
1964 | ulist_free(roots); | ||
1965 | goto out; | ||
1966 | } | ||
1967 | } | ||
1968 | |||
1969 | /* this loop is similar to step 2 of btrfs_qgroup_account_ref */ | ||
1970 | ULIST_ITER_INIT(&uiter); | ||
1971 | while ((unode = ulist_next(tmp, &uiter))) { | ||
1972 | struct btrfs_qgroup *qg; | ||
1973 | struct btrfs_qgroup_list *glist; | ||
1974 | |||
1975 | qg = (struct btrfs_qgroup *)(uintptr_t) unode->aux; | ||
1976 | qg->rfer += found.offset; | ||
1977 | qg->rfer_cmpr += found.offset; | ||
1978 | WARN_ON(qg->tag >= seq); | ||
1979 | if (qg->refcnt - seq == roots->nnodes) { | ||
1980 | qg->excl += found.offset; | ||
1981 | qg->excl_cmpr += found.offset; | ||
1982 | } | ||
1983 | qgroup_dirty(fs_info, qg); | ||
1984 | |||
1985 | list_for_each_entry(glist, &qg->groups, next_group) { | ||
1986 | ret = ulist_add(tmp, glist->group->qgroupid, | ||
1987 | (uintptr_t)glist->group, | ||
1988 | GFP_ATOMIC); | ||
1989 | if (ret < 0) { | ||
1990 | spin_unlock(&fs_info->qgroup_lock); | ||
1991 | ulist_free(roots); | ||
1992 | goto out; | ||
1993 | } | ||
1994 | } | ||
1995 | } | ||
1996 | |||
1997 | spin_unlock(&fs_info->qgroup_lock); | ||
1998 | ulist_free(roots); | ||
1999 | ret = 0; | ||
2000 | } | ||
2001 | |||
2002 | out: | ||
2003 | btrfs_put_tree_mod_seq(fs_info, &tree_mod_seq_elem); | ||
2004 | |||
2005 | return ret; | ||
2006 | } | ||
2007 | |||
2008 | static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) | ||
2009 | { | ||
2010 | struct qgroup_rescan *qscan = container_of(work, struct qgroup_rescan, | ||
2011 | work); | ||
2012 | struct btrfs_path *path; | ||
2013 | struct btrfs_trans_handle *trans = NULL; | ||
2014 | struct btrfs_fs_info *fs_info = qscan->fs_info; | ||
2015 | struct ulist *tmp = NULL; | ||
2016 | struct extent_buffer *scratch_leaf = NULL; | ||
2017 | int err = -ENOMEM; | ||
2018 | |||
2019 | path = btrfs_alloc_path(); | ||
2020 | if (!path) | ||
2021 | goto out; | ||
2022 | tmp = ulist_alloc(GFP_NOFS); | ||
2023 | if (!tmp) | ||
2024 | goto out; | ||
2025 | scratch_leaf = kmalloc(sizeof(*scratch_leaf), GFP_NOFS); | ||
2026 | if (!scratch_leaf) | ||
2027 | goto out; | ||
2028 | |||
2029 | err = 0; | ||
2030 | while (!err) { | ||
2031 | trans = btrfs_start_transaction(fs_info->fs_root, 0); | ||
2032 | if (IS_ERR(trans)) { | ||
2033 | err = PTR_ERR(trans); | ||
2034 | break; | ||
2035 | } | ||
2036 | if (!fs_info->quota_enabled) { | ||
2037 | err = -EINTR; | ||
2038 | } else { | ||
2039 | err = qgroup_rescan_leaf(qscan, path, trans, | ||
2040 | tmp, scratch_leaf); | ||
2041 | } | ||
2042 | if (err > 0) | ||
2043 | btrfs_commit_transaction(trans, fs_info->fs_root); | ||
2044 | else | ||
2045 | btrfs_end_transaction(trans, fs_info->fs_root); | ||
2046 | } | ||
2047 | |||
2048 | out: | ||
2049 | kfree(scratch_leaf); | ||
2050 | ulist_free(tmp); | ||
2051 | btrfs_free_path(path); | ||
2052 | kfree(qscan); | ||
2053 | |||
2054 | mutex_lock(&fs_info->qgroup_rescan_lock); | ||
2055 | fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN; | ||
2056 | |||
2057 | if (err == 2 && | ||
2058 | fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) { | ||
2059 | fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; | ||
2060 | } else if (err < 0) { | ||
2061 | fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; | ||
2062 | } | ||
2063 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
2064 | |||
2065 | if (err >= 0) { | ||
2066 | pr_info("btrfs: qgroup scan completed%s\n", | ||
2067 | err == 2 ? " (inconsistency flag cleared)" : ""); | ||
2068 | } else { | ||
2069 | pr_err("btrfs: qgroup scan failed with %d\n", err); | ||
2070 | } | ||
2071 | } | ||
2072 | |||
2073 | static void | ||
2074 | qgroup_rescan_start(struct btrfs_fs_info *fs_info, struct qgroup_rescan *qscan) | ||
2075 | { | ||
2076 | memset(&qscan->work, 0, sizeof(qscan->work)); | ||
2077 | qscan->work.func = btrfs_qgroup_rescan_worker; | ||
2078 | qscan->fs_info = fs_info; | ||
2079 | |||
2080 | pr_info("btrfs: qgroup scan started\n"); | ||
2081 | btrfs_queue_worker(&fs_info->qgroup_rescan_workers, &qscan->work); | ||
2082 | } | ||
2083 | |||
2084 | int | ||
2085 | btrfs_qgroup_rescan(struct btrfs_fs_info *fs_info) | ||
2086 | { | ||
2087 | int ret = 0; | ||
2088 | struct rb_node *n; | ||
2089 | struct btrfs_qgroup *qgroup; | ||
2090 | struct qgroup_rescan *qscan = kmalloc(sizeof(*qscan), GFP_NOFS); | ||
2091 | |||
2092 | if (!qscan) | ||
2093 | return -ENOMEM; | ||
2094 | |||
2095 | mutex_lock(&fs_info->qgroup_rescan_lock); | ||
2096 | spin_lock(&fs_info->qgroup_lock); | ||
2097 | if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) | ||
2098 | ret = -EINPROGRESS; | ||
2099 | else if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON)) | ||
2100 | ret = -EINVAL; | ||
2101 | if (ret) { | ||
2102 | spin_unlock(&fs_info->qgroup_lock); | ||
2103 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
2104 | kfree(qscan); | ||
2105 | return ret; | ||
2106 | } | ||
2107 | |||
2108 | fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN; | ||
2109 | memset(&fs_info->qgroup_rescan_progress, 0, | ||
2110 | sizeof(fs_info->qgroup_rescan_progress)); | ||
2111 | |||
2112 | /* clear all current qgroup tracking information */ | ||
2113 | for (n = rb_first(&fs_info->qgroup_tree); n; n = rb_next(n)) { | ||
2114 | qgroup = rb_entry(n, struct btrfs_qgroup, node); | ||
2115 | qgroup->rfer = 0; | ||
2116 | qgroup->rfer_cmpr = 0; | ||
2117 | qgroup->excl = 0; | ||
2118 | qgroup->excl_cmpr = 0; | ||
2119 | } | ||
2120 | spin_unlock(&fs_info->qgroup_lock); | ||
2121 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
2122 | |||
2123 | qgroup_rescan_start(fs_info, qscan); | ||
2124 | |||
2125 | return 0; | ||
2126 | } | ||