aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorJiaying Zhang <jiayingz@google.com>2010-03-04 16:14:02 -0500
committerTheodore Ts'o <tytso@mit.edu>2010-03-04 16:14:02 -0500
commit744692dc059845b2a3022119871846e74d4f6e11 (patch)
treeed246651aebcb8dae57de8c58dc20983064ee017 /fs/ext4/extents.c
parentc7064ef13b2181a489836349f9baf87df0dab28f (diff)
ext4: use ext4_get_block_write in buffer write
Allocate uninitialized extent before ext4 buffer write and convert the extent to initialized after io completes. The purpose is to make sure an extent can only be marked initialized after it has been written with new data so we can safely drop the i_mutex lock in ext4 DIO read without exposing stale data. This helps to improve multi-thread DIO read performance on high-speed disks. Skip the nobh and data=journal mount cases to make things simple for now. Signed-off-by: Jiaying Zhang <jiayingz@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 90ba8d9df69..c7f166ab50e 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1619,7 +1619,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
1619 BUG_ON(path[depth].p_hdr == NULL); 1619 BUG_ON(path[depth].p_hdr == NULL);
1620 1620
1621 /* try to insert block into found extent and return */ 1621 /* try to insert block into found extent and return */
1622 if (ex && (flag != EXT4_GET_BLOCKS_PRE_IO) 1622 if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)
1623 && ext4_can_extents_be_merged(inode, ex, newext)) { 1623 && ext4_can_extents_be_merged(inode, ex, newext)) {
1624 ext_debug("append [%d]%d block to %d:[%d]%d (from %llu)\n", 1624 ext_debug("append [%d]%d block to %d:[%d]%d (from %llu)\n",
1625 ext4_ext_is_uninitialized(newext), 1625 ext4_ext_is_uninitialized(newext),
@@ -1740,7 +1740,7 @@ has_space:
1740 1740
1741merge: 1741merge:
1742 /* try to merge extents to the right */ 1742 /* try to merge extents to the right */
1743 if (flag != EXT4_GET_BLOCKS_PRE_IO) 1743 if (!(flag & EXT4_GET_BLOCKS_PRE_IO))
1744 ext4_ext_try_to_merge(inode, path, nearex); 1744 ext4_ext_try_to_merge(inode, path, nearex);
1745 1745
1746 /* try to merge extents to the left */ 1746 /* try to merge extents to the left */
@@ -3065,7 +3065,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
3065 ext4_ext_show_leaf(inode, path); 3065 ext4_ext_show_leaf(inode, path);
3066 3066
3067 /* get_block() before submit the IO, split the extent */ 3067 /* get_block() before submit the IO, split the extent */
3068 if (flags == EXT4_GET_BLOCKS_PRE_IO) { 3068 if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
3069 ret = ext4_split_unwritten_extents(handle, 3069 ret = ext4_split_unwritten_extents(handle,
3070 inode, path, iblock, 3070 inode, path, iblock,
3071 max_blocks, flags); 3071 max_blocks, flags);
@@ -3078,10 +3078,12 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
3078 io->flag = EXT4_IO_UNWRITTEN; 3078 io->flag = EXT4_IO_UNWRITTEN;
3079 else 3079 else
3080 ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN); 3080 ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
3081 if (ext4_should_dioread_nolock(inode))
3082 set_buffer_uninit(bh_result);
3081 goto out; 3083 goto out;
3082 } 3084 }
3083 /* IO end_io complete, convert the filled extent to written */ 3085 /* IO end_io complete, convert the filled extent to written */
3084 if (flags == EXT4_GET_BLOCKS_CONVERT) { 3086 if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
3085 ret = ext4_convert_unwritten_extents_endio(handle, inode, 3087 ret = ext4_convert_unwritten_extents_endio(handle, inode,
3086 path); 3088 path);
3087 if (ret >= 0) 3089 if (ret >= 0)
@@ -3351,21 +3353,21 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
3351 if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){ 3353 if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
3352 ext4_ext_mark_uninitialized(&newex); 3354 ext4_ext_mark_uninitialized(&newex);
3353 /* 3355 /*
3354 * io_end structure was created for every async 3356 * io_end structure was created for every IO write to an
3355 * direct IO write to the middle of the file. 3357 * uninitialized extent. To avoid unecessary conversion,
3356 * To avoid unecessary convertion for every aio dio rewrite 3358 * here we flag the IO that really needs the conversion.
3357 * to the mid of file, here we flag the IO that is really
3358 * need the convertion.
3359 * For non asycn direct IO case, flag the inode state 3359 * For non asycn direct IO case, flag the inode state
3360 * that we need to perform convertion when IO is done. 3360 * that we need to perform convertion when IO is done.
3361 */ 3361 */
3362 if (flags == EXT4_GET_BLOCKS_PRE_IO) { 3362 if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
3363 if (io) 3363 if (io)
3364 io->flag = EXT4_IO_UNWRITTEN; 3364 io->flag = EXT4_IO_UNWRITTEN;
3365 else 3365 else
3366 ext4_set_inode_state(inode, 3366 ext4_set_inode_state(inode,
3367 EXT4_STATE_DIO_UNWRITTEN); 3367 EXT4_STATE_DIO_UNWRITTEN);
3368 } 3368 }
3369 if (ext4_should_dioread_nolock(inode))
3370 set_buffer_uninit(bh_result);
3369 } 3371 }
3370 3372
3371 if (unlikely(EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL)) { 3373 if (unlikely(EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL)) {