aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2009-01-22 12:13:05 -0500
committerJan Kara <jack@suse.cz>2009-03-25 21:18:34 -0400
commit60e58e0f30e723464c2a7d34b71b8675566c572d (patch)
tree2797ae1bccdad12d53c989a6dccea1c8ffd2bce3 /fs/ext4/mballoc.c
parent643d00ccc311664188c8209bf8b596a30e139c3a (diff)
ext4: quota reservation for delayed allocation
Uses quota reservation/claim/release to handle quota properly for delayed allocation in the three steps: 1) quotas are reserved when data being copied to cache when block allocation is defered 2) when new blocks are allocated. reserved quotas are converted to the real allocated quota, 2) over-booked quotas for metadata blocks are released back. Signed-off-by: Mingming Cao <cmm@us.ibm.com> Acked-by: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 9f61e62f435f..4de42090c41f 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -3086,9 +3086,12 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
3086 if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED)) 3086 if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
3087 /* release all the reserved blocks if non delalloc */ 3087 /* release all the reserved blocks if non delalloc */
3088 percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks); 3088 percpu_counter_sub(&sbi->s_dirtyblocks_counter, reserv_blks);
3089 else 3089 else {
3090 percpu_counter_sub(&sbi->s_dirtyblocks_counter, 3090 percpu_counter_sub(&sbi->s_dirtyblocks_counter,
3091 ac->ac_b_ex.fe_len); 3091 ac->ac_b_ex.fe_len);
3092 /* convert reserved quota blocks to real quota blocks */
3093 vfs_dq_claim_block(ac->ac_inode, ac->ac_b_ex.fe_len);
3094 }
3092 3095
3093 if (sbi->s_log_groups_per_flex) { 3096 if (sbi->s_log_groups_per_flex) {
3094 ext4_group_t flex_group = ext4_flex_group(sbi, 3097 ext4_group_t flex_group = ext4_flex_group(sbi,
@@ -4544,7 +4547,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
4544 struct ext4_sb_info *sbi; 4547 struct ext4_sb_info *sbi;
4545 struct super_block *sb; 4548 struct super_block *sb;
4546 ext4_fsblk_t block = 0; 4549 ext4_fsblk_t block = 0;
4547 unsigned int inquota; 4550 unsigned int inquota = 0;
4548 unsigned int reserv_blks = 0; 4551 unsigned int reserv_blks = 0;
4549 4552
4550 sb = ar->inode->i_sb; 4553 sb = ar->inode->i_sb;
@@ -4562,9 +4565,17 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
4562 (unsigned long long) ar->pleft, 4565 (unsigned long long) ar->pleft,
4563 (unsigned long long) ar->pright); 4566 (unsigned long long) ar->pright);
4564 4567
4565 if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) { 4568 /*
4566 /* 4569 * For delayed allocation, we could skip the ENOSPC and
4567 * With delalloc we already reserved the blocks 4570 * EDQUOT check, as blocks and quotas have been already
4571 * reserved when data being copied into pagecache.
4572 */
4573 if (EXT4_I(ar->inode)->i_delalloc_reserved_flag)
4574 ar->flags |= EXT4_MB_DELALLOC_RESERVED;
4575 else {
4576 /* Without delayed allocation we need to verify
4577 * there is enough free blocks to do block allocation
4578 * and verify allocation doesn't exceed the quota limits.
4568 */ 4579 */
4569 while (ar->len && ext4_claim_free_blocks(sbi, ar->len)) { 4580 while (ar->len && ext4_claim_free_blocks(sbi, ar->len)) {
4570 /* let others to free the space */ 4581 /* let others to free the space */
@@ -4576,19 +4587,16 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
4576 return 0; 4587 return 0;
4577 } 4588 }
4578 reserv_blks = ar->len; 4589 reserv_blks = ar->len;
4590 while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) {
4591 ar->flags |= EXT4_MB_HINT_NOPREALLOC;
4592 ar->len--;
4593 }
4594 inquota = ar->len;
4595 if (ar->len == 0) {
4596 *errp = -EDQUOT;
4597 goto out3;
4598 }
4579 } 4599 }
4580 while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) {
4581 ar->flags |= EXT4_MB_HINT_NOPREALLOC;
4582 ar->len--;
4583 }
4584 if (ar->len == 0) {
4585 *errp = -EDQUOT;
4586 goto out3;
4587 }
4588 inquota = ar->len;
4589
4590 if (EXT4_I(ar->inode)->i_delalloc_reserved_flag)
4591 ar->flags |= EXT4_MB_DELALLOC_RESERVED;
4592 4600
4593 ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); 4601 ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
4594 if (!ac) { 4602 if (!ac) {
@@ -4654,7 +4662,7 @@ repeat:
4654out2: 4662out2:
4655 kmem_cache_free(ext4_ac_cachep, ac); 4663 kmem_cache_free(ext4_ac_cachep, ac);
4656out1: 4664out1:
4657 if (ar->len < inquota) 4665 if (inquota && ar->len < inquota)
4658 DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len); 4666 DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len);
4659out3: 4667out3:
4660 if (!ar->len) { 4668 if (!ar->len) {