aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/balloc.c38
-rw-r--r--fs/ext4/ext4.h7
-rw-r--r--fs/ext4/mballoc.c30
3 files changed, 26 insertions, 49 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index f3032c919a22..22bc7435d913 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -499,44 +499,6 @@ error_return:
499} 499}
500 500
501/** 501/**
502 * ext4_free_blocks() -- Free given blocks and update quota
503 * @handle: handle for this transaction
504 * @inode: inode
505 * @block: start physical block to free
506 * @count: number of blocks to count
507 * @metadata: Are these metadata blocks
508 */
509void ext4_free_blocks(handle_t *handle, struct inode *inode,
510 ext4_fsblk_t block, unsigned long count,
511 int metadata)
512{
513 struct super_block *sb;
514 unsigned long dquot_freed_blocks;
515
516 /* this isn't the right place to decide whether block is metadata
517 * inode.c/extents.c knows better, but for safety ... */
518 if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
519 metadata = 1;
520
521 /* We need to make sure we don't reuse
522 * block released untill the transaction commit.
523 * writeback mode have weak data consistency so
524 * don't force data as metadata when freeing block
525 * for writeback mode.
526 */
527 if (metadata == 0 && !ext4_should_writeback_data(inode))
528 metadata = 1;
529
530 sb = inode->i_sb;
531
532 ext4_mb_free_blocks(handle, inode, block, count,
533 metadata, &dquot_freed_blocks);
534 if (dquot_freed_blocks)
535 vfs_dq_free_block(inode, dquot_freed_blocks);
536 return;
537}
538
539/**
540 * ext4_has_free_blocks() 502 * ext4_has_free_blocks()
541 * @sbi: in-core super block structure. 503 * @sbi: in-core super block structure.
542 * @nblocks: number of needed blocks 504 * @nblocks: number of needed blocks
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 57c4e03afa0a..210e1b53e91f 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1325,8 +1325,6 @@ extern ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
1325 ext4_fsblk_t goal, unsigned long *count, int *errp); 1325 ext4_fsblk_t goal, unsigned long *count, int *errp);
1326extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); 1326extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
1327extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); 1327extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks);
1328extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
1329 ext4_fsblk_t block, unsigned long count, int metadata);
1330extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, 1328extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
1331 ext4_fsblk_t block, unsigned long count); 1329 ext4_fsblk_t block, unsigned long count);
1332extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *); 1330extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *);
@@ -1385,8 +1383,9 @@ extern int ext4_mb_reserve_blocks(struct super_block *, int);
1385extern void ext4_discard_preallocations(struct inode *); 1383extern void ext4_discard_preallocations(struct inode *);
1386extern int __init init_ext4_mballoc(void); 1384extern int __init init_ext4_mballoc(void);
1387extern void exit_ext4_mballoc(void); 1385extern void exit_ext4_mballoc(void);
1388extern void ext4_mb_free_blocks(handle_t *, struct inode *, 1386extern void ext4_free_blocks(handle_t *handle, struct inode *inode,
1389 ext4_fsblk_t, unsigned long, int, unsigned long *); 1387 ext4_fsblk_t block, unsigned long count,
1388 int metadata);
1390extern int ext4_mb_add_groupinfo(struct super_block *sb, 1389extern int ext4_mb_add_groupinfo(struct super_block *sb,
1391 ext4_group_t i, struct ext4_group_desc *desc); 1390 ext4_group_t i, struct ext4_group_desc *desc);
1392extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t); 1391extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t);
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)