| From 0c51dd21fdd04586411a3653caee9c73e3468ee5 Mon Sep 17 00:00:00 2001 |
| From: Mingming <cmm@us.ibm.com> |
| Date: Tue, 10 Nov 2009 10:48:04 -0500 |
| Subject: [PATCH 54/85] ext4: skip conversion of uninit extents after direct IO if there isn't any |
| |
| (cherry picked from commit 5f5249507e4b5c4fc0f9c93f33d133d8c95f47e1) |
| |
| At the end of direct I/O operation, ext4_ext_direct_IO() always called |
| ext4_convert_unwritten_extents(), regardless of whether there were any |
| unwritten extents involved in the I/O or not. |
| |
| This commit adds a state flag so that ext4_ext_direct_IO() only calls |
| ext4_convert_unwritten_extents() when necessary. |
| |
| Signed-off-by: Mingming Cao <cmm@us.ibm.com> |
| Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| fs/ext4/ext4.h | 1 + |
| fs/ext4/extents.c | 22 +++++++++++++++++----- |
| fs/ext4/inode.c | 4 +++- |
| 3 files changed, 21 insertions(+), 6 deletions(-) |
| |
| --- a/fs/ext4/ext4.h |
| +++ b/fs/ext4/ext4.h |
| @@ -318,6 +318,7 @@ static inline __u32 ext4_mask_flags(umod |
| #define EXT4_STATE_NO_EXPAND 0x00000008 /* No space for expansion */ |
| #define EXT4_STATE_DA_ALLOC_CLOSE 0x00000010 /* Alloc DA blks on close */ |
| #define EXT4_STATE_EXT_MIGRATE 0x00000020 /* Inode is migrating */ |
| +#define EXT4_STATE_DIO_UNWRITTEN 0x00000040 /* need convert on dio done*/ |
| |
| /* Used to pass group descriptor data when online resize is done */ |
| struct ext4_new_group_input { |
| --- a/fs/ext4/extents.c |
| +++ b/fs/ext4/extents.c |
| @@ -3025,12 +3025,18 @@ ext4_ext_handle_uninitialized_extents(ha |
| ret = ext4_split_unwritten_extents(handle, |
| inode, path, iblock, |
| max_blocks, flags); |
| - /* flag the io_end struct that we need convert when IO done */ |
| + /* |
| + * Flag the inode(non aio case) or end_io struct (aio case) |
| + * that this IO needs to convertion to written when IO is |
| + * completed |
| + */ |
| if (io) |
| io->flag = DIO_AIO_UNWRITTEN; |
| + else |
| + EXT4_I(inode)->i_state |= EXT4_STATE_DIO_UNWRITTEN; |
| goto out; |
| } |
| - /* DIO end_io complete, convert the filled extent to written */ |
| + /* async DIO end_io complete, convert the filled extent to written */ |
| if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) { |
| ret = ext4_convert_unwritten_extents_dio(handle, inode, |
| path); |
| @@ -3272,10 +3278,16 @@ int ext4_ext_get_blocks(handle_t *handle |
| * To avoid unecessary convertion for every aio dio rewrite |
| * to the mid of file, here we flag the IO that is really |
| * need the convertion. |
| - * |
| + * For non asycn direct IO case, flag the inode state |
| + * that we need to perform convertion when IO is done. |
| */ |
| - if (io && flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT) |
| - io->flag = DIO_AIO_UNWRITTEN; |
| + if (flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT) { |
| + if (io) |
| + io->flag = DIO_AIO_UNWRITTEN; |
| + else |
| + EXT4_I(inode)->i_state |= |
| + EXT4_STATE_DIO_UNWRITTEN;; |
| + } |
| } |
| err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); |
| if (err) { |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -3766,7 +3766,8 @@ static ssize_t ext4_ext_direct_IO(int rw |
| if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) { |
| ext4_free_io_end(iocb->private); |
| iocb->private = NULL; |
| - } else if (ret > 0) { |
| + } else if (ret > 0 && (EXT4_I(inode)->i_state & |
| + EXT4_STATE_DIO_UNWRITTEN)) { |
| int err; |
| /* |
| * for non AIO case, since the IO is already |
| @@ -3776,6 +3777,7 @@ static ssize_t ext4_ext_direct_IO(int rw |
| offset, ret); |
| if (err < 0) |
| ret = err; |
| + EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN; |
| } |
| return ret; |
| } |