diff options
author | Liu Bo <liubo2009@cn.fujitsu.com> | 2012-03-29 09:57:45 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-03-29 09:57:45 -0400 |
commit | 17ce6ef8d731af5edac8c39e806db4c7e1f6956f (patch) | |
tree | 4a54d3c5618efff3deec03fa5d32a42c0a8fc804 | |
parent | 4cb13e5d6ecc47b91b24a35f8fbc2c9f33d075fe (diff) |
Btrfs: add a check to decide if we should defrag the range
If our file's layout is as follows:
| hole | data1 | hole | data2 |
we do not need to defrag this file, because this file has holes and
cannot be merged into one extent.
Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ioctl.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index de46fa218590..6c39d1a55907 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -784,6 +784,31 @@ none: | |||
784 | return -ENOENT; | 784 | return -ENOENT; |
785 | } | 785 | } |
786 | 786 | ||
787 | /* | ||
788 | * Validaty check of prev em and next em: | ||
789 | * 1) no prev/next em | ||
790 | * 2) prev/next em is an hole/inline extent | ||
791 | */ | ||
792 | static int check_adjacent_extents(struct inode *inode, struct extent_map *em) | ||
793 | { | ||
794 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | ||
795 | struct extent_map *prev = NULL, *next = NULL; | ||
796 | int ret = 0; | ||
797 | |||
798 | read_lock(&em_tree->lock); | ||
799 | prev = lookup_extent_mapping(em_tree, em->start - 1, (u64)-1); | ||
800 | next = lookup_extent_mapping(em_tree, em->start + em->len, (u64)-1); | ||
801 | read_unlock(&em_tree->lock); | ||
802 | |||
803 | if ((!prev || prev->block_start >= EXTENT_MAP_LAST_BYTE) && | ||
804 | (!next || next->block_start >= EXTENT_MAP_LAST_BYTE)) | ||
805 | ret = 1; | ||
806 | free_extent_map(prev); | ||
807 | free_extent_map(next); | ||
808 | |||
809 | return ret; | ||
810 | } | ||
811 | |||
787 | static int should_defrag_range(struct inode *inode, u64 start, u64 len, | 812 | static int should_defrag_range(struct inode *inode, u64 start, u64 len, |
788 | int thresh, u64 *last_len, u64 *skip, | 813 | int thresh, u64 *last_len, u64 *skip, |
789 | u64 *defrag_end) | 814 | u64 *defrag_end) |
@@ -821,8 +846,16 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
821 | } | 846 | } |
822 | 847 | ||
823 | /* this will cover holes, and inline extents */ | 848 | /* this will cover holes, and inline extents */ |
824 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) | 849 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { |
850 | ret = 0; | ||
851 | goto out; | ||
852 | } | ||
853 | |||
854 | /* If we have nothing to merge with us, just skip. */ | ||
855 | if (check_adjacent_extents(inode, em)) { | ||
825 | ret = 0; | 856 | ret = 0; |
857 | goto out; | ||
858 | } | ||
826 | 859 | ||
827 | /* | 860 | /* |
828 | * we hit a real extent, if it is big don't bother defragging it again | 861 | * we hit a real extent, if it is big don't bother defragging it again |
@@ -830,6 +863,7 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
830 | if ((*last_len == 0 || *last_len >= thresh) && em->len >= thresh) | 863 | if ((*last_len == 0 || *last_len >= thresh) && em->len >= thresh) |
831 | ret = 0; | 864 | ret = 0; |
832 | 865 | ||
866 | out: | ||
833 | /* | 867 | /* |
834 | * last_len ends up being a counter of how many bytes we've defragged. | 868 | * last_len ends up being a counter of how many bytes we've defragged. |
835 | * every time we choose not to defrag an extent, we reset *last_len | 869 | * every time we choose not to defrag an extent, we reset *last_len |