diff options
author | Tao Ma <boyu.mt@taobao.com> | 2011-10-26 11:08:39 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-10-26 11:08:39 -0400 |
commit | b3ff05690845911cc40387176f0bc5a7af9ef3ff (patch) | |
tree | 9ed6230ae4616d67d85aed9e9b8dc6477642312c /fs/ext4 | |
parent | 0a10da73e1fa6fb9b45f1166011ff3b04c27c010 (diff) |
ext4: don't check io->flag when setting EXT4_STATE_DIO_UNWRITTEN inode state
When we want to convert the unitialized extent in direct write, we can
either do it in ext4_end_io_nolock(AIO case) or in
ext4_ext_direct_IO(non AIO case) and EXT4_I(inode)->cur_aio_dio is a
guard for ext4_ext_map_blocks to find the right case. In e9e3bcecf,
we mistakenly change it by:
- if (io)
+ if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) {
io->flag = EXT4_IO_END_UNWRITTEN;
- else
+ atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
+ } else
ext4_set_inode_state(inode,
EXT4_STATE_DIO_UNWRITTEN);
So now if we map 2 blocks, and the first one set the
EXT_IO_END_UNWRITTEN, the 2nd mapping will set inode state because of
the check for the flag. This is wrong.
Cc: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/extents.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 797b63b59740..c2ac06cb2d46 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -3390,9 +3390,11 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
3390 | * that this IO needs to conversion to written when IO is | 3390 | * that this IO needs to conversion to written when IO is |
3391 | * completed | 3391 | * completed |
3392 | */ | 3392 | */ |
3393 | if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) { | 3393 | if (io) { |
3394 | io->flag = EXT4_IO_END_UNWRITTEN; | 3394 | if (!(io->flag & EXT4_IO_END_UNWRITTEN)) { |
3395 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); | 3395 | io->flag = EXT4_IO_END_UNWRITTEN; |
3396 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); | ||
3397 | } | ||
3396 | } else | 3398 | } else |
3397 | ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN); | 3399 | ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN); |
3398 | if (ext4_should_dioread_nolock(inode)) | 3400 | if (ext4_should_dioread_nolock(inode)) |
@@ -3946,9 +3948,11 @@ got_allocated_blocks: | |||
3946 | * that we need to perform conversion when IO is done. | 3948 | * that we need to perform conversion when IO is done. |
3947 | */ | 3949 | */ |
3948 | if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { | 3950 | if ((flags & EXT4_GET_BLOCKS_PRE_IO)) { |
3949 | if (io && !(io->flag & EXT4_IO_END_UNWRITTEN)) { | 3951 | if (io) { |
3950 | io->flag = EXT4_IO_END_UNWRITTEN; | 3952 | if (!(io->flag & EXT4_IO_END_UNWRITTEN)) { |
3951 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); | 3953 | io->flag = EXT4_IO_END_UNWRITTEN; |
3954 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); | ||
3955 | } | ||
3952 | } else | 3956 | } else |
3953 | ext4_set_inode_state(inode, | 3957 | ext4_set_inode_state(inode, |
3954 | EXT4_STATE_DIO_UNWRITTEN); | 3958 | EXT4_STATE_DIO_UNWRITTEN); |