aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2013-06-04 13:21:11 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-06-04 13:21:11 -0400
commit6b523df4fb5ae281ddbc817f40504b33e6226554 (patch)
treef129ccf336689296ff21e34ed86712b25d437a65 /fs/ext4/extents.c
parent3613d22807a2616e9346800bacd88aa8bbbefcd7 (diff)
ext4: use transaction reservation for extent conversion in ext4_end_io
Later we would like to clear PageWriteback bit only after extent conversion from unwritten to written extents is performed. However it is not possible to start a transaction after PageWriteback is set because that violates lock ordering (and is easy to deadlock). So we have to reserve a transaction before locking pages and sending them for IO and later we use the transaction for extent conversion from ext4_end_io(). Reviewed-by: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 94283d06cace..208f664f9ee0 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4566,10 +4566,9 @@ retry:
4566 * function, to convert the fallocated extents after IO is completed. 4566 * function, to convert the fallocated extents after IO is completed.
4567 * Returns 0 on success. 4567 * Returns 0 on success.
4568 */ 4568 */
4569int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, 4569int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
4570 ssize_t len) 4570 loff_t offset, ssize_t len)
4571{ 4571{
4572 handle_t *handle;
4573 unsigned int max_blocks; 4572 unsigned int max_blocks;
4574 int ret = 0; 4573 int ret = 0;
4575 int ret2 = 0; 4574 int ret2 = 0;
@@ -4584,16 +4583,32 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
4584 max_blocks = ((EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) - 4583 max_blocks = ((EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) -
4585 map.m_lblk); 4584 map.m_lblk);
4586 /* 4585 /*
4587 * credits to insert 1 extent into extent tree 4586 * This is somewhat ugly but the idea is clear: When transaction is
4587 * reserved, everything goes into it. Otherwise we rather start several
4588 * smaller transactions for conversion of each extent separately.
4588 */ 4589 */
4589 credits = ext4_chunk_trans_blocks(inode, max_blocks); 4590 if (handle) {
4591 handle = ext4_journal_start_reserved(handle,
4592 EXT4_HT_EXT_CONVERT);
4593 if (IS_ERR(handle))
4594 return PTR_ERR(handle);
4595 credits = 0;
4596 } else {
4597 /*
4598 * credits to insert 1 extent into extent tree
4599 */
4600 credits = ext4_chunk_trans_blocks(inode, max_blocks);
4601 }
4590 while (ret >= 0 && ret < max_blocks) { 4602 while (ret >= 0 && ret < max_blocks) {
4591 map.m_lblk += ret; 4603 map.m_lblk += ret;
4592 map.m_len = (max_blocks -= ret); 4604 map.m_len = (max_blocks -= ret);
4593 handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, credits); 4605 if (credits) {
4594 if (IS_ERR(handle)) { 4606 handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
4595 ret = PTR_ERR(handle); 4607 credits);
4596 break; 4608 if (IS_ERR(handle)) {
4609 ret = PTR_ERR(handle);
4610 break;
4611 }
4597 } 4612 }
4598 ret = ext4_map_blocks(handle, inode, &map, 4613 ret = ext4_map_blocks(handle, inode, &map,
4599 EXT4_GET_BLOCKS_IO_CONVERT_EXT); 4614 EXT4_GET_BLOCKS_IO_CONVERT_EXT);
@@ -4604,10 +4619,13 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
4604 inode->i_ino, map.m_lblk, 4619 inode->i_ino, map.m_lblk,
4605 map.m_len, ret); 4620 map.m_len, ret);
4606 ext4_mark_inode_dirty(handle, inode); 4621 ext4_mark_inode_dirty(handle, inode);
4607 ret2 = ext4_journal_stop(handle); 4622 if (credits)
4608 if (ret <= 0 || ret2 ) 4623 ret2 = ext4_journal_stop(handle);
4624 if (ret <= 0 || ret2)
4609 break; 4625 break;
4610 } 4626 }
4627 if (!credits)
4628 ret2 = ext4_journal_stop(handle);
4611 return ret > 0 ? ret2 : ret; 4629 return ret > 0 ? ret2 : ret;
4612} 4630}
4613 4631