ext4: Handling preallocated blocks in delayed allocation From: Mingming Cao <cmm@xxxxxxxxxx> This patch fix ext4 delayed allocation that allows it avoid doing delayed allocation handling for blocks that are already preallocated on disk. With delayed allocation, at write_begin() time, ext4_get_blocks_wrap() now is only doing block map with create = 0. ext4_get_blocks_wrap() returns 0 if the blocks are not allocated or preallocated(). If the blocks are prea-allocated, the resulting buffer head is not mapped marked, but ext4_get_blocks_wrap() returns the number of blocks are actually being preallocated. Right now delayed allocation mistream pre-allocated blocks as un-allocated as the buffer head is unmapped. This patch fix this by checking the number of blocks returned by ext4_get_blocks_wrap() rather than checking if buffer head is mapped or not. Signed-off-by: Mingming Cao <cmm@xxxxxxxxxx> --- fs/ext4/inode.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) Index: linux-2.6.25-rc3/fs/ext4/inode.c =================================================================== --- linux-2.6.25-rc3.orig/fs/ext4/inode.c 2008-02-29 10:17:21.000000000 -0800 +++ linux-2.6.25-rc3/fs/ext4/inode.c 2008-02-29 10:40:01.000000000 -0800 @@ -1343,7 +1343,7 @@ static int ext4_journalled_write_end(str } /* - * this is a special callback for ->prepare_write() only + * this is a special callback for ->write_begin() only * it's intention is to return mapped block or reserve space */ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, @@ -1354,24 +1354,24 @@ static int ext4_da_get_block_prep(struct BUG_ON(create == 0); BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); - /* first, we need to know whether the block is allocated already - * XXX: when the filesystem has a lot of free blocks, we could - * reserve even allocated blocks to save this lookup */ + /* + * first, we need to know whether the block is allocated already + * preallocated blocks are unmapped but should treated + * the same as allocated blocks. + */ ret = ext4_get_blocks_wrap(NULL, inode, iblock, 1, bh_result, 0, 0); - if (ret >= 0) { - if (buffer_mapped(bh_result)) { - bh_result->b_size = (ret << inode->i_blkbits); - } else { - /* the block isn't allocated yet, let's reserve space */ - /* XXX: call reservation here */ - /* - * XXX: __block_prepare_write() unmaps passed block, - * is it OK? - */ - map_bh(bh_result, inode->i_sb, 0); - set_buffer_new(bh_result); - set_buffer_delay(bh_result); - } + if (ret == 0) { + /* the block isn't allocated yet, let's reserve space */ + /* XXX: call reservation here */ + /* + * XXX: __block_prepare_write() unmaps passed block, + * is it OK? + */ + map_bh(bh_result, inode->i_sb, 0); + set_buffer_new(bh_result); + set_buffer_delay(bh_result); + } else if (ret > 0) { + bh_result->b_size = (ret << inode->i_blkbits); ret = 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html