ext4: delayed allocation ENOSPC handling
This patch does block reservation for delayed allocation, to avoid ENOSPC later at page flush time. Blocks(data and metadata) are reserved at da_write_begin() time, the freeblocks counter is updated by then, and the number of reserved blocks is store in per inode counter. At the writepage time, the unused reserved meta blocks are returned back. At unlink/truncate time, reserved blocks are properly released. Updated fix from Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> to fix the oldallocator block reservation accounting with delalloc, added lock to guard the counters and also fix the reservation for meta blocks. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Mingming Cao <cmm@us.ibm.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
committed by
Theodore Ts'o
parent
e8ced39d5e
commit
d2a1763791
@@ -2964,7 +2964,15 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
|
||||
le16_add_cpu(&gdp->bg_free_blocks_count, -ac->ac_b_ex.fe_len);
|
||||
gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
|
||||
spin_unlock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group));
|
||||
percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
|
||||
|
||||
/*
|
||||
* free blocks account has already be reduced/reserved
|
||||
* at write_begin() time for delayed allocation
|
||||
* do not double accounting
|
||||
*/
|
||||
if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
|
||||
percpu_counter_sub(&sbi->s_freeblocks_counter,
|
||||
ac->ac_b_ex.fe_len);
|
||||
|
||||
if (sbi->s_log_groups_per_flex) {
|
||||
ext4_group_t flex_group = ext4_flex_group(sbi,
|
||||
@@ -4169,7 +4177,12 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
|
||||
&(ar->len), errp);
|
||||
return block;
|
||||
}
|
||||
ar->len = ext4_has_free_blocks(sbi, ar->len);
|
||||
if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) {
|
||||
/*
|
||||
* With delalloc we already reserved the blocks
|
||||
*/
|
||||
ar->len = ext4_has_free_blocks(sbi, ar->len);
|
||||
}
|
||||
|
||||
if (ar->len == 0) {
|
||||
*errp = -ENOSPC;
|
||||
@@ -4186,6 +4199,9 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
|
||||
}
|
||||
inquota = ar->len;
|
||||
|
||||
if (EXT4_I(ar->inode)->i_delalloc_reserved_flag)
|
||||
ar->flags |= EXT4_MB_DELALLOC_RESERVED;
|
||||
|
||||
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
|
||||
if (!ac) {
|
||||
ar->len = 0;
|
||||
|
Reference in New Issue
Block a user