diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2012-01-10 03:41:01 -0500 |
---|---|---|
committer | Li Zefan <lizf@cn.fujitsu.com> | 2012-01-10 21:26:31 -0500 |
commit | db804f23a72bada58f083dfad6a65d019ddb3bd4 (patch) | |
tree | 24c7a53995b61b5f98d87b8db136fc908a3a035f /fs/btrfs/free-space-cache.c | |
parent | d25223a0d22f7ec4203ec285dc6e51f696591ba3 (diff) |
Btrfs: add pinned extents to on-disk free space cache correctly
I got this while running xfstests:
[24256.836098] block group 317849600 has an wrong amount of free space
[24256.836100] btrfs: failed to load free space cache for block group 317849600
We should clamp the extent returned by find_first_extent_bit(),
so the start of the extent won't smaller than the start of the
block group.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index ec23d43d0c35..01840ef95a32 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -838,7 +838,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
838 | struct io_ctl io_ctl; | 838 | struct io_ctl io_ctl; |
839 | struct list_head bitmap_list; | 839 | struct list_head bitmap_list; |
840 | struct btrfs_key key; | 840 | struct btrfs_key key; |
841 | u64 start, end, len; | 841 | u64 start, extent_start, extent_end, len; |
842 | int entries = 0; | 842 | int entries = 0; |
843 | int bitmaps = 0; | 843 | int bitmaps = 0; |
844 | int ret; | 844 | int ret; |
@@ -857,25 +857,12 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
857 | struct btrfs_free_cluster, | 857 | struct btrfs_free_cluster, |
858 | block_group_list); | 858 | block_group_list); |
859 | 859 | ||
860 | /* | ||
861 | * We shouldn't have switched the pinned extents yet so this is the | ||
862 | * right one | ||
863 | */ | ||
864 | unpin = root->fs_info->pinned_extents; | ||
865 | |||
866 | /* Lock all pages first so we can lock the extent safely. */ | 860 | /* Lock all pages first so we can lock the extent safely. */ |
867 | io_ctl_prepare_pages(&io_ctl, inode, 0); | 861 | io_ctl_prepare_pages(&io_ctl, inode, 0); |
868 | 862 | ||
869 | lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, | 863 | lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, |
870 | 0, &cached_state, GFP_NOFS); | 864 | 0, &cached_state, GFP_NOFS); |
871 | 865 | ||
872 | /* | ||
873 | * When searching for pinned extents, we need to start at our start | ||
874 | * offset. | ||
875 | */ | ||
876 | if (block_group) | ||
877 | start = block_group->key.objectid; | ||
878 | |||
879 | node = rb_first(&ctl->free_space_offset); | 866 | node = rb_first(&ctl->free_space_offset); |
880 | if (!node && cluster) { | 867 | if (!node && cluster) { |
881 | node = rb_first(&cluster->root); | 868 | node = rb_first(&cluster->root); |
@@ -918,9 +905,20 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
918 | * We want to add any pinned extents to our free space cache | 905 | * We want to add any pinned extents to our free space cache |
919 | * so we don't leak the space | 906 | * so we don't leak the space |
920 | */ | 907 | */ |
908 | |||
909 | /* | ||
910 | * We shouldn't have switched the pinned extents yet so this is the | ||
911 | * right one | ||
912 | */ | ||
913 | unpin = root->fs_info->pinned_extents; | ||
914 | |||
915 | if (block_group) | ||
916 | start = block_group->key.objectid; | ||
917 | |||
921 | while (block_group && (start < block_group->key.objectid + | 918 | while (block_group && (start < block_group->key.objectid + |
922 | block_group->key.offset)) { | 919 | block_group->key.offset)) { |
923 | ret = find_first_extent_bit(unpin, start, &start, &end, | 920 | ret = find_first_extent_bit(unpin, start, |
921 | &extent_start, &extent_end, | ||
924 | EXTENT_DIRTY); | 922 | EXTENT_DIRTY); |
925 | if (ret) { | 923 | if (ret) { |
926 | ret = 0; | 924 | ret = 0; |
@@ -928,20 +926,21 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
928 | } | 926 | } |
929 | 927 | ||
930 | /* This pinned extent is out of our range */ | 928 | /* This pinned extent is out of our range */ |
931 | if (start >= block_group->key.objectid + | 929 | if (extent_start >= block_group->key.objectid + |
932 | block_group->key.offset) | 930 | block_group->key.offset) |
933 | break; | 931 | break; |
934 | 932 | ||
935 | len = block_group->key.objectid + | 933 | extent_start = max(extent_start, start); |
936 | block_group->key.offset - start; | 934 | extent_end = min(block_group->key.objectid + |
937 | len = min(len, end + 1 - start); | 935 | block_group->key.offset, extent_end + 1); |
936 | len = extent_end - extent_start; | ||
938 | 937 | ||
939 | entries++; | 938 | entries++; |
940 | ret = io_ctl_add_entry(&io_ctl, start, len, NULL); | 939 | ret = io_ctl_add_entry(&io_ctl, extent_start, len, NULL); |
941 | if (ret) | 940 | if (ret) |
942 | goto out_nospc; | 941 | goto out_nospc; |
943 | 942 | ||
944 | start = end + 1; | 943 | start = extent_end; |
945 | } | 944 | } |
946 | 945 | ||
947 | /* Write out the bitmaps */ | 946 | /* Write out the bitmaps */ |