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; |
