aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c44
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:
1957static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, 1960static 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);
3094out: 3094out:
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);
3336out: 3342out:
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;