diff options
-rw-r--r-- | fs/ext4/extents.c | 72 |
1 files changed, 58 insertions, 14 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index aabbb3f53683..e8755c21f4b9 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -1656,16 +1656,60 @@ static int ext4_ext_try_to_merge_right(struct inode *inode, | |||
1656 | } | 1656 | } |
1657 | 1657 | ||
1658 | /* | 1658 | /* |
1659 | * This function does a very simple check to see if we can collapse | ||
1660 | * an extent tree with a single extent tree leaf block into the inode. | ||
1661 | */ | ||
1662 | static void ext4_ext_try_to_merge_up(handle_t *handle, | ||
1663 | struct inode *inode, | ||
1664 | struct ext4_ext_path *path) | ||
1665 | { | ||
1666 | size_t s; | ||
1667 | unsigned max_root = ext4_ext_space_root(inode, 0); | ||
1668 | ext4_fsblk_t blk; | ||
1669 | |||
1670 | if ((path[0].p_depth != 1) || | ||
1671 | (le16_to_cpu(path[0].p_hdr->eh_entries) != 1) || | ||
1672 | (le16_to_cpu(path[1].p_hdr->eh_entries) > max_root)) | ||
1673 | return; | ||
1674 | |||
1675 | /* | ||
1676 | * We need to modify the block allocation bitmap and the block | ||
1677 | * group descriptor to release the extent tree block. If we | ||
1678 | * can't get the journal credits, give up. | ||
1679 | */ | ||
1680 | if (ext4_journal_extend(handle, 2)) | ||
1681 | return; | ||
1682 | |||
1683 | /* | ||
1684 | * Copy the extent data up to the inode | ||
1685 | */ | ||
1686 | blk = ext4_idx_pblock(path[0].p_idx); | ||
1687 | s = le16_to_cpu(path[1].p_hdr->eh_entries) * | ||
1688 | sizeof(struct ext4_extent_idx); | ||
1689 | s += sizeof(struct ext4_extent_header); | ||
1690 | |||
1691 | memcpy(path[0].p_hdr, path[1].p_hdr, s); | ||
1692 | path[0].p_depth = 0; | ||
1693 | path[0].p_ext = EXT_FIRST_EXTENT(path[0].p_hdr) + | ||
1694 | (path[1].p_ext - EXT_FIRST_EXTENT(path[1].p_hdr)); | ||
1695 | path[0].p_hdr->eh_max = cpu_to_le16(max_root); | ||
1696 | |||
1697 | brelse(path[1].p_bh); | ||
1698 | ext4_free_blocks(handle, inode, NULL, blk, 1, | ||
1699 | EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); | ||
1700 | } | ||
1701 | |||
1702 | /* | ||
1659 | * This function tries to merge the @ex extent to neighbours in the tree. | 1703 | * This function tries to merge the @ex extent to neighbours in the tree. |
1660 | * return 1 if merge left else 0. | 1704 | * return 1 if merge left else 0. |
1661 | */ | 1705 | */ |
1662 | static int ext4_ext_try_to_merge(struct inode *inode, | 1706 | static void ext4_ext_try_to_merge(handle_t *handle, |
1707 | struct inode *inode, | ||
1663 | struct ext4_ext_path *path, | 1708 | struct ext4_ext_path *path, |
1664 | struct ext4_extent *ex) { | 1709 | struct ext4_extent *ex) { |
1665 | struct ext4_extent_header *eh; | 1710 | struct ext4_extent_header *eh; |
1666 | unsigned int depth; | 1711 | unsigned int depth; |
1667 | int merge_done = 0; | 1712 | int merge_done = 0; |
1668 | int ret = 0; | ||
1669 | 1713 | ||
1670 | depth = ext_depth(inode); | 1714 | depth = ext_depth(inode); |
1671 | BUG_ON(path[depth].p_hdr == NULL); | 1715 | BUG_ON(path[depth].p_hdr == NULL); |
@@ -1675,9 +1719,9 @@ static int ext4_ext_try_to_merge(struct inode *inode, | |||
1675 | merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1); | 1719 | merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1); |
1676 | 1720 | ||
1677 | if (!merge_done) | 1721 | if (!merge_done) |
1678 | ret = ext4_ext_try_to_merge_right(inode, path, ex); | 1722 | (void) ext4_ext_try_to_merge_right(inode, path, ex); |
1679 | 1723 | ||
1680 | return ret; | 1724 | ext4_ext_try_to_merge_up(handle, inode, path); |
1681 | } | 1725 | } |
1682 | 1726 | ||
1683 | /* | 1727 | /* |
@@ -1893,7 +1937,7 @@ has_space: | |||
1893 | merge: | 1937 | merge: |
1894 | /* try to merge extents */ | 1938 | /* try to merge extents */ |
1895 | if (!(flag & EXT4_GET_BLOCKS_PRE_IO)) | 1939 | if (!(flag & EXT4_GET_BLOCKS_PRE_IO)) |
1896 | ext4_ext_try_to_merge(inode, path, nearex); | 1940 | ext4_ext_try_to_merge(handle, inode, path, nearex); |
1897 | 1941 | ||
1898 | 1942 | ||
1899 | /* time to correct all indexes above */ | 1943 | /* time to correct all indexes above */ |
@@ -1901,7 +1945,7 @@ merge: | |||
1901 | if (err) | 1945 | if (err) |
1902 | goto cleanup; | 1946 | goto cleanup; |
1903 | 1947 | ||
1904 | err = ext4_ext_dirty(handle, inode, path + depth); | 1948 | err = ext4_ext_dirty(handle, inode, path + path->p_depth); |
1905 | 1949 | ||
1906 | cleanup: | 1950 | cleanup: |
1907 | if (npath) { | 1951 | if (npath) { |
@@ -2924,9 +2968,9 @@ static int ext4_split_extent_at(handle_t *handle, | |||
2924 | ext4_ext_mark_initialized(ex); | 2968 | ext4_ext_mark_initialized(ex); |
2925 | 2969 | ||
2926 | if (!(flags & EXT4_GET_BLOCKS_PRE_IO)) | 2970 | if (!(flags & EXT4_GET_BLOCKS_PRE_IO)) |
2927 | ext4_ext_try_to_merge(inode, path, ex); | 2971 | ext4_ext_try_to_merge(handle, inode, path, ex); |
2928 | 2972 | ||
2929 | err = ext4_ext_dirty(handle, inode, path + depth); | 2973 | err = ext4_ext_dirty(handle, inode, path + path->p_depth); |
2930 | goto out; | 2974 | goto out; |
2931 | } | 2975 | } |
2932 | 2976 | ||
@@ -2958,8 +3002,8 @@ static int ext4_split_extent_at(handle_t *handle, | |||
2958 | goto fix_extent_len; | 3002 | goto fix_extent_len; |
2959 | /* update the extent length and mark as initialized */ | 3003 | /* update the extent length and mark as initialized */ |
2960 | ex->ee_len = cpu_to_le16(ee_len); | 3004 | ex->ee_len = cpu_to_le16(ee_len); |
2961 | ext4_ext_try_to_merge(inode, path, ex); | 3005 | ext4_ext_try_to_merge(handle, inode, path, ex); |
2962 | err = ext4_ext_dirty(handle, inode, path + depth); | 3006 | err = ext4_ext_dirty(handle, inode, path + path->p_depth); |
2963 | goto out; | 3007 | goto out; |
2964 | } else if (err) | 3008 | } else if (err) |
2965 | goto fix_extent_len; | 3009 | goto fix_extent_len; |
@@ -3191,8 +3235,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
3191 | if (err) | 3235 | if (err) |
3192 | goto out; | 3236 | goto out; |
3193 | ext4_ext_mark_initialized(ex); | 3237 | ext4_ext_mark_initialized(ex); |
3194 | ext4_ext_try_to_merge(inode, path, ex); | 3238 | ext4_ext_try_to_merge(handle, inode, path, ex); |
3195 | err = ext4_ext_dirty(handle, inode, path + depth); | 3239 | err = ext4_ext_dirty(handle, inode, path + path->p_depth); |
3196 | goto out; | 3240 | goto out; |
3197 | } | 3241 | } |
3198 | 3242 | ||
@@ -3333,10 +3377,10 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle, | |||
3333 | /* note: ext4_ext_correct_indexes() isn't needed here because | 3377 | /* note: ext4_ext_correct_indexes() isn't needed here because |
3334 | * borders are not changed | 3378 | * borders are not changed |
3335 | */ | 3379 | */ |
3336 | ext4_ext_try_to_merge(inode, path, ex); | 3380 | ext4_ext_try_to_merge(handle, inode, path, ex); |
3337 | 3381 | ||
3338 | /* Mark modified extent as dirty */ | 3382 | /* Mark modified extent as dirty */ |
3339 | err = ext4_ext_dirty(handle, inode, path + depth); | 3383 | err = ext4_ext_dirty(handle, inode, path + path->p_depth); |
3340 | out: | 3384 | out: |
3341 | ext4_ext_show_leaf(inode, path); | 3385 | ext4_ext_show_leaf(inode, path); |
3342 | return err; | 3386 | return err; |