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.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 6e5a23a2cc25..0dca90be1afb 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4427,18 +4427,24 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
4427 return 0; 4427 return 0;
4428} 4428}
4429 4429
4430/* 4430/**
4431 * Main entry point into mballoc to free blocks 4431 * ext4_free_blocks() -- Free given blocks and update quota
4432 * @handle: handle for this transaction
4433 * @inode: inode
4434 * @block: start physical block to free
4435 * @count: number of blocks to count
4436 * @metadata: Are these metadata blocks
4432 */ 4437 */
4433void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, 4438void ext4_free_blocks(handle_t *handle, struct inode *inode,
4434 ext4_fsblk_t block, unsigned long count, 4439 ext4_fsblk_t block, unsigned long count,
4435 int metadata, unsigned long *freed) 4440 int metadata)
4436{ 4441{
4437 struct buffer_head *bitmap_bh = NULL; 4442 struct buffer_head *bitmap_bh = NULL;
4438 struct super_block *sb = inode->i_sb; 4443 struct super_block *sb = inode->i_sb;
4439 struct ext4_allocation_context *ac = NULL; 4444 struct ext4_allocation_context *ac = NULL;
4440 struct ext4_group_desc *gdp; 4445 struct ext4_group_desc *gdp;
4441 struct ext4_super_block *es; 4446 struct ext4_super_block *es;
4447 unsigned long freed = 0;
4442 unsigned int overflow; 4448 unsigned int overflow;
4443 ext4_grpblk_t bit; 4449 ext4_grpblk_t bit;
4444 struct buffer_head *gd_bh; 4450 struct buffer_head *gd_bh;
@@ -4448,7 +4454,15 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
4448 int err = 0; 4454 int err = 0;
4449 int ret; 4455 int ret;
4450 4456
4451 *freed = 0; 4457 /*
4458 * We need to make sure we don't reuse the freed block until
4459 * after the transaction is committed, which we can do by
4460 * treating the block as metadata, below. We make an
4461 * exception if the inode is to be written in writeback mode
4462 * since writeback mode has weak data consistency guarantees.
4463 */
4464 if (!ext4_should_writeback_data(inode))
4465 metadata = 1;
4452 4466
4453 sbi = EXT4_SB(sb); 4467 sbi = EXT4_SB(sb);
4454 es = EXT4_SB(sb)->s_es; 4468 es = EXT4_SB(sb)->s_es;
@@ -4577,7 +4591,7 @@ do_more:
4577 4591
4578 ext4_mb_release_desc(&e4b); 4592 ext4_mb_release_desc(&e4b);
4579 4593
4580 *freed += count; 4594 freed += count;
4581 4595
4582 /* We dirtied the bitmap block */ 4596 /* We dirtied the bitmap block */
4583 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); 4597 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
@@ -4597,6 +4611,8 @@ do_more:
4597 } 4611 }
4598 sb->s_dirt = 1; 4612 sb->s_dirt = 1;
4599error_return: 4613error_return:
4614 if (freed)
4615 vfs_dq_free_block(inode, freed);
4600 brelse(bitmap_bh); 4616 brelse(bitmap_bh);
4601 ext4_std_error(sb, err); 4617 ext4_std_error(sb, err);
4602 if (ac) 4618 if (ac)