diff options
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 715264b4bae4..3a7928f825e4 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -1007,7 +1007,8 @@ cleanup: | |||
1007 | for (i = 0; i < depth; i++) { | 1007 | for (i = 0; i < depth; i++) { |
1008 | if (!ablocks[i]) | 1008 | if (!ablocks[i]) |
1009 | continue; | 1009 | continue; |
1010 | ext4_free_blocks(handle, inode, ablocks[i], 1, 1); | 1010 | ext4_free_blocks(handle, inode, 0, ablocks[i], 1, |
1011 | EXT4_FREE_BLOCKS_METADATA); | ||
1011 | } | 1012 | } |
1012 | } | 1013 | } |
1013 | kfree(ablocks); | 1014 | kfree(ablocks); |
@@ -1761,7 +1762,9 @@ int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, | |||
1761 | while (block < last && block != EXT_MAX_BLOCK) { | 1762 | while (block < last && block != EXT_MAX_BLOCK) { |
1762 | num = last - block; | 1763 | num = last - block; |
1763 | /* find extent for this block */ | 1764 | /* find extent for this block */ |
1765 | down_read(&EXT4_I(inode)->i_data_sem); | ||
1764 | path = ext4_ext_find_extent(inode, block, path); | 1766 | path = ext4_ext_find_extent(inode, block, path); |
1767 | up_read(&EXT4_I(inode)->i_data_sem); | ||
1765 | if (IS_ERR(path)) { | 1768 | if (IS_ERR(path)) { |
1766 | err = PTR_ERR(path); | 1769 | err = PTR_ERR(path); |
1767 | path = NULL; | 1770 | path = NULL; |
@@ -1957,7 +1960,6 @@ errout: | |||
1957 | static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | 1960 | static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, |
1958 | struct ext4_ext_path *path) | 1961 | struct ext4_ext_path *path) |
1959 | { | 1962 | { |
1960 | struct buffer_head *bh; | ||
1961 | int err; | 1963 | int err; |
1962 | ext4_fsblk_t leaf; | 1964 | ext4_fsblk_t leaf; |
1963 | 1965 | ||
@@ -1973,9 +1975,8 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | |||
1973 | if (err) | 1975 | if (err) |
1974 | return err; | 1976 | return err; |
1975 | ext_debug("index is empty, remove it, free block %llu\n", leaf); | 1977 | ext_debug("index is empty, remove it, free block %llu\n", leaf); |
1976 | bh = sb_find_get_block(inode->i_sb, leaf); | 1978 | ext4_free_blocks(handle, inode, 0, leaf, 1, |
1977 | ext4_forget(handle, 1, inode, bh, leaf); | 1979 | EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); |
1978 | ext4_free_blocks(handle, inode, leaf, 1, 1); | ||
1979 | return err; | 1980 | return err; |
1980 | } | 1981 | } |
1981 | 1982 | ||
@@ -2042,12 +2043,11 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
2042 | struct ext4_extent *ex, | 2043 | struct ext4_extent *ex, |
2043 | ext4_lblk_t from, ext4_lblk_t to) | 2044 | ext4_lblk_t from, ext4_lblk_t to) |
2044 | { | 2045 | { |
2045 | struct buffer_head *bh; | ||
2046 | unsigned short ee_len = ext4_ext_get_actual_len(ex); | 2046 | unsigned short ee_len = ext4_ext_get_actual_len(ex); |
2047 | int i, metadata = 0; | 2047 | int flags = EXT4_FREE_BLOCKS_FORGET; |
2048 | 2048 | ||
2049 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | 2049 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
2050 | metadata = 1; | 2050 | flags |= EXT4_FREE_BLOCKS_METADATA; |
2051 | #ifdef EXTENTS_STATS | 2051 | #ifdef EXTENTS_STATS |
2052 | { | 2052 | { |
2053 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 2053 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
@@ -2072,11 +2072,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
2072 | num = le32_to_cpu(ex->ee_block) + ee_len - from; | 2072 | num = le32_to_cpu(ex->ee_block) + ee_len - from; |
2073 | start = ext_pblock(ex) + ee_len - num; | 2073 | start = ext_pblock(ex) + ee_len - num; |
2074 | ext_debug("free last %u blocks starting %llu\n", num, start); | 2074 | ext_debug("free last %u blocks starting %llu\n", num, start); |
2075 | for (i = 0; i < num; i++) { | 2075 | ext4_free_blocks(handle, inode, 0, start, num, flags); |
2076 | bh = sb_find_get_block(inode->i_sb, start + i); | ||
2077 | ext4_forget(handle, 0, inode, bh, start + i); | ||
2078 | } | ||
2079 | ext4_free_blocks(handle, inode, start, num, metadata); | ||
2080 | } else if (from == le32_to_cpu(ex->ee_block) | 2076 | } else if (from == le32_to_cpu(ex->ee_block) |
2081 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { | 2077 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { |
2082 | printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", | 2078 | printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", |
@@ -2167,7 +2163,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
2167 | correct_index = 1; | 2163 | correct_index = 1; |
2168 | credits += (ext_depth(inode)) + 1; | 2164 | credits += (ext_depth(inode)) + 1; |
2169 | } | 2165 | } |
2170 | credits += 2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb); | 2166 | credits += EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); |
2171 | 2167 | ||
2172 | err = ext4_ext_truncate_extend_restart(handle, inode, credits); | 2168 | err = ext4_ext_truncate_extend_restart(handle, inode, credits); |
2173 | if (err) | 2169 | if (err) |
@@ -3064,6 +3060,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
3064 | if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) { | 3060 | if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) { |
3065 | ret = ext4_convert_unwritten_extents_dio(handle, inode, | 3061 | ret = ext4_convert_unwritten_extents_dio(handle, inode, |
3066 | path); | 3062 | path); |
3063 | if (ret >= 0) | ||
3064 | ext4_update_inode_fsync_trans(handle, inode, 1); | ||
3067 | goto out2; | 3065 | goto out2; |
3068 | } | 3066 | } |
3069 | /* buffered IO case */ | 3067 | /* buffered IO case */ |
@@ -3091,6 +3089,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
3091 | ret = ext4_ext_convert_to_initialized(handle, inode, | 3089 | ret = ext4_ext_convert_to_initialized(handle, inode, |
3092 | path, iblock, | 3090 | path, iblock, |
3093 | max_blocks); | 3091 | max_blocks); |
3092 | if (ret >= 0) | ||
3093 | ext4_update_inode_fsync_trans(handle, inode, 1); | ||
3094 | out: | 3094 | out: |
3095 | if (ret <= 0) { | 3095 | if (ret <= 0) { |
3096 | err = ret; | 3096 | err = ret; |
@@ -3319,8 +3319,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
3319 | /* not a good idea to call discard here directly, | 3319 | /* not a good idea to call discard here directly, |
3320 | * but otherwise we'd need to call it every free() */ | 3320 | * but otherwise we'd need to call it every free() */ |
3321 | ext4_discard_preallocations(inode); | 3321 | ext4_discard_preallocations(inode); |
3322 | ext4_free_blocks(handle, inode, ext_pblock(&newex), | 3322 | ext4_free_blocks(handle, inode, 0, ext_pblock(&newex), |
3323 | ext4_ext_get_actual_len(&newex), 0); | 3323 | ext4_ext_get_actual_len(&newex), 0); |
3324 | goto out2; | 3324 | goto out2; |
3325 | } | 3325 | } |
3326 | 3326 | ||
@@ -3329,10 +3329,16 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
3329 | allocated = ext4_ext_get_actual_len(&newex); | 3329 | allocated = ext4_ext_get_actual_len(&newex); |
3330 | set_buffer_new(bh_result); | 3330 | set_buffer_new(bh_result); |
3331 | 3331 | ||
3332 | /* Cache only when it is _not_ an uninitialized extent */ | 3332 | /* |
3333 | if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) | 3333 | * Cache the extent and update transaction to commit on fdatasync only |
3334 | * when it is _not_ an uninitialized extent. | ||
3335 | */ | ||
3336 | if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) { | ||
3334 | ext4_ext_put_in_cache(inode, iblock, allocated, newblock, | 3337 | ext4_ext_put_in_cache(inode, iblock, allocated, newblock, |
3335 | EXT4_EXT_CACHE_EXTENT); | 3338 | EXT4_EXT_CACHE_EXTENT); |
3339 | ext4_update_inode_fsync_trans(handle, inode, 1); | ||
3340 | } else | ||
3341 | ext4_update_inode_fsync_trans(handle, inode, 0); | ||
3336 | out: | 3342 | out: |
3337 | if (allocated > max_blocks) | 3343 | if (allocated > max_blocks) |
3338 | allocated = max_blocks; | 3344 | allocated = max_blocks; |
@@ -3720,10 +3726,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
3720 | * Walk the extent tree gathering extent information. | 3726 | * Walk the extent tree gathering extent information. |
3721 | * ext4_ext_fiemap_cb will push extents back to user. | 3727 | * ext4_ext_fiemap_cb will push extents back to user. |
3722 | */ | 3728 | */ |
3723 | down_read(&EXT4_I(inode)->i_data_sem); | ||
3724 | error = ext4_ext_walk_space(inode, start_blk, len_blks, | 3729 | error = ext4_ext_walk_space(inode, start_blk, len_blks, |
3725 | ext4_ext_fiemap_cb, fieinfo); | 3730 | ext4_ext_fiemap_cb, fieinfo); |
3726 | up_read(&EXT4_I(inode)->i_data_sem); | ||
3727 | } | 3731 | } |
3728 | 3732 | ||
3729 | return error; | 3733 | return error; |