diff options
-rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
-rw-r--r-- | fs/ext4/extents.c | 28 | ||||
-rw-r--r-- | fs/ext4/move_extent.c | 2 |
3 files changed, 21 insertions, 12 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 550b4f99a843..696e51ae02fa 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -582,6 +582,7 @@ enum { | |||
582 | */ | 582 | */ |
583 | #define EXT4_EX_NOCACHE 0x0800 | 583 | #define EXT4_EX_NOCACHE 0x0800 |
584 | #define EXT4_EX_FORCE_CACHE 0x1000 | 584 | #define EXT4_EX_FORCE_CACHE 0x1000 |
585 | #define EXT4_EX_NOFREE_ON_ERR 0x2000 | ||
585 | 586 | ||
586 | /* | 587 | /* |
587 | * Flags used by ext4_free_blocks | 588 | * Flags used by ext4_free_blocks |
@@ -2733,7 +2734,7 @@ extern int ext4_ext_insert_extent(handle_t *, struct inode *, | |||
2733 | struct ext4_ext_path *, | 2734 | struct ext4_ext_path *, |
2734 | struct ext4_extent *, int); | 2735 | struct ext4_extent *, int); |
2735 | extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t, | 2736 | extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t, |
2736 | struct ext4_ext_path *, | 2737 | struct ext4_ext_path **, |
2737 | int flags); | 2738 | int flags); |
2738 | extern void ext4_ext_drop_refs(struct ext4_ext_path *); | 2739 | extern void ext4_ext_drop_refs(struct ext4_ext_path *); |
2739 | extern int ext4_ext_check_inode(struct inode *inode); | 2740 | extern int ext4_ext_check_inode(struct inode *inode); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index bf205f72be35..0ced78c974e2 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -855,11 +855,13 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode) | |||
855 | 855 | ||
856 | struct ext4_ext_path * | 856 | struct ext4_ext_path * |
857 | ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | 857 | ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, |
858 | struct ext4_ext_path *path, int flags) | 858 | struct ext4_ext_path **orig_path, int flags) |
859 | { | 859 | { |
860 | struct ext4_extent_header *eh; | 860 | struct ext4_extent_header *eh; |
861 | struct buffer_head *bh; | 861 | struct buffer_head *bh; |
862 | short int depth, i, ppos = 0, alloc = 0; | 862 | struct ext4_ext_path *path = orig_path ? *orig_path : NULL; |
863 | short int depth, i, ppos = 0; | ||
864 | short free_on_err = (flags & EXT4_EX_NOFREE_ON_ERR) == 0; | ||
863 | int ret; | 865 | int ret; |
864 | 866 | ||
865 | eh = ext_inode_hdr(inode); | 867 | eh = ext_inode_hdr(inode); |
@@ -871,7 +873,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
871 | GFP_NOFS); | 873 | GFP_NOFS); |
872 | if (unlikely(!path)) | 874 | if (unlikely(!path)) |
873 | return ERR_PTR(-ENOMEM); | 875 | return ERR_PTR(-ENOMEM); |
874 | alloc = 1; | 876 | free_on_err = 1; |
875 | } | 877 | } |
876 | path[0].p_hdr = eh; | 878 | path[0].p_hdr = eh; |
877 | path[0].p_bh = NULL; | 879 | path[0].p_bh = NULL; |
@@ -923,8 +925,11 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
923 | 925 | ||
924 | err: | 926 | err: |
925 | ext4_ext_drop_refs(path); | 927 | ext4_ext_drop_refs(path); |
926 | if (alloc) | 928 | if (free_on_err) { |
927 | kfree(path); | 929 | kfree(path); |
930 | if (orig_path) | ||
931 | *orig_path = NULL; | ||
932 | } | ||
928 | return ERR_PTR(ret); | 933 | return ERR_PTR(ret); |
929 | } | 934 | } |
930 | 935 | ||
@@ -1356,7 +1361,7 @@ repeat: | |||
1356 | ext4_ext_drop_refs(path); | 1361 | ext4_ext_drop_refs(path); |
1357 | path = ext4_ext_find_extent(inode, | 1362 | path = ext4_ext_find_extent(inode, |
1358 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), | 1363 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), |
1359 | path, gb_flags); | 1364 | &path, gb_flags | EXT4_EX_NOFREE_ON_ERR); |
1360 | if (IS_ERR(path)) | 1365 | if (IS_ERR(path)) |
1361 | err = PTR_ERR(path); | 1366 | err = PTR_ERR(path); |
1362 | } else { | 1367 | } else { |
@@ -1369,7 +1374,7 @@ repeat: | |||
1369 | ext4_ext_drop_refs(path); | 1374 | ext4_ext_drop_refs(path); |
1370 | path = ext4_ext_find_extent(inode, | 1375 | path = ext4_ext_find_extent(inode, |
1371 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), | 1376 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), |
1372 | path, gb_flags); | 1377 | &path, gb_flags | EXT4_EX_NOFREE_ON_ERR); |
1373 | if (IS_ERR(path)) { | 1378 | if (IS_ERR(path)) { |
1374 | err = PTR_ERR(path); | 1379 | err = PTR_ERR(path); |
1375 | goto out; | 1380 | goto out; |
@@ -2152,7 +2157,7 @@ static int ext4_fill_fiemap_extents(struct inode *inode, | |||
2152 | path = NULL; | 2157 | path = NULL; |
2153 | } | 2158 | } |
2154 | 2159 | ||
2155 | path = ext4_ext_find_extent(inode, block, path, 0); | 2160 | path = ext4_ext_find_extent(inode, block, &path, 0); |
2156 | if (IS_ERR(path)) { | 2161 | if (IS_ERR(path)) { |
2157 | up_read(&EXT4_I(inode)->i_data_sem); | 2162 | up_read(&EXT4_I(inode)->i_data_sem); |
2158 | err = PTR_ERR(path); | 2163 | err = PTR_ERR(path); |
@@ -3313,7 +3318,8 @@ static int ext4_split_extent(handle_t *handle, | |||
3313 | * result in split of original leaf or extent zeroout. | 3318 | * result in split of original leaf or extent zeroout. |
3314 | */ | 3319 | */ |
3315 | ext4_ext_drop_refs(path); | 3320 | ext4_ext_drop_refs(path); |
3316 | path = ext4_ext_find_extent(inode, map->m_lblk, path, 0); | 3321 | path = ext4_ext_find_extent(inode, map->m_lblk, &path, |
3322 | EXT4_EX_NOFREE_ON_ERR); | ||
3317 | if (IS_ERR(path)) | 3323 | if (IS_ERR(path)) |
3318 | return PTR_ERR(path); | 3324 | return PTR_ERR(path); |
3319 | depth = ext_depth(inode); | 3325 | depth = ext_depth(inode); |
@@ -3697,7 +3703,8 @@ static int ext4_convert_initialized_extents(handle_t *handle, | |||
3697 | if (err < 0) | 3703 | if (err < 0) |
3698 | goto out; | 3704 | goto out; |
3699 | ext4_ext_drop_refs(path); | 3705 | ext4_ext_drop_refs(path); |
3700 | path = ext4_ext_find_extent(inode, map->m_lblk, path, 0); | 3706 | path = ext4_ext_find_extent(inode, map->m_lblk, &path, |
3707 | EXT4_EX_NOFREE_ON_ERR); | ||
3701 | if (IS_ERR(path)) { | 3708 | if (IS_ERR(path)) { |
3702 | err = PTR_ERR(path); | 3709 | err = PTR_ERR(path); |
3703 | goto out; | 3710 | goto out; |
@@ -3769,7 +3776,8 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle, | |||
3769 | if (err < 0) | 3776 | if (err < 0) |
3770 | goto out; | 3777 | goto out; |
3771 | ext4_ext_drop_refs(path); | 3778 | ext4_ext_drop_refs(path); |
3772 | path = ext4_ext_find_extent(inode, map->m_lblk, path, 0); | 3779 | path = ext4_ext_find_extent(inode, map->m_lblk, &path, |
3780 | EXT4_EX_NOFREE_ON_ERR); | ||
3773 | if (IS_ERR(path)) { | 3781 | if (IS_ERR(path)) { |
3774 | err = PTR_ERR(path); | 3782 | err = PTR_ERR(path); |
3775 | goto out; | 3783 | goto out; |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index c8f895b410f6..5e2465a8e4ce 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -37,7 +37,7 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock, | |||
37 | int ret = 0; | 37 | int ret = 0; |
38 | struct ext4_ext_path *path; | 38 | struct ext4_ext_path *path; |
39 | 39 | ||
40 | path = ext4_ext_find_extent(inode, lblock, *orig_path, EXT4_EX_NOCACHE); | 40 | path = ext4_ext_find_extent(inode, lblock, orig_path, EXT4_EX_NOCACHE); |
41 | if (IS_ERR(path)) | 41 | if (IS_ERR(path)) |
42 | ret = PTR_ERR(path); | 42 | ret = PTR_ERR(path); |
43 | else if (path[ext_depth(inode)].p_ext == NULL) | 43 | else if (path[ext_depth(inode)].p_ext == NULL) |