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 /fs/ext4/inode.c | |
parent | b0857d309faefaf5443752458e8af1a4b22b3e92 (diff) |
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>
Diffstat (limited to 'fs/ext4/inode.c')
-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, | |||
3036 | 3036 | ||
3037 | BUG_ON(iocb->private == NULL); | 3037 | BUG_ON(iocb->private == NULL); |
3038 | 3038 | ||
3039 | /* | ||
3040 | * Make all waiters for direct IO properly wait also for extent | ||
3041 | * conversion. This also disallows race between truncate() and | ||
3042 | * overwrite DIO as i_dio_count needs to be incremented under i_mutex. | ||
3043 | */ | ||
3044 | if (rw == WRITE) | ||
3045 | atomic_inc(&inode->i_dio_count); | ||
3046 | |||
3039 | /* If we do a overwrite dio, i_mutex locking can be released */ | 3047 | /* If we do a overwrite dio, i_mutex locking can be released */ |
3040 | overwrite = *((int *)iocb->private); | 3048 | overwrite = *((int *)iocb->private); |
3041 | 3049 | ||
3042 | if (overwrite) { | 3050 | if (overwrite) { |
3043 | atomic_inc(&inode->i_dio_count); | ||
3044 | down_read(&EXT4_I(inode)->i_data_sem); | 3051 | down_read(&EXT4_I(inode)->i_data_sem); |
3045 | mutex_unlock(&inode->i_mutex); | 3052 | mutex_unlock(&inode->i_mutex); |
3046 | } | 3053 | } |
@@ -3143,9 +3150,10 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, | |||
3143 | } | 3150 | } |
3144 | 3151 | ||
3145 | retake_lock: | 3152 | retake_lock: |
3153 | if (rw == WRITE) | ||
3154 | inode_dio_done(inode); | ||
3146 | /* take i_mutex locking again if we do a ovewrite dio */ | 3155 | /* take i_mutex locking again if we do a ovewrite dio */ |
3147 | if (overwrite) { | 3156 | if (overwrite) { |
3148 | inode_dio_done(inode); | ||
3149 | up_read(&EXT4_I(inode)->i_data_sem); | 3157 | up_read(&EXT4_I(inode)->i_data_sem); |
3150 | mutex_lock(&inode->i_mutex); | 3158 | mutex_lock(&inode->i_mutex); |
3151 | } | 3159 | } |