aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2016-02-28 16:36:38 -0500
committerDave Chinner <david@fromorbit.com>2016-02-28 16:36:38 -0500
commit74c66bcb7eda551f3b8588659c58fe29184af903 (patch)
tree0d1f5bc2cb487890f23caf622138135c54dfd4a5 /fs/ext4/inode.c
parentc19b104a67b3bb1ac48275a8a1c9df666e676c25 (diff)
ext4: Fix data exposure after failed AIO DIO
When AIO DIO fails e.g. due to IO error, we must not convert unwritten extents as that will expose uninitialized data. Handle this case by clearing unwritten flag from io_end in case of error and thus preventing extent conversion. Signed-off-by: Jan Kara <jack@suse.cz> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c21
1 files changed, 8 insertions, 13 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 9db04dd9b88a..2b98171a9432 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3166,9 +3166,6 @@ static int ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3166{ 3166{
3167 ext4_io_end_t *io_end = iocb->private; 3167 ext4_io_end_t *io_end = iocb->private;
3168 3168
3169 if (size <= 0)
3170 return 0;
3171
3172 /* if not async direct IO just return */ 3169 /* if not async direct IO just return */
3173 if (!io_end) 3170 if (!io_end)
3174 return 0; 3171 return 0;
@@ -3179,6 +3176,14 @@ static int ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
3179 size); 3176 size);
3180 3177
3181 iocb->private = NULL; 3178 iocb->private = NULL;
3179 /*
3180 * Error during AIO DIO. We cannot convert unwritten extents as the
3181 * data was not written. Just clear the unwritten flag and drop io_end.
3182 */
3183 if (size <= 0) {
3184 ext4_clear_io_unwritten_flag(io_end);
3185 size = 0;
3186 }
3182 io_end->offset = offset; 3187 io_end->offset = offset;
3183 io_end->size = size; 3188 io_end->size = size;
3184 ext4_put_io_end(io_end); 3189 ext4_put_io_end(io_end);
@@ -3306,16 +3311,6 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
3306 if (io_end) { 3311 if (io_end) {
3307 ext4_inode_aio_set(inode, NULL); 3312 ext4_inode_aio_set(inode, NULL);
3308 ext4_put_io_end(io_end); 3313 ext4_put_io_end(io_end);
3309 /*
3310 * When no IO was submitted ext4_end_io_dio() was not
3311 * called so we have to put iocb's reference.
3312 */
3313 if (ret <= 0 && ret != -EIOCBQUEUED && iocb->private) {
3314 WARN_ON(iocb->private != io_end);
3315 WARN_ON(io_end->flag & EXT4_IO_END_UNWRITTEN);
3316 ext4_put_io_end(io_end);
3317 iocb->private = NULL;
3318 }
3319 } 3314 }
3320 if (ret > 0 && !overwrite && ext4_test_inode_state(inode, 3315 if (ret > 0 && !overwrite && ext4_test_inode_state(inode,
3321 EXT4_STATE_DIO_UNWRITTEN)) { 3316 EXT4_STATE_DIO_UNWRITTEN)) {