ext4: Update i_diskzie during writepage for delayed allocation.
RFC PATCH 1/1 ext4: Update i_diskzie during writepage for delayed allocation.
We need to update i_disksize after allocating blocks. writepages already does this. Update writepage to also update i_disksize.
--- fs/ext4/inode.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 39 insertions(+), 1 deletions(-)
fs/ext4/inode.c +39 -1
@@ -1488,6 +1488,44 @@ out:return ret; } +/* FIXME!! only support data=writeback mode */ +static int ext4_da_writepage (struct page *page, +struct writeback_control *wbc) +{ +struct inode *inode = page->mapping->host; +handle_t *handle =NULL ; +int ret =0 ; +int err; + +if (ext4_journal_current_handle ()) + goto out_fail; + + handle =ext4_journal_start (inode,ext4_writepage_trans_blocks (inode)); +if (IS_ERR (handle)) { + ret =PTR_ERR (handle); + goto out_fail; + } + +if (test_opt (inode->i_sb,NOBH ) &&ext4_should_writeback_data (inode)) + ret =nobh_writepage (page, ext4_get_block, wbc); +else + ret =block_write_full_page (page, ext4_get_block, wbc); + +if (!ret && inode->i_size >EXT4_I (inode)->i_disksize) { +EXT4_I (inode)->i_disksize = inode->i_size; +ext4_mark_inode_dirty (handle, inode); + } + + err =ext4_journal_stop (handle); +if (!ret) + ret = err; +return ret; + +out_fail: +redirty_page_for_writepage (wbc, page); +unlock_page (page); +return ret; +}static int ext4_da_writepages (struct address_space *mapping,struct writeback_control *wbc)
@@ -2015,7 +2053,7 @@ static const struct address_space_operations ext4_journalled_aops = {static const struct address_space_operations ext4_da_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, - .writepage = ext4_writeback_writepage, + .writepage = ext4_da_writepage, .writepages = ext4_da_writepages, .sync_page = block_sync_page, .write_begin = ext4_da_write_begin,
Signature · 1 line
1.5.5.rc0.16.g02b00.dirty
RFC PATCH 1/1 ext4: Return unwritten buffer head when trying to read from prealloc space.
ext4_ext_get_blocks returns number of blocks allocated with buffer head unmapped for a read from prealloc space. This is needed so that delayed allocation doesn't do block reservation for prealloc space since the blocks are already resevred on disk. Fix ext4_ext_get_blocks to not return greater than max_blocks and also mark the buffer head unwritten. Some code path tries to read the block if buffer_head is not new and no uptodate. Marking the buffer head unwritten avoid this reading.
--- fs/ext4/extents.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
fs/ext4/extents.c +13 -1
@@ -2600,8 +2600,20 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, }if (create ==EXT4_CREATE_UNINITIALIZED_EXT ) goto out; -if (!create) +if (!create) { +/* +* We have blocks reserved already. We +* return allocated blocks so that delalloc +* won't do block reservation for us. But +* the buffer head will be unmapped so that +* a read from the block return 0 +*/ +if (allocated > max_blocks) + allocated = max_blocks; +/* mark the buffer unwritten */ +__set_bit (BH_Unwritten, &bh_result->b_state); goto out2; + } ret = ext4_ext_convert_to_initialized(handle, inode, path, iblock,
Signature · 1 line
1.5.5.rc0.16.g02b00.dirty
Re: [RFC PATCH] ext4: Return unwritten buffer head when trying to read from prealloc space.
Quoted 8 lines · Aneesh Kumar K.V
ext4_ext_get_blocksreturns number of blocks allocated with buffer head unmapped for a read from prealloc space. This is needed so that delayed allocation doesn't do block reservation for prealloc space since the blocks are already resevred on disk. Fixext4_ext_get_blocksto not return greater thanmax_blocksand also mark the buffer head unwritten. Some code path tries to read the block ifbuffer_headis not new and no uptodate. Marking the buffer head unwritten avoid this reading.
Seems this patch fixes two bugs together, it would be nice to split to two as they cause two different problems.
To fix the bh->b_size warning solof founds for delayed allocation, I would say we need to fix it in ext4_get_blocks_handle() (for indirect files) and ext4_ext_get_blocks()(for extent files) both, not allowing returning b_size greater than what the caller asking for. Also, the patch below seems only address the preallocation map case, we need to fix in in general block lookup case.
Quoted 31 lines
Signed-off-by Aneesh Kumar K.V <[email protected]>--- fs/ext4/extents.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)fs/ext4/extents.c +13
-1@@ -2600,8 +2600,20 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, }if (create ==EXT4_CREATE_UNINITIALIZED_EXT ) goto out; -if (!create) +if (!create) { +/* +* We have blocks reserved already. We +* return allocated blocks so that delalloc +* won't do block reservation for us. But +* the buffer head will be unmapped so that +* a read from the block return 0 +*/ +if (allocated > max_blocks) + allocated = max_blocks; +/* mark the buffer unwritten */ +__set_bit (BH_Unwritten, &bh_result->b_state); goto out2; + } ret = ext4_ext_convert_to_initialized(handle, inode, path, iblock,
Re: [RFC PATCH] ext4: Return unwritten buffer head when trying to read from prealloc space.
Quoted 10 lines · Mingming Cao
Quoted 8 lines · Aneesh Kumar K.V
ext4_ext_get_blocksreturns number of blocks allocated with buffer head unmapped for a read from prealloc space. This is needed so that delayed allocation doesn't do block reservation for prealloc space since the blocks are already resevred on disk. Fixext4_ext_get_blocksto not return greater thanmax_blocksand also mark the buffer head unwritten. Some code path tries to read the block ifbuffer_headis not new and no uptodate. Marking the buffer head unwritten avoid this reading.
Quoted 2 lines
Seems this patch fixes two bugs together, it would be nice to split to two as they cause two different problems.
Split patches here.
http://www.radian.org/~kvaneesh/ext4/patches-to-patchqueue/
Quoted 8 lines
To fix the
bh->b_sizewarning solof founds for delayed allocation, I would say we need to fix it inext4_get_blocks_handle()(for indirect files) and ext4_ext_get_blocks()(for extent files) both, not allowing returningb_sizegreater than what the caller asking for. Also, the patch below seems only address the preallocation map case, we need to fix in in general block lookup case.
ext4_ext_get_blocks already make sure we doesn't return > max_blocks. for normal allocation.
2694 out:
2695 if (allocated > max_blocks)
2696 allocated = max_blocks;
-aneesh
Re: [RFC PATCH] ext4: Return unwritten buffer head when trying to read from prealloc space.
Quoted 11 lines · Aneesh Kumar K.V
Quoted 10 lines · Mingming Cao
Quoted 8 lines · Aneesh Kumar K.V
ext4_ext_get_blocksreturns number of blocks allocated with buffer head unmapped for a read from prealloc space. This is needed so that delayed allocation doesn't do block reservation for prealloc space since the blocks are already resevred on disk. Fixext4_ext_get_blocksto not return greater thanmax_blocksand also mark the buffer head unwritten. Some code path tries to read the block ifbuffer_headis not new and no uptodate. Marking the buffer head unwritten avoid this reading.
Quoted 7 lines
Quoted 2 lines
Seems this patch fixes two bugs together, it would be nice to split to two as they cause two different problems.
Split patches here.
I will pick them up in patch queue.
Quoted 9 lines
Quoted 8 lines
To fix the
bh->b_sizewarning solof founds for delayed allocation, I would say we need to fix it inext4_get_blocks_handle()(for indirect files) and ext4_ext_get_blocks()(for extent files) both, not allowing returningb_sizegreater than what the caller asking for. Also, the patch below seems only address the preallocation map case, we need to fix in in general block lookup case.
Quoted 7 lines
ext4_ext_get_blocksalready make sure we doesn't return >max_blocks. for normal allocation.2694 out:
2695 if (allocated >max_blocks)
2696 allocated =max_blocks;
Oh I see, I missed that.
Regards,
Mingming
Quoted 2 lines
-aneesh
Quoted 3 lines · Aneesh Kumar K.V
We need to update
i_disksizeafter allocating blocks. writepages already does this. Update writepage to also updatei_disksize.
I agree that we should update the i_disk size after the allocation, to avoid possible exposing stale data in case of fs crash happened after the metadata hit to disk but before data being written out.
Quoted 63 lines
Signed-off-by Aneesh Kumar K.V <[email protected]>--- fs/ext4/inode.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 39 insertions(+), 1 deletions(-)fs/ext4/inode.c +39
-1@@ -1488,6 +1488,44 @@ out:return ret; } +/* FIXME!! only support data=writeback mode */ +static int ext4_da_writepage (struct page *page, +struct writeback_control *wbc) +{ +struct inode *inode = page->mapping->host; +handle_t *handle =NULL ; +int ret =0 ; +int err; + +if (ext4_journal_current_handle ()) + goto out_fail; + + handle =ext4_journal_start (inode,ext4_writepage_trans_blocks (inode)); +if (IS_ERR (handle)) { + ret =PTR_ERR (handle); + goto out_fail; + } + +if (test_opt (inode->i_sb,NOBH ) &&ext4_should_writeback_data (inode)) + ret =nobh_writepage (page, ext4_get_block, wbc); +else + ret =block_write_full_page (page, ext4_get_block, wbc); + +if (!ret && inode->i_size >EXT4_I (inode)->i_disksize) { +EXT4_I (inode)->i_disksize = inode->i_size; +ext4_mark_inode_dirty (handle, inode); + } + + err =ext4_journal_stop (handle); +if (!ret) + ret = err; +return ret; + +out_fail: +redirty_page_for_writepage (wbc, page); +unlock_page (page); +return ret; +}static int ext4_da_writepages (struct address_space *mapping,struct writeback_control *wbc)@@ -2015,7 +2053,7 @@ static const struct address_space_operations ext4_journalled_aops = {static const struct address_space_operations ext4_da_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, - .writepage = ext4_writeback_writepage, + .writepage = ext4_da_writepage, .writepages = ext4_da_writepages, .sync_page = block_sync_page, .write_begin = ext4_da_write_begin,