diff options
author | Jan Kara <jack@suse.cz> | 2013-06-04 14:27:38 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-06-04 14:27:38 -0400 |
commit | e83403959fddb6d90e8c5e54bbce3110d0c82165 (patch) | |
tree | e993e008bab6fee97a1c8389f6bfc7bb438f2b49 | |
parent | b0857d309faefaf5443752458e8af1a4b22b3e92 (diff) | |
download | talos-obmc-linux-e83403959fddb6d90e8c5e54bbce3110d0c82165.tar.gz talos-obmc-linux-e83403959fddb6d90e8c5e54bbce3110d0c82165.zip |
ext4: protect extent conversion after DIO with i_dio_count
Make sure extent conversion after DIO happens while i_dio_count is
still elevated so that inode_dio_wait() waits until extent conversion
is done. This removes the need for explicit waiting for extent
conversion in some cases.
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>
-rw-r--r-- | fs/ext4/inode.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 510dba785db4..eb4ddfeeeedc 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3036,11 +3036,18 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, BUG_ON(iocb->private == NULL); + /* + * Make all waiters for direct IO properly wait also for extent + * conversion. This also disallows race between truncate() and + * overwrite DIO as i_dio_count needs to be incremented under i_mutex. + */ + if (rw == WRITE) + atomic_inc(&inode->i_dio_count); + /* If we do a overwrite dio, i_mutex locking can be released */ overwrite = *((int *)iocb->private); if (overwrite) { - atomic_inc(&inode->i_dio_count); down_read(&EXT4_I(inode)->i_data_sem); mutex_unlock(&inode->i_mutex); } @@ -3143,9 +3150,10 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, } retake_lock: + if (rw == WRITE) + inode_dio_done(inode); /* take i_mutex locking again if we do a ovewrite dio */ if (overwrite) { - inode_dio_done(inode); up_read(&EXT4_I(inode)->i_data_sem); mutex_lock(&inode->i_mutex); } |