aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/balloc.c
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2008-07-14 17:52:37 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-07-14 17:52:37 -0400
commitd2a1763791a634e315ec926b62829c1e88842c86 (patch)
tree75a701a89829ba7d728fdc19c30aa2794b9706b9 /fs/ext4/balloc.c
parente8ced39d5e8911c662d4d69a342b9d053eaaac4e (diff)
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>
Diffstat (limited to 'fs/ext4/balloc.c')
-rw-r--r--fs/ext4/balloc.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 6369bacf0dcb..495ab21b9832 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1701,7 +1701,12 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
1701 } 1701 }
1702 1702
1703 sbi = EXT4_SB(sb); 1703 sbi = EXT4_SB(sb);
1704 *count = ext4_has_free_blocks(sbi, *count); 1704 if (!EXT4_I(inode)->i_delalloc_reserved_flag) {
1705 /*
1706 * With delalloc we already reserved the blocks
1707 */
1708 *count = ext4_has_free_blocks(sbi, *count);
1709 }
1705 if (*count == 0) { 1710 if (*count == 0) {
1706 *errp = -ENOSPC; 1711 *errp = -ENOSPC;
1707 return 0; /*return with ENOSPC error */ 1712 return 0; /*return with ENOSPC error */
@@ -1902,7 +1907,8 @@ allocated:
1902 le16_add_cpu(&gdp->bg_free_blocks_count, -num); 1907 le16_add_cpu(&gdp->bg_free_blocks_count, -num);
1903 gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp); 1908 gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp);
1904 spin_unlock(sb_bgl_lock(sbi, group_no)); 1909 spin_unlock(sb_bgl_lock(sbi, group_no));
1905 percpu_counter_sub(&sbi->s_freeblocks_counter, num); 1910 if (!EXT4_I(inode)->i_delalloc_reserved_flag)
1911 percpu_counter_sub(&sbi->s_freeblocks_counter, num);
1906 1912
1907 if (sbi->s_log_groups_per_flex) { 1913 if (sbi->s_log_groups_per_flex) {
1908 ext4_group_t flex_group = ext4_flex_group(sbi, group_no); 1914 ext4_group_t flex_group = ext4_flex_group(sbi, group_no);
@@ -1976,40 +1982,49 @@ static ext4_fsblk_t do_blk_alloc(handle_t *handle, struct inode *inode,
1976} 1982}
1977 1983
1978/* 1984/*
1979 * ext4_new_meta_block() -- allocate block for meta data (indexing) blocks 1985 * ext4_new_meta_blocks() -- allocate block for meta data (indexing) blocks
1980 * 1986 *
1981 * @handle: handle to this transaction 1987 * @handle: handle to this transaction
1982 * @inode: file inode 1988 * @inode: file inode
1983 * @goal: given target block(filesystem wide) 1989 * @goal: given target block(filesystem wide)
1990 * @count: total number of blocks need
1984 * @errp: error code 1991 * @errp: error code
1985 * 1992 *
1986 * Return allocated block number on success 1993 * Return 1st allocated block numberon success, *count stores total account
1994 * error stores in errp pointer
1987 */ 1995 */
1988ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode, 1996ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode,
1989 ext4_fsblk_t goal, int *errp) 1997 ext4_fsblk_t goal, unsigned long *count, int *errp)
1990{ 1998{
1991 unsigned long count = 1; 1999 ext4_fsblk_t ret;
1992 return do_blk_alloc(handle, inode, 0, goal, 2000 ret = do_blk_alloc(handle, inode, 0, goal,
1993 &count, errp, EXT4_META_BLOCK); 2001 count, errp, EXT4_META_BLOCK);
2002 /*
2003 * Account for the allocated meta blocks
2004 */
2005 if (!(*errp)) {
2006 spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
2007 EXT4_I(inode)->i_allocated_meta_blocks += *count;
2008 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
2009 }
2010 return ret;
1994} 2011}
1995 2012
1996/* 2013/*
1997 * ext4_new_meta_blocks() -- allocate block for meta data (indexing) blocks 2014 * ext4_new_meta_block() -- allocate block for meta data (indexing) blocks
1998 * 2015 *
1999 * @handle: handle to this transaction 2016 * @handle: handle to this transaction
2000 * @inode: file inode 2017 * @inode: file inode
2001 * @goal: given target block(filesystem wide) 2018 * @goal: given target block(filesystem wide)
2002 * @count: total number of blocks need
2003 * @errp: error code 2019 * @errp: error code
2004 * 2020 *
2005 * Return 1st allocated block numberon success, *count stores total account 2021 * Return allocated block number on success
2006 * error stores in errp pointer
2007 */ 2022 */
2008ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, 2023ext4_fsblk_t ext4_new_meta_block(handle_t *handle, struct inode *inode,
2009 ext4_fsblk_t goal, unsigned long *count, int *errp) 2024 ext4_fsblk_t goal, int *errp)
2010{ 2025{
2011 return do_blk_alloc(handle, inode, 0, goal, 2026 unsigned long count = 1;
2012 count, errp, EXT4_META_BLOCK); 2027 return ext4_new_meta_blocks(handle, inode, goal, &count, errp);
2013} 2028}
2014 2029
2015/* 2030/*