diff options
-rw-r--r-- | fs/ext4/ext4.h | 10 | ||||
-rw-r--r-- | fs/ext4/extents.c | 24 | ||||
-rw-r--r-- | fs/ext4/inode.c | 67 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 49 | ||||
-rw-r--r-- | fs/ext4/migrate.c | 23 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 8 | ||||
-rw-r--r-- | include/trace/events/ext4.h | 16 |
7 files changed, 109 insertions, 88 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 210e1b53e91f..4cfc2f0edb3f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -376,6 +376,12 @@ struct ext4_new_group_data { | |||
376 | EXT4_GET_BLOCKS_DIO_CREATE_EXT) | 376 | EXT4_GET_BLOCKS_DIO_CREATE_EXT) |
377 | 377 | ||
378 | /* | 378 | /* |
379 | * Flags used by ext4_free_blocks | ||
380 | */ | ||
381 | #define EXT4_FREE_BLOCKS_METADATA 0x0001 | ||
382 | #define EXT4_FREE_BLOCKS_FORGET 0x0002 | ||
383 | |||
384 | /* | ||
379 | * ioctl commands | 385 | * ioctl commands |
380 | */ | 386 | */ |
381 | #define EXT4_IOC_GETFLAGS FS_IOC_GETFLAGS | 387 | #define EXT4_IOC_GETFLAGS FS_IOC_GETFLAGS |
@@ -1384,8 +1390,8 @@ extern void ext4_discard_preallocations(struct inode *); | |||
1384 | extern int __init init_ext4_mballoc(void); | 1390 | extern int __init init_ext4_mballoc(void); |
1385 | extern void exit_ext4_mballoc(void); | 1391 | extern void exit_ext4_mballoc(void); |
1386 | extern void ext4_free_blocks(handle_t *handle, struct inode *inode, | 1392 | extern void ext4_free_blocks(handle_t *handle, struct inode *inode, |
1387 | ext4_fsblk_t block, unsigned long count, | 1393 | struct buffer_head *bh, ext4_fsblk_t block, |
1388 | int metadata); | 1394 | unsigned long count, int flags); |
1389 | extern int ext4_mb_add_groupinfo(struct super_block *sb, | 1395 | extern int ext4_mb_add_groupinfo(struct super_block *sb, |
1390 | ext4_group_t i, struct ext4_group_desc *desc); | 1396 | ext4_group_t i, struct ext4_group_desc *desc); |
1391 | extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t); | 1397 | extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 74dcff84c3a8..2c4a9321fb14 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); |
@@ -1957,7 +1958,6 @@ errout: | |||
1957 | static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | 1958 | static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, |
1958 | struct ext4_ext_path *path) | 1959 | struct ext4_ext_path *path) |
1959 | { | 1960 | { |
1960 | struct buffer_head *bh; | ||
1961 | int err; | 1961 | int err; |
1962 | ext4_fsblk_t leaf; | 1962 | ext4_fsblk_t leaf; |
1963 | 1963 | ||
@@ -1973,9 +1973,8 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | |||
1973 | if (err) | 1973 | if (err) |
1974 | return err; | 1974 | return err; |
1975 | ext_debug("index is empty, remove it, free block %llu\n", leaf); | 1975 | ext_debug("index is empty, remove it, free block %llu\n", leaf); |
1976 | bh = sb_find_get_block(inode->i_sb, leaf); | 1976 | ext4_free_blocks(handle, inode, 0, leaf, 1, |
1977 | ext4_forget(handle, 1, inode, bh, leaf); | 1977 | EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); |
1978 | ext4_free_blocks(handle, inode, leaf, 1, 1); | ||
1979 | return err; | 1978 | return err; |
1980 | } | 1979 | } |
1981 | 1980 | ||
@@ -2042,12 +2041,11 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
2042 | struct ext4_extent *ex, | 2041 | struct ext4_extent *ex, |
2043 | ext4_lblk_t from, ext4_lblk_t to) | 2042 | ext4_lblk_t from, ext4_lblk_t to) |
2044 | { | 2043 | { |
2045 | struct buffer_head *bh; | ||
2046 | unsigned short ee_len = ext4_ext_get_actual_len(ex); | 2044 | unsigned short ee_len = ext4_ext_get_actual_len(ex); |
2047 | int i, metadata = 0; | 2045 | int flags = EXT4_FREE_BLOCKS_FORGET; |
2048 | 2046 | ||
2049 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | 2047 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
2050 | metadata = 1; | 2048 | flags |= EXT4_FREE_BLOCKS_METADATA; |
2051 | #ifdef EXTENTS_STATS | 2049 | #ifdef EXTENTS_STATS |
2052 | { | 2050 | { |
2053 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 2051 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
@@ -2072,11 +2070,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
2072 | num = le32_to_cpu(ex->ee_block) + ee_len - from; | 2070 | num = le32_to_cpu(ex->ee_block) + ee_len - from; |
2073 | start = ext_pblock(ex) + ee_len - num; | 2071 | start = ext_pblock(ex) + ee_len - num; |
2074 | ext_debug("free last %u blocks starting %llu\n", num, start); | 2072 | ext_debug("free last %u blocks starting %llu\n", num, start); |
2075 | for (i = 0; i < num; i++) { | 2073 | ext4_free_blocks(handle, inode, 0, start, num, flags); |
2076 | bh = sb_find_get_block(inode->i_sb, start + i); | ||
2077 | ext4_forget(handle, metadata, inode, bh, start + i); | ||
2078 | } | ||
2079 | ext4_free_blocks(handle, inode, start, num, metadata); | ||
2080 | } else if (from == le32_to_cpu(ex->ee_block) | 2074 | } else if (from == le32_to_cpu(ex->ee_block) |
2081 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { | 2075 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { |
2082 | printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", | 2076 | printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", |
@@ -3319,8 +3313,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
3319 | /* not a good idea to call discard here directly, | 3313 | /* not a good idea to call discard here directly, |
3320 | * but otherwise we'd need to call it every free() */ | 3314 | * but otherwise we'd need to call it every free() */ |
3321 | ext4_discard_preallocations(inode); | 3315 | ext4_discard_preallocations(inode); |
3322 | ext4_free_blocks(handle, inode, ext_pblock(&newex), | 3316 | ext4_free_blocks(handle, inode, 0, ext_pblock(&newex), |
3323 | ext4_ext_get_actual_len(&newex), 0); | 3317 | ext4_ext_get_actual_len(&newex), 0); |
3324 | goto out2; | 3318 | goto out2; |
3325 | } | 3319 | } |
3326 | 3320 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 72c694323492..3b28e1fbfc90 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -669,7 +669,7 @@ allocated: | |||
669 | return ret; | 669 | return ret; |
670 | failed_out: | 670 | failed_out: |
671 | for (i = 0; i < index; i++) | 671 | for (i = 0; i < index; i++) |
672 | ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); | 672 | ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); |
673 | return ret; | 673 | return ret; |
674 | } | 674 | } |
675 | 675 | ||
@@ -765,20 +765,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, | |||
765 | return err; | 765 | return err; |
766 | failed: | 766 | failed: |
767 | /* Allocation failed, free what we already allocated */ | 767 | /* Allocation failed, free what we already allocated */ |
768 | ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0); | ||
768 | for (i = 1; i <= n ; i++) { | 769 | for (i = 1; i <= n ; i++) { |
769 | BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget"); | ||
770 | /* | 770 | /* |
771 | * Note: is_metadata is 0 because branch[i].bh is | 771 | * branch[i].bh is newly allocated, so there is no |
772 | * newly allocated, so there is no need to revoke the | 772 | * need to revoke the block, which is why we don't |
773 | * block. If we do, it's harmless, but not necessary. | 773 | * need to set EXT4_FREE_BLOCKS_METADATA. |
774 | */ | 774 | */ |
775 | ext4_forget(handle, 0, inode, branch[i].bh, | 775 | ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, |
776 | branch[i].bh->b_blocknr); | 776 | EXT4_FREE_BLOCKS_FORGET); |
777 | } | 777 | } |
778 | for (i = 0; i < indirect_blks; i++) | 778 | for (i = n+1; i < indirect_blks; i++) |
779 | ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); | 779 | ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); |
780 | 780 | ||
781 | ext4_free_blocks(handle, inode, new_blocks[i], num, 0); | 781 | ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0); |
782 | 782 | ||
783 | return err; | 783 | return err; |
784 | } | 784 | } |
@@ -857,18 +857,16 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode, | |||
857 | 857 | ||
858 | err_out: | 858 | err_out: |
859 | for (i = 1; i <= num; i++) { | 859 | for (i = 1; i <= num; i++) { |
860 | BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget"); | ||
861 | /* | 860 | /* |
862 | * Note: is_metadata is 0 because branch[i].bh is | 861 | * branch[i].bh is newly allocated, so there is no |
863 | * newly allocated, so there is no need to revoke the | 862 | * need to revoke the block, which is why we don't |
864 | * block. If we do, it's harmless, but not necessary. | 863 | * need to set EXT4_FREE_BLOCKS_METADATA. |
865 | */ | 864 | */ |
866 | ext4_forget(handle, 0, inode, where[i].bh, | 865 | ext4_free_blocks(handle, inode, where[i].bh, 0, 1, |
867 | where[i].bh->b_blocknr); | 866 | EXT4_FREE_BLOCKS_FORGET); |
868 | ext4_free_blocks(handle, inode, | ||
869 | le32_to_cpu(where[i-1].key), 1, 0); | ||
870 | } | 867 | } |
871 | ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 0); | 868 | ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key), |
869 | blks, 0); | ||
872 | 870 | ||
873 | return err; | 871 | return err; |
874 | } | 872 | } |
@@ -4080,7 +4078,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, | |||
4080 | __le32 *last) | 4078 | __le32 *last) |
4081 | { | 4079 | { |
4082 | __le32 *p; | 4080 | __le32 *p; |
4083 | int is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode); | 4081 | int flags = EXT4_FREE_BLOCKS_FORGET; |
4082 | |||
4083 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | ||
4084 | flags |= EXT4_FREE_BLOCKS_METADATA; | ||
4084 | 4085 | ||
4085 | if (try_to_extend_transaction(handle, inode)) { | 4086 | if (try_to_extend_transaction(handle, inode)) { |
4086 | if (bh) { | 4087 | if (bh) { |
@@ -4096,27 +4097,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, | |||
4096 | } | 4097 | } |
4097 | } | 4098 | } |
4098 | 4099 | ||
4099 | /* | 4100 | for (p = first; p < last; p++) |
4100 | * Any buffers which are on the journal will be in memory. We | 4101 | *p = 0; |
4101 | * find them on the hash table so jbd2_journal_revoke() will | ||
4102 | * run jbd2_journal_forget() on them. We've already detached | ||
4103 | * each block from the file, so bforget() in | ||
4104 | * jbd2_journal_forget() should be safe. | ||
4105 | * | ||
4106 | * AKPM: turn on bforget in jbd2_journal_forget()!!! | ||
4107 | */ | ||
4108 | for (p = first; p < last; p++) { | ||
4109 | u32 nr = le32_to_cpu(*p); | ||
4110 | if (nr) { | ||
4111 | struct buffer_head *tbh; | ||
4112 | |||
4113 | *p = 0; | ||
4114 | tbh = sb_find_get_block(inode->i_sb, nr); | ||
4115 | ext4_forget(handle, is_metadata, inode, tbh, nr); | ||
4116 | } | ||
4117 | } | ||
4118 | 4102 | ||
4119 | ext4_free_blocks(handle, inode, block_to_free, count, is_metadata); | 4103 | ext4_free_blocks(handle, inode, 0, block_to_free, count, flags); |
4120 | } | 4104 | } |
4121 | 4105 | ||
4122 | /** | 4106 | /** |
@@ -4304,7 +4288,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
4304 | blocks_for_truncate(inode)); | 4288 | blocks_for_truncate(inode)); |
4305 | } | 4289 | } |
4306 | 4290 | ||
4307 | ext4_free_blocks(handle, inode, nr, 1, 1); | 4291 | ext4_free_blocks(handle, inode, 0, nr, 1, |
4292 | EXT4_FREE_BLOCKS_METADATA); | ||
4308 | 4293 | ||
4309 | if (parent_bh) { | 4294 | if (parent_bh) { |
4310 | /* | 4295 | /* |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 0dca90be1afb..78de5d3c5dce 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -4436,8 +4436,8 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
4436 | * @metadata: Are these metadata blocks | 4436 | * @metadata: Are these metadata blocks |
4437 | */ | 4437 | */ |
4438 | void ext4_free_blocks(handle_t *handle, struct inode *inode, | 4438 | void ext4_free_blocks(handle_t *handle, struct inode *inode, |
4439 | ext4_fsblk_t block, unsigned long count, | 4439 | struct buffer_head *bh, ext4_fsblk_t block, |
4440 | int metadata) | 4440 | unsigned long count, int flags) |
4441 | { | 4441 | { |
4442 | struct buffer_head *bitmap_bh = NULL; | 4442 | struct buffer_head *bitmap_bh = NULL; |
4443 | struct super_block *sb = inode->i_sb; | 4443 | struct super_block *sb = inode->i_sb; |
@@ -4454,15 +4454,12 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
4454 | int err = 0; | 4454 | int err = 0; |
4455 | int ret; | 4455 | int ret; |
4456 | 4456 | ||
4457 | /* | 4457 | if (bh) { |
4458 | * We need to make sure we don't reuse the freed block until | 4458 | if (block) |
4459 | * after the transaction is committed, which we can do by | 4459 | BUG_ON(block != bh->b_blocknr); |
4460 | * treating the block as metadata, below. We make an | 4460 | else |
4461 | * exception if the inode is to be written in writeback mode | 4461 | block = bh->b_blocknr; |
4462 | * since writeback mode has weak data consistency guarantees. | 4462 | } |
4463 | */ | ||
4464 | if (!ext4_should_writeback_data(inode)) | ||
4465 | metadata = 1; | ||
4466 | 4463 | ||
4467 | sbi = EXT4_SB(sb); | 4464 | sbi = EXT4_SB(sb); |
4468 | es = EXT4_SB(sb)->s_es; | 4465 | es = EXT4_SB(sb)->s_es; |
@@ -4476,7 +4473,32 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
4476 | } | 4473 | } |
4477 | 4474 | ||
4478 | ext4_debug("freeing block %llu\n", block); | 4475 | ext4_debug("freeing block %llu\n", block); |
4479 | trace_ext4_free_blocks(inode, block, count, metadata); | 4476 | trace_ext4_free_blocks(inode, block, count, flags); |
4477 | |||
4478 | if (flags & EXT4_FREE_BLOCKS_FORGET) { | ||
4479 | struct buffer_head *tbh = bh; | ||
4480 | int i; | ||
4481 | |||
4482 | BUG_ON(bh && (count > 1)); | ||
4483 | |||
4484 | for (i = 0; i < count; i++) { | ||
4485 | if (!bh) | ||
4486 | tbh = sb_find_get_block(inode->i_sb, | ||
4487 | block + i); | ||
4488 | ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA, | ||
4489 | inode, tbh, block + i); | ||
4490 | } | ||
4491 | } | ||
4492 | |||
4493 | /* | ||
4494 | * We need to make sure we don't reuse the freed block until | ||
4495 | * after the transaction is committed, which we can do by | ||
4496 | * treating the block as metadata, below. We make an | ||
4497 | * exception if the inode is to be written in writeback mode | ||
4498 | * since writeback mode has weak data consistency guarantees. | ||
4499 | */ | ||
4500 | if (!ext4_should_writeback_data(inode)) | ||
4501 | flags |= EXT4_FREE_BLOCKS_METADATA; | ||
4480 | 4502 | ||
4481 | ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); | 4503 | ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); |
4482 | if (ac) { | 4504 | if (ac) { |
@@ -4552,7 +4574,8 @@ do_more: | |||
4552 | err = ext4_mb_load_buddy(sb, block_group, &e4b); | 4574 | err = ext4_mb_load_buddy(sb, block_group, &e4b); |
4553 | if (err) | 4575 | if (err) |
4554 | goto error_return; | 4576 | goto error_return; |
4555 | if (metadata && ext4_handle_valid(handle)) { | 4577 | |
4578 | if ((flags & EXT4_FREE_BLOCKS_METADATA) && ext4_handle_valid(handle)) { | ||
4556 | struct ext4_free_data *new_entry; | 4579 | struct ext4_free_data *new_entry; |
4557 | /* | 4580 | /* |
4558 | * blocks being freed are metadata. these blocks shouldn't | 4581 | * blocks being freed are metadata. these blocks shouldn't |
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index a93d5b80f3e2..d641e13e740e 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c | |||
@@ -262,13 +262,17 @@ static int free_dind_blocks(handle_t *handle, | |||
262 | for (i = 0; i < max_entries; i++) { | 262 | for (i = 0; i < max_entries; i++) { |
263 | if (tmp_idata[i]) { | 263 | if (tmp_idata[i]) { |
264 | extend_credit_for_blkdel(handle, inode); | 264 | extend_credit_for_blkdel(handle, inode); |
265 | ext4_free_blocks(handle, inode, | 265 | ext4_free_blocks(handle, inode, 0, |
266 | le32_to_cpu(tmp_idata[i]), 1, 1); | 266 | le32_to_cpu(tmp_idata[i]), 1, |
267 | EXT4_FREE_BLOCKS_METADATA | | ||
268 | EXT4_FREE_BLOCKS_FORGET); | ||
267 | } | 269 | } |
268 | } | 270 | } |
269 | put_bh(bh); | 271 | put_bh(bh); |
270 | extend_credit_for_blkdel(handle, inode); | 272 | extend_credit_for_blkdel(handle, inode); |
271 | ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); | 273 | ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, |
274 | EXT4_FREE_BLOCKS_METADATA | | ||
275 | EXT4_FREE_BLOCKS_FORGET); | ||
272 | return 0; | 276 | return 0; |
273 | } | 277 | } |
274 | 278 | ||
@@ -297,7 +301,9 @@ static int free_tind_blocks(handle_t *handle, | |||
297 | } | 301 | } |
298 | put_bh(bh); | 302 | put_bh(bh); |
299 | extend_credit_for_blkdel(handle, inode); | 303 | extend_credit_for_blkdel(handle, inode); |
300 | ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); | 304 | ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, |
305 | EXT4_FREE_BLOCKS_METADATA | | ||
306 | EXT4_FREE_BLOCKS_FORGET); | ||
301 | return 0; | 307 | return 0; |
302 | } | 308 | } |
303 | 309 | ||
@@ -308,8 +314,10 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data) | |||
308 | /* ei->i_data[EXT4_IND_BLOCK] */ | 314 | /* ei->i_data[EXT4_IND_BLOCK] */ |
309 | if (i_data[0]) { | 315 | if (i_data[0]) { |
310 | extend_credit_for_blkdel(handle, inode); | 316 | extend_credit_for_blkdel(handle, inode); |
311 | ext4_free_blocks(handle, inode, | 317 | ext4_free_blocks(handle, inode, 0, |
312 | le32_to_cpu(i_data[0]), 1, 1); | 318 | le32_to_cpu(i_data[0]), 1, |
319 | EXT4_FREE_BLOCKS_METADATA | | ||
320 | EXT4_FREE_BLOCKS_FORGET); | ||
313 | } | 321 | } |
314 | 322 | ||
315 | /* ei->i_data[EXT4_DIND_BLOCK] */ | 323 | /* ei->i_data[EXT4_DIND_BLOCK] */ |
@@ -419,7 +427,8 @@ static int free_ext_idx(handle_t *handle, struct inode *inode, | |||
419 | } | 427 | } |
420 | put_bh(bh); | 428 | put_bh(bh); |
421 | extend_credit_for_blkdel(handle, inode); | 429 | extend_credit_for_blkdel(handle, inode); |
422 | ext4_free_blocks(handle, inode, block, 1, 1); | 430 | ext4_free_blocks(handle, inode, 0, block, 1, |
431 | EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); | ||
423 | return retval; | 432 | return retval; |
424 | } | 433 | } |
425 | 434 | ||
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 025701926f9a..910bf9a59cb3 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -482,9 +482,10 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
482 | ea_bdebug(bh, "refcount now=0; freeing"); | 482 | ea_bdebug(bh, "refcount now=0; freeing"); |
483 | if (ce) | 483 | if (ce) |
484 | mb_cache_entry_free(ce); | 484 | mb_cache_entry_free(ce); |
485 | ext4_free_blocks(handle, inode, bh->b_blocknr, 1, 1); | ||
486 | get_bh(bh); | 485 | get_bh(bh); |
487 | ext4_forget(handle, 1, inode, bh, bh->b_blocknr); | 486 | ext4_free_blocks(handle, inode, bh, 0, 1, |
487 | EXT4_FREE_BLOCKS_METADATA | | ||
488 | EXT4_FREE_BLOCKS_FORGET); | ||
488 | } else { | 489 | } else { |
489 | le32_add_cpu(&BHDR(bh)->h_refcount, -1); | 490 | le32_add_cpu(&BHDR(bh)->h_refcount, -1); |
490 | error = ext4_handle_dirty_metadata(handle, inode, bh); | 491 | error = ext4_handle_dirty_metadata(handle, inode, bh); |
@@ -832,7 +833,8 @@ inserted: | |||
832 | new_bh = sb_getblk(sb, block); | 833 | new_bh = sb_getblk(sb, block); |
833 | if (!new_bh) { | 834 | if (!new_bh) { |
834 | getblk_failed: | 835 | getblk_failed: |
835 | ext4_free_blocks(handle, inode, block, 1, 1); | 836 | ext4_free_blocks(handle, inode, 0, block, 1, |
837 | EXT4_FREE_BLOCKS_METADATA); | ||
836 | error = -EIO; | 838 | error = -EIO; |
837 | goto cleanup; | 839 | goto cleanup; |
838 | } | 840 | } |
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index b390e1fc4a7b..74f628bfdd1b 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h | |||
@@ -650,30 +650,32 @@ TRACE_EVENT(ext4_allocate_blocks, | |||
650 | 650 | ||
651 | TRACE_EVENT(ext4_free_blocks, | 651 | TRACE_EVENT(ext4_free_blocks, |
652 | TP_PROTO(struct inode *inode, __u64 block, unsigned long count, | 652 | TP_PROTO(struct inode *inode, __u64 block, unsigned long count, |
653 | int metadata), | 653 | int flags), |
654 | 654 | ||
655 | TP_ARGS(inode, block, count, metadata), | 655 | TP_ARGS(inode, block, count, flags), |
656 | 656 | ||
657 | TP_STRUCT__entry( | 657 | TP_STRUCT__entry( |
658 | __field( dev_t, dev ) | 658 | __field( dev_t, dev ) |
659 | __field( ino_t, ino ) | 659 | __field( ino_t, ino ) |
660 | __field( umode_t, mode ) | ||
660 | __field( __u64, block ) | 661 | __field( __u64, block ) |
661 | __field( unsigned long, count ) | 662 | __field( unsigned long, count ) |
662 | __field( int, metadata ) | 663 | __field( int, flags ) |
663 | |||
664 | ), | 664 | ), |
665 | 665 | ||
666 | TP_fast_assign( | 666 | TP_fast_assign( |
667 | __entry->dev = inode->i_sb->s_dev; | 667 | __entry->dev = inode->i_sb->s_dev; |
668 | __entry->ino = inode->i_ino; | 668 | __entry->ino = inode->i_ino; |
669 | __entry->mode = inode->i_mode; | ||
669 | __entry->block = block; | 670 | __entry->block = block; |
670 | __entry->count = count; | 671 | __entry->count = count; |
671 | __entry->metadata = metadata; | 672 | __entry->flags = flags; |
672 | ), | 673 | ), |
673 | 674 | ||
674 | TP_printk("dev %s ino %lu block %llu count %lu metadata %d", | 675 | TP_printk("dev %s ino %lu mode 0%o block %llu count %lu flags %d", |
675 | jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, | 676 | jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino, |
676 | __entry->block, __entry->count, __entry->metadata) | 677 | __entry->mode, __entry->block, __entry->count, |
678 | __entry->flags) | ||
677 | ); | 679 | ); |
678 | 680 | ||
679 | TRACE_EVENT(ext4_sync_file, | 681 | TRACE_EVENT(ext4_sync_file, |