diff options
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 87 |
1 files changed, 60 insertions, 27 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 6e7b7d928f4a..08c1ac976479 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -466,7 +466,8 @@ int ext4_ext_check_inode(struct inode *inode) | |||
466 | 466 | ||
467 | static struct buffer_head * | 467 | static struct buffer_head * |
468 | __read_extent_tree_block(const char *function, unsigned int line, | 468 | __read_extent_tree_block(const char *function, unsigned int line, |
469 | struct inode *inode, ext4_fsblk_t pblk, int depth) | 469 | struct inode *inode, ext4_fsblk_t pblk, int depth, |
470 | int flags) | ||
470 | { | 471 | { |
471 | struct buffer_head *bh; | 472 | struct buffer_head *bh; |
472 | int err; | 473 | int err; |
@@ -488,6 +489,32 @@ __read_extent_tree_block(const char *function, unsigned int line, | |||
488 | if (err) | 489 | if (err) |
489 | goto errout; | 490 | goto errout; |
490 | set_buffer_verified(bh); | 491 | set_buffer_verified(bh); |
492 | /* | ||
493 | * If this is a leaf block, cache all of its entries | ||
494 | */ | ||
495 | if (!(flags & EXT4_EX_NOCACHE) && depth == 0) { | ||
496 | struct ext4_extent_header *eh = ext_block_hdr(bh); | ||
497 | struct ext4_extent *ex = EXT_FIRST_EXTENT(eh); | ||
498 | ext4_lblk_t prev = 0; | ||
499 | int i; | ||
500 | |||
501 | for (i = le16_to_cpu(eh->eh_entries); i > 0; i--, ex++) { | ||
502 | unsigned int status = EXTENT_STATUS_WRITTEN; | ||
503 | ext4_lblk_t lblk = le32_to_cpu(ex->ee_block); | ||
504 | int len = ext4_ext_get_actual_len(ex); | ||
505 | |||
506 | if (prev && (prev != lblk)) | ||
507 | ext4_es_cache_extent(inode, prev, | ||
508 | lblk - prev, ~0, | ||
509 | EXTENT_STATUS_HOLE); | ||
510 | |||
511 | if (ext4_ext_is_uninitialized(ex)) | ||
512 | status = EXTENT_STATUS_UNWRITTEN; | ||
513 | ext4_es_cache_extent(inode, lblk, len, | ||
514 | ext4_ext_pblock(ex), status); | ||
515 | prev = lblk + len; | ||
516 | } | ||
517 | } | ||
491 | return bh; | 518 | return bh; |
492 | errout: | 519 | errout: |
493 | put_bh(bh); | 520 | put_bh(bh); |
@@ -495,8 +522,9 @@ errout: | |||
495 | 522 | ||
496 | } | 523 | } |
497 | 524 | ||
498 | #define read_extent_tree_block(inode, pblk, depth) \ | 525 | #define read_extent_tree_block(inode, pblk, depth, flags) \ |
499 | __read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth)) | 526 | __read_extent_tree_block(__func__, __LINE__, (inode), (pblk), \ |
527 | (depth), (flags)) | ||
500 | 528 | ||
501 | #ifdef EXT_DEBUG | 529 | #ifdef EXT_DEBUG |
502 | static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) | 530 | static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) |
@@ -730,7 +758,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode) | |||
730 | 758 | ||
731 | struct ext4_ext_path * | 759 | struct ext4_ext_path * |
732 | ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | 760 | ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, |
733 | struct ext4_ext_path *path) | 761 | struct ext4_ext_path *path, int flags) |
734 | { | 762 | { |
735 | struct ext4_extent_header *eh; | 763 | struct ext4_extent_header *eh; |
736 | struct buffer_head *bh; | 764 | struct buffer_head *bh; |
@@ -762,7 +790,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
762 | path[ppos].p_depth = i; | 790 | path[ppos].p_depth = i; |
763 | path[ppos].p_ext = NULL; | 791 | path[ppos].p_ext = NULL; |
764 | 792 | ||
765 | bh = read_extent_tree_block(inode, path[ppos].p_block, --i); | 793 | bh = read_extent_tree_block(inode, path[ppos].p_block, --i, |
794 | flags); | ||
766 | if (IS_ERR(bh)) { | 795 | if (IS_ERR(bh)) { |
767 | ret = PTR_ERR(bh); | 796 | ret = PTR_ERR(bh); |
768 | goto err; | 797 | goto err; |
@@ -1199,7 +1228,8 @@ out: | |||
1199 | * if no free index is found, then it requests in-depth growing. | 1228 | * if no free index is found, then it requests in-depth growing. |
1200 | */ | 1229 | */ |
1201 | static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode, | 1230 | static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode, |
1202 | unsigned int flags, | 1231 | unsigned int mb_flags, |
1232 | unsigned int gb_flags, | ||
1203 | struct ext4_ext_path *path, | 1233 | struct ext4_ext_path *path, |
1204 | struct ext4_extent *newext) | 1234 | struct ext4_extent *newext) |
1205 | { | 1235 | { |
@@ -1221,7 +1251,7 @@ repeat: | |||
1221 | if (EXT_HAS_FREE_INDEX(curp)) { | 1251 | if (EXT_HAS_FREE_INDEX(curp)) { |
1222 | /* if we found index with free entry, then use that | 1252 | /* if we found index with free entry, then use that |
1223 | * entry: create all needed subtree and add new leaf */ | 1253 | * entry: create all needed subtree and add new leaf */ |
1224 | err = ext4_ext_split(handle, inode, flags, path, newext, i); | 1254 | err = ext4_ext_split(handle, inode, mb_flags, path, newext, i); |
1225 | if (err) | 1255 | if (err) |
1226 | goto out; | 1256 | goto out; |
1227 | 1257 | ||
@@ -1229,12 +1259,12 @@ repeat: | |||
1229 | ext4_ext_drop_refs(path); | 1259 | ext4_ext_drop_refs(path); |
1230 | path = ext4_ext_find_extent(inode, | 1260 | path = ext4_ext_find_extent(inode, |
1231 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), | 1261 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), |
1232 | path); | 1262 | path, gb_flags); |
1233 | if (IS_ERR(path)) | 1263 | if (IS_ERR(path)) |
1234 | err = PTR_ERR(path); | 1264 | err = PTR_ERR(path); |
1235 | } else { | 1265 | } else { |
1236 | /* tree is full, time to grow in depth */ | 1266 | /* tree is full, time to grow in depth */ |
1237 | err = ext4_ext_grow_indepth(handle, inode, flags, newext); | 1267 | err = ext4_ext_grow_indepth(handle, inode, mb_flags, newext); |
1238 | if (err) | 1268 | if (err) |
1239 | goto out; | 1269 | goto out; |
1240 | 1270 | ||
@@ -1242,7 +1272,7 @@ repeat: | |||
1242 | ext4_ext_drop_refs(path); | 1272 | ext4_ext_drop_refs(path); |
1243 | path = ext4_ext_find_extent(inode, | 1273 | path = ext4_ext_find_extent(inode, |
1244 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), | 1274 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), |
1245 | path); | 1275 | path, gb_flags); |
1246 | if (IS_ERR(path)) { | 1276 | if (IS_ERR(path)) { |
1247 | err = PTR_ERR(path); | 1277 | err = PTR_ERR(path); |
1248 | goto out; | 1278 | goto out; |
@@ -1415,7 +1445,7 @@ got_index: | |||
1415 | while (++depth < path->p_depth) { | 1445 | while (++depth < path->p_depth) { |
1416 | /* subtract from p_depth to get proper eh_depth */ | 1446 | /* subtract from p_depth to get proper eh_depth */ |
1417 | bh = read_extent_tree_block(inode, block, | 1447 | bh = read_extent_tree_block(inode, block, |
1418 | path->p_depth - depth); | 1448 | path->p_depth - depth, 0); |
1419 | if (IS_ERR(bh)) | 1449 | if (IS_ERR(bh)) |
1420 | return PTR_ERR(bh); | 1450 | return PTR_ERR(bh); |
1421 | eh = ext_block_hdr(bh); | 1451 | eh = ext_block_hdr(bh); |
@@ -1424,7 +1454,7 @@ got_index: | |||
1424 | put_bh(bh); | 1454 | put_bh(bh); |
1425 | } | 1455 | } |
1426 | 1456 | ||
1427 | bh = read_extent_tree_block(inode, block, path->p_depth - depth); | 1457 | bh = read_extent_tree_block(inode, block, path->p_depth - depth, 0); |
1428 | if (IS_ERR(bh)) | 1458 | if (IS_ERR(bh)) |
1429 | return PTR_ERR(bh); | 1459 | return PTR_ERR(bh); |
1430 | eh = ext_block_hdr(bh); | 1460 | eh = ext_block_hdr(bh); |
@@ -1786,7 +1816,7 @@ out: | |||
1786 | */ | 1816 | */ |
1787 | int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | 1817 | int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, |
1788 | struct ext4_ext_path *path, | 1818 | struct ext4_ext_path *path, |
1789 | struct ext4_extent *newext, int flag) | 1819 | struct ext4_extent *newext, int gb_flags) |
1790 | { | 1820 | { |
1791 | struct ext4_extent_header *eh; | 1821 | struct ext4_extent_header *eh; |
1792 | struct ext4_extent *ex, *fex; | 1822 | struct ext4_extent *ex, *fex; |
@@ -1795,7 +1825,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | |||
1795 | int depth, len, err; | 1825 | int depth, len, err; |
1796 | ext4_lblk_t next; | 1826 | ext4_lblk_t next; |
1797 | unsigned uninitialized = 0; | 1827 | unsigned uninitialized = 0; |
1798 | int flags = 0; | 1828 | int mb_flags = 0; |
1799 | 1829 | ||
1800 | if (unlikely(ext4_ext_get_actual_len(newext) == 0)) { | 1830 | if (unlikely(ext4_ext_get_actual_len(newext) == 0)) { |
1801 | EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0"); | 1831 | EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0"); |
@@ -1810,7 +1840,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | |||
1810 | } | 1840 | } |
1811 | 1841 | ||
1812 | /* try to insert block into found extent and return */ | 1842 | /* try to insert block into found extent and return */ |
1813 | if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)) { | 1843 | if (ex && !(gb_flags & EXT4_GET_BLOCKS_PRE_IO)) { |
1814 | 1844 | ||
1815 | /* | 1845 | /* |
1816 | * Try to see whether we should rather test the extent on | 1846 | * Try to see whether we should rather test the extent on |
@@ -1913,7 +1943,7 @@ prepend: | |||
1913 | if (next != EXT_MAX_BLOCKS) { | 1943 | if (next != EXT_MAX_BLOCKS) { |
1914 | ext_debug("next leaf block - %u\n", next); | 1944 | ext_debug("next leaf block - %u\n", next); |
1915 | BUG_ON(npath != NULL); | 1945 | BUG_ON(npath != NULL); |
1916 | npath = ext4_ext_find_extent(inode, next, NULL); | 1946 | npath = ext4_ext_find_extent(inode, next, NULL, 0); |
1917 | if (IS_ERR(npath)) | 1947 | if (IS_ERR(npath)) |
1918 | return PTR_ERR(npath); | 1948 | return PTR_ERR(npath); |
1919 | BUG_ON(npath->p_depth != path->p_depth); | 1949 | BUG_ON(npath->p_depth != path->p_depth); |
@@ -1932,9 +1962,10 @@ prepend: | |||
1932 | * There is no free space in the found leaf. | 1962 | * There is no free space in the found leaf. |
1933 | * We're gonna add a new leaf in the tree. | 1963 | * We're gonna add a new leaf in the tree. |
1934 | */ | 1964 | */ |
1935 | if (flag & EXT4_GET_BLOCKS_METADATA_NOFAIL) | 1965 | if (gb_flags & EXT4_GET_BLOCKS_METADATA_NOFAIL) |
1936 | flags = EXT4_MB_USE_RESERVED; | 1966 | mb_flags = EXT4_MB_USE_RESERVED; |
1937 | err = ext4_ext_create_new_leaf(handle, inode, flags, path, newext); | 1967 | err = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags, |
1968 | path, newext); | ||
1938 | if (err) | 1969 | if (err) |
1939 | goto cleanup; | 1970 | goto cleanup; |
1940 | depth = ext_depth(inode); | 1971 | depth = ext_depth(inode); |
@@ -2000,7 +2031,7 @@ has_space: | |||
2000 | 2031 | ||
2001 | merge: | 2032 | merge: |
2002 | /* try to merge extents */ | 2033 | /* try to merge extents */ |
2003 | if (!(flag & EXT4_GET_BLOCKS_PRE_IO)) | 2034 | if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO)) |
2004 | ext4_ext_try_to_merge(handle, inode, path, nearex); | 2035 | ext4_ext_try_to_merge(handle, inode, path, nearex); |
2005 | 2036 | ||
2006 | 2037 | ||
@@ -2043,7 +2074,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode, | |||
2043 | path = NULL; | 2074 | path = NULL; |
2044 | } | 2075 | } |
2045 | 2076 | ||
2046 | path = ext4_ext_find_extent(inode, block, path); | 2077 | path = ext4_ext_find_extent(inode, block, path, 0); |
2047 | if (IS_ERR(path)) { | 2078 | if (IS_ERR(path)) { |
2048 | up_read(&EXT4_I(inode)->i_data_sem); | 2079 | up_read(&EXT4_I(inode)->i_data_sem); |
2049 | err = PTR_ERR(path); | 2080 | err = PTR_ERR(path); |
@@ -2705,7 +2736,7 @@ again: | |||
2705 | ext4_lblk_t ee_block; | 2736 | ext4_lblk_t ee_block; |
2706 | 2737 | ||
2707 | /* find extent for this block */ | 2738 | /* find extent for this block */ |
2708 | path = ext4_ext_find_extent(inode, end, NULL); | 2739 | path = ext4_ext_find_extent(inode, end, NULL, EXT4_EX_NOCACHE); |
2709 | if (IS_ERR(path)) { | 2740 | if (IS_ERR(path)) { |
2710 | ext4_journal_stop(handle); | 2741 | ext4_journal_stop(handle); |
2711 | return PTR_ERR(path); | 2742 | return PTR_ERR(path); |
@@ -2747,6 +2778,7 @@ again: | |||
2747 | */ | 2778 | */ |
2748 | err = ext4_split_extent_at(handle, inode, path, | 2779 | err = ext4_split_extent_at(handle, inode, path, |
2749 | end + 1, split_flag, | 2780 | end + 1, split_flag, |
2781 | EXT4_EX_NOCACHE | | ||
2750 | EXT4_GET_BLOCKS_PRE_IO | | 2782 | EXT4_GET_BLOCKS_PRE_IO | |
2751 | EXT4_GET_BLOCKS_METADATA_NOFAIL); | 2783 | EXT4_GET_BLOCKS_METADATA_NOFAIL); |
2752 | 2784 | ||
@@ -2823,7 +2855,8 @@ again: | |||
2823 | i + 1, ext4_idx_pblock(path[i].p_idx)); | 2855 | i + 1, ext4_idx_pblock(path[i].p_idx)); |
2824 | memset(path + i + 1, 0, sizeof(*path)); | 2856 | memset(path + i + 1, 0, sizeof(*path)); |
2825 | bh = read_extent_tree_block(inode, | 2857 | bh = read_extent_tree_block(inode, |
2826 | ext4_idx_pblock(path[i].p_idx), depth - i - 1); | 2858 | ext4_idx_pblock(path[i].p_idx), depth - i - 1, |
2859 | EXT4_EX_NOCACHE); | ||
2827 | if (IS_ERR(bh)) { | 2860 | if (IS_ERR(bh)) { |
2828 | /* should we reset i_size? */ | 2861 | /* should we reset i_size? */ |
2829 | err = PTR_ERR(bh); | 2862 | err = PTR_ERR(bh); |
@@ -3170,7 +3203,7 @@ static int ext4_split_extent(handle_t *handle, | |||
3170 | * result in split of original leaf or extent zeroout. | 3203 | * result in split of original leaf or extent zeroout. |
3171 | */ | 3204 | */ |
3172 | ext4_ext_drop_refs(path); | 3205 | ext4_ext_drop_refs(path); |
3173 | path = ext4_ext_find_extent(inode, map->m_lblk, path); | 3206 | path = ext4_ext_find_extent(inode, map->m_lblk, path, 0); |
3174 | if (IS_ERR(path)) | 3207 | if (IS_ERR(path)) |
3175 | return PTR_ERR(path); | 3208 | return PTR_ERR(path); |
3176 | depth = ext_depth(inode); | 3209 | depth = ext_depth(inode); |
@@ -3554,7 +3587,7 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle, | |||
3554 | if (err < 0) | 3587 | if (err < 0) |
3555 | goto out; | 3588 | goto out; |
3556 | ext4_ext_drop_refs(path); | 3589 | ext4_ext_drop_refs(path); |
3557 | path = ext4_ext_find_extent(inode, map->m_lblk, path); | 3590 | path = ext4_ext_find_extent(inode, map->m_lblk, path, 0); |
3558 | if (IS_ERR(path)) { | 3591 | if (IS_ERR(path)) { |
3559 | err = PTR_ERR(path); | 3592 | err = PTR_ERR(path); |
3560 | goto out; | 3593 | goto out; |
@@ -4041,7 +4074,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | |||
4041 | trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); | 4074 | trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); |
4042 | 4075 | ||
4043 | /* find extent for this block */ | 4076 | /* find extent for this block */ |
4044 | path = ext4_ext_find_extent(inode, map->m_lblk, NULL); | 4077 | path = ext4_ext_find_extent(inode, map->m_lblk, NULL, 0); |
4045 | if (IS_ERR(path)) { | 4078 | if (IS_ERR(path)) { |
4046 | err = PTR_ERR(path); | 4079 | err = PTR_ERR(path); |
4047 | path = NULL; | 4080 | path = NULL; |
@@ -4760,6 +4793,6 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
4760 | error = ext4_fill_fiemap_extents(inode, start_blk, | 4793 | error = ext4_fill_fiemap_extents(inode, start_blk, |
4761 | len_blks, fieinfo); | 4794 | len_blks, fieinfo); |
4762 | } | 4795 | } |
4763 | 4796 | ext4_es_lru_add(inode); | |
4764 | return error; | 4797 | return error; |
4765 | } | 4798 | } |