diff options
author | Li Zefan <lizefan@huawei.com> | 2012-06-11 04:03:35 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-06-14 21:30:55 -0400 |
commit | 6c282eb40ed6f64a51ff447707714df551d85b8e (patch) | |
tree | 97d8a780a577d21c0f237f2140f3a129f40096bf /fs/btrfs/ioctl.c | |
parent | 7ddf5a42d311d74fd9f7373cb56def0843c219f8 (diff) |
Btrfs: fix defrag regression
If a file has 3 small extents:
| ext1 | ext2 | ext3 |
Running "btrfs fi defrag" will only defrag the last two extents, if those
extent mappings hasn't been read into memory from disk.
This bug was introduced by commit 17ce6ef8d731af5edac8c39e806db4c7e1f6956f
("Btrfs: add a check to decide if we should defrag the range")
The cause is, that commit looked into previous and next extents using
lookup_extent_mapping() only.
While at it, remove the code that checks the previous extent, since
it's sufficient to check the next extent.
Signed-off-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 97 |
1 files changed, 49 insertions, 48 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c5254dde1f0f..a98f7d252829 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -786,39 +786,57 @@ none: | |||
786 | return -ENOENT; | 786 | return -ENOENT; |
787 | } | 787 | } |
788 | 788 | ||
789 | /* | 789 | static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start) |
790 | * Validaty check of prev em and next em: | ||
791 | * 1) no prev/next em | ||
792 | * 2) prev/next em is an hole/inline extent | ||
793 | */ | ||
794 | static int check_adjacent_extents(struct inode *inode, struct extent_map *em) | ||
795 | { | 790 | { |
796 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 791 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
797 | struct extent_map *prev = NULL, *next = NULL; | 792 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
798 | int ret = 0; | 793 | struct extent_map *em; |
794 | u64 len = PAGE_CACHE_SIZE; | ||
799 | 795 | ||
796 | /* | ||
797 | * hopefully we have this extent in the tree already, try without | ||
798 | * the full extent lock | ||
799 | */ | ||
800 | read_lock(&em_tree->lock); | 800 | read_lock(&em_tree->lock); |
801 | prev = lookup_extent_mapping(em_tree, em->start - 1, (u64)-1); | 801 | em = lookup_extent_mapping(em_tree, start, len); |
802 | next = lookup_extent_mapping(em_tree, em->start + em->len, (u64)-1); | ||
803 | read_unlock(&em_tree->lock); | 802 | read_unlock(&em_tree->lock); |
804 | 803 | ||
805 | if ((!prev || prev->block_start >= EXTENT_MAP_LAST_BYTE) && | 804 | if (!em) { |
806 | (!next || next->block_start >= EXTENT_MAP_LAST_BYTE)) | 805 | /* get the big lock and read metadata off disk */ |
807 | ret = 1; | 806 | lock_extent(io_tree, start, start + len - 1); |
808 | free_extent_map(prev); | 807 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); |
809 | free_extent_map(next); | 808 | unlock_extent(io_tree, start, start + len - 1); |
810 | 809 | ||
810 | if (IS_ERR(em)) | ||
811 | return NULL; | ||
812 | } | ||
813 | |||
814 | return em; | ||
815 | } | ||
816 | |||
817 | static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em) | ||
818 | { | ||
819 | struct extent_map *next; | ||
820 | bool ret = true; | ||
821 | |||
822 | /* this is the last extent */ | ||
823 | if (em->start + em->len >= i_size_read(inode)) | ||
824 | return false; | ||
825 | |||
826 | next = defrag_lookup_extent(inode, em->start + em->len); | ||
827 | if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE) | ||
828 | ret = false; | ||
829 | |||
830 | free_extent_map(next); | ||
811 | return ret; | 831 | return ret; |
812 | } | 832 | } |
813 | 833 | ||
814 | static int should_defrag_range(struct inode *inode, u64 start, u64 len, | 834 | static int should_defrag_range(struct inode *inode, u64 start, int thresh, |
815 | int thresh, u64 *last_len, u64 *skip, | 835 | u64 *last_len, u64 *skip, u64 *defrag_end) |
816 | u64 *defrag_end) | ||
817 | { | 836 | { |
818 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 837 | struct extent_map *em; |
819 | struct extent_map *em = NULL; | ||
820 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | ||
821 | int ret = 1; | 838 | int ret = 1; |
839 | bool next_mergeable = true; | ||
822 | 840 | ||
823 | /* | 841 | /* |
824 | * make sure that once we start defragging an extent, we keep on | 842 | * make sure that once we start defragging an extent, we keep on |
@@ -829,23 +847,9 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
829 | 847 | ||
830 | *skip = 0; | 848 | *skip = 0; |
831 | 849 | ||
832 | /* | 850 | em = defrag_lookup_extent(inode, start); |
833 | * hopefully we have this extent in the tree already, try without | 851 | if (!em) |
834 | * the full extent lock | 852 | return 0; |
835 | */ | ||
836 | read_lock(&em_tree->lock); | ||
837 | em = lookup_extent_mapping(em_tree, start, len); | ||
838 | read_unlock(&em_tree->lock); | ||
839 | |||
840 | if (!em) { | ||
841 | /* get the big lock and read metadata off disk */ | ||
842 | lock_extent(io_tree, start, start + len - 1); | ||
843 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); | ||
844 | unlock_extent(io_tree, start, start + len - 1); | ||
845 | |||
846 | if (IS_ERR(em)) | ||
847 | return 0; | ||
848 | } | ||
849 | 853 | ||
850 | /* this will cover holes, and inline extents */ | 854 | /* this will cover holes, and inline extents */ |
851 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | 855 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { |
@@ -853,18 +857,15 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
853 | goto out; | 857 | goto out; |
854 | } | 858 | } |
855 | 859 | ||
856 | /* If we have nothing to merge with us, just skip. */ | 860 | next_mergeable = defrag_check_next_extent(inode, em); |
857 | if (check_adjacent_extents(inode, em)) { | ||
858 | ret = 0; | ||
859 | goto out; | ||
860 | } | ||
861 | 861 | ||
862 | /* | 862 | /* |
863 | * we hit a real extent, if it is big don't bother defragging it again | 863 | * we hit a real extent, if it is big or the next extent is not a |
864 | * real extent, don't bother defragging it | ||
864 | */ | 865 | */ |
865 | if ((*last_len == 0 || *last_len >= thresh) && em->len >= thresh) | 866 | if ((*last_len == 0 || *last_len >= thresh) && |
867 | (em->len >= thresh || !next_mergeable)) | ||
866 | ret = 0; | 868 | ret = 0; |
867 | |||
868 | out: | 869 | out: |
869 | /* | 870 | /* |
870 | * last_len ends up being a counter of how many bytes we've defragged. | 871 | * last_len ends up being a counter of how many bytes we've defragged. |
@@ -1143,8 +1144,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1143 | break; | 1144 | break; |
1144 | 1145 | ||
1145 | if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, | 1146 | if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, |
1146 | PAGE_CACHE_SIZE, extent_thresh, | 1147 | extent_thresh, &last_len, &skip, |
1147 | &last_len, &skip, &defrag_end)) { | 1148 | &defrag_end)) { |
1148 | unsigned long next; | 1149 | unsigned long next; |
1149 | /* | 1150 | /* |
1150 | * the should_defrag function tells us how much to skip | 1151 | * the should_defrag function tells us how much to skip |