diff options
author | Wang Shilong <wangsl-fnst@cn.fujitsu.com> | 2013-02-27 06:16:57 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-03-01 10:13:03 -0500 |
commit | 06b3a860dcf596bdc2bb1cca3252d3907b581938 (patch) | |
tree | 9166d47ee4c0cc1c19521db17880b6a5b254c907 /fs | |
parent | b8dae3138876080d4dd98cc438ff759338d632ef (diff) |
Btrfs: fix missing deleted items in btrfs_clean_quota_tree
Steps to reproduce:
i=0
ncases=100
mkfs.btrfs <disk>
mount <disk> <mnt>
btrfs quota enable <mnt>
btrfs qgroup create 2/1 <mnt>
while [ $i -le $ncases ]
do
btrfs qgroup create 1/$i <mnt>
btrfs qgroup assign 1/$i 2/1 <mnt>
i=$(($i+1))
done
btrfs quota disable <mnt>
umount <mnt>
btrfsck <mnt>
You can also use the commands:
btrfs-debug-tree <disk> | grep QGROUP
You will find there are still items existed.The reasons why this happens
is because the original code just checks slots[0]==0 and returns.
We try to fix it by deleting the leaf one by one.
Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/qgroup.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 88ab785bbd73..f011d9b8ffb1 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -732,7 +732,9 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans, | |||
732 | { | 732 | { |
733 | struct btrfs_path *path; | 733 | struct btrfs_path *path; |
734 | struct btrfs_key key; | 734 | struct btrfs_key key; |
735 | struct extent_buffer *leaf = NULL; | ||
735 | int ret; | 736 | int ret; |
737 | int nr = 0; | ||
736 | 738 | ||
737 | if (!root) | 739 | if (!root) |
738 | return -EINVAL; | 740 | return -EINVAL; |
@@ -741,24 +743,30 @@ static int btrfs_clean_quota_tree(struct btrfs_trans_handle *trans, | |||
741 | if (!path) | 743 | if (!path) |
742 | return -ENOMEM; | 744 | return -ENOMEM; |
743 | 745 | ||
744 | while (1) { | 746 | path->leave_spinning = 1; |
745 | key.objectid = 0; | ||
746 | key.offset = 0; | ||
747 | key.type = 0; | ||
748 | 747 | ||
749 | path->leave_spinning = 1; | 748 | key.objectid = 0; |
749 | key.offset = 0; | ||
750 | key.type = 0; | ||
751 | |||
752 | while (1) { | ||
750 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 753 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
751 | if (ret > 0) { | 754 | if (ret < 0) |
752 | if (path->slots[0] == 0) | 755 | goto out; |
753 | break; | 756 | leaf = path->nodes[0]; |
754 | path->slots[0]--; | 757 | nr = btrfs_header_nritems(leaf); |
755 | } else if (ret < 0) { | 758 | if (!nr) |
756 | break; | 759 | break; |
757 | } | 760 | /* |
758 | 761 | * delete the leaf one by one | |
759 | ret = btrfs_del_item(trans, root, path); | 762 | * since the whole tree is going |
763 | * to be deleted. | ||
764 | */ | ||
765 | path->slots[0] = 0; | ||
766 | ret = btrfs_del_items(trans, root, path, 0, nr); | ||
760 | if (ret) | 767 | if (ret) |
761 | goto out; | 768 | goto out; |
769 | |||
762 | btrfs_release_path(path); | 770 | btrfs_release_path(path); |
763 | } | 771 | } |
764 | ret = 0; | 772 | ret = 0; |