aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c49
1 files changed, 36 insertions, 13 deletions
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 */
4438void ext4_free_blocks(handle_t *handle, struct inode *inode, 4438void 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