diff options
-rw-r--r-- | fs/ext4/balloc.c | 38 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 7 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 30 |
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 | */ | ||
509 | void 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); |
1326 | extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); | 1326 | extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); |
1327 | extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); | 1327 | extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); |
1328 | extern void ext4_free_blocks(handle_t *handle, struct inode *inode, | ||
1329 | ext4_fsblk_t block, unsigned long count, int metadata); | ||
1330 | extern void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | 1328 | extern 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); |
1332 | extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *); | 1330 | extern ext4_fsblk_t ext4_count_free_blocks(struct super_block *); |
@@ -1385,8 +1383,9 @@ extern int ext4_mb_reserve_blocks(struct super_block *, int); | |||
1385 | extern void ext4_discard_preallocations(struct inode *); | 1383 | extern void ext4_discard_preallocations(struct inode *); |
1386 | extern int __init init_ext4_mballoc(void); | 1384 | extern int __init init_ext4_mballoc(void); |
1387 | extern void exit_ext4_mballoc(void); | 1385 | extern void exit_ext4_mballoc(void); |
1388 | extern void ext4_mb_free_blocks(handle_t *, struct inode *, | 1386 | extern 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); | ||
1390 | extern int ext4_mb_add_groupinfo(struct super_block *sb, | 1389 | extern 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); |
1392 | extern int ext4_mb_get_buddy_cache_lock(struct super_block *, ext4_group_t); | 1391 | extern 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 | */ |
4433 | void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, | 4438 | void 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; |
4599 | error_return: | 4613 | error_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) |