aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Zefan <lizefan@huawei.com>2012-06-11 04:03:35 -0400
committerChris Mason <chris.mason@oracle.com>2012-06-14 21:30:55 -0400
commit6c282eb40ed6f64a51ff447707714df551d85b8e (patch)
tree97d8a780a577d21c0f237f2140f3a129f40096bf
parent7ddf5a42d311d74fd9f7373cb56def0843c219f8 (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>
-rw-r--r--fs/btrfs/ioctl.c97
1 files changed, 49 insertions, 48 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c5254dde1f0..a98f7d25282 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/* 789static 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 */
794static 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
817static 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
814static int should_defrag_range(struct inode *inode, u64 start, u64 len, 834static 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
868out: 869out:
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