Commit 69c499d1 authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: restructure ext4_ext_direct_IO()

Remove a level of indentation by moving the DIO read and extending
write case to the beginning of the file.  This results in no actual
programmatic changes to the file, but makes it easier to
read/understand.
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 4a092d73
...@@ -2927,10 +2927,10 @@ static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode) ...@@ -2927,10 +2927,10 @@ static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode)
* fall back to buffered IO. * fall back to buffered IO.
* *
* For holes, we fallocate those blocks, mark them as uninitialized * For holes, we fallocate those blocks, mark them as uninitialized
* If those blocks were preallocated, we mark sure they are splited, but * If those blocks were preallocated, we mark sure they are split, but
* still keep the range to write as uninitialized. * still keep the range to write as uninitialized.
* *
* The unwrritten extents will be converted to written when DIO is completed. * The unwritten extents will be converted to written when DIO is completed.
* For async direct IO, since the IO may still pending when return, we * For async direct IO, since the IO may still pending when return, we
* set up an end_io call back function, which will do the conversion * set up an end_io call back function, which will do the conversion
* when async direct IO completed. * when async direct IO completed.
...@@ -2948,12 +2948,14 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, ...@@ -2948,12 +2948,14 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode = file->f_mapping->host; struct inode *inode = file->f_mapping->host;
ssize_t ret; ssize_t ret;
size_t count = iov_length(iov, nr_segs); size_t count = iov_length(iov, nr_segs);
loff_t final_size = offset + count;
if (rw == WRITE && final_size <= inode->i_size) {
int overwrite = 0; int overwrite = 0;
get_block_t *get_block_func = NULL; get_block_t *get_block_func = NULL;
int dio_flags = 0; int dio_flags = 0;
loff_t final_size = offset + count;
/* Use the old path for reads and writes beyond i_size. */
if (rw != WRITE || final_size > inode->i_size)
return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
BUG_ON(iocb->private == NULL); BUG_ON(iocb->private == NULL);
...@@ -2969,28 +2971,26 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, ...@@ -2969,28 +2971,26 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
/* /*
* We could direct write to holes and fallocate. * We could direct write to holes and fallocate.
* *
* Allocated blocks to fill the hole are marked as uninitialized * Allocated blocks to fill the hole are marked as
* to prevent parallel buffered read to expose the stale data * uninitialized to prevent parallel buffered read to expose
* before DIO complete the data IO. * the stale data before DIO complete the data IO.
* *
* As to previously fallocated extents, ext4 get_block * As to previously fallocated extents, ext4 get_block will
* will just simply mark the buffer mapped but still * just simply mark the buffer mapped but still keep the
* keep the extents uninitialized. * extents uninitialized.
* *
* for non AIO case, we will convert those unwritten extents * For non AIO case, we will convert those unwritten extents
* to written after return back from blockdev_direct_IO. * to written after return back from blockdev_direct_IO.
* *
* for async DIO, the conversion needs to be defered when * For async DIO, the conversion needs to be deferred when the
* the IO is completed. The ext4 end_io callback function * IO is completed. The ext4 end_io callback function will be
* will be called to take care of the conversion work. * called to take care of the conversion work. Here for async
* Here for async case, we allocate an io_end structure to * case, we allocate an io_end structure to hook to the iocb.
* hook to the iocb.
*/ */
iocb->private = NULL; iocb->private = NULL;
ext4_inode_aio_set(inode, NULL); ext4_inode_aio_set(inode, NULL);
if (!is_sync_kiocb(iocb)) { if (!is_sync_kiocb(iocb)) {
ext4_io_end_t *io_end = ext4_io_end_t *io_end = ext4_init_io_end(inode, GFP_NOFS);
ext4_init_io_end(inode, GFP_NOFS);
if (!io_end) { if (!io_end) {
ret = -ENOMEM; ret = -ENOMEM;
goto retake_lock; goto retake_lock;
...@@ -2998,11 +2998,10 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, ...@@ -2998,11 +2998,10 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
io_end->flag |= EXT4_IO_END_DIRECT; io_end->flag |= EXT4_IO_END_DIRECT;
iocb->private = io_end; iocb->private = io_end;
/* /*
* we save the io structure for current async * we save the io structure for current async direct
* direct IO, so that later ext4_map_blocks() * IO, so that later ext4_map_blocks() could flag the
* could flag the io structure whether there * io structure whether there is a unwritten extents
* is a unwritten extents needs to be converted * needs to be converted when IO is completed.
* when IO is completed.
*/ */
ext4_inode_aio_set(inode, io_end); ext4_inode_aio_set(inode, io_end);
} }
...@@ -3024,18 +3023,18 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, ...@@ -3024,18 +3023,18 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
if (iocb->private) if (iocb->private)
ext4_inode_aio_set(inode, NULL); ext4_inode_aio_set(inode, NULL);
/* /*
* The io_end structure takes a reference to the inode, * The io_end structure takes a reference to the inode, that
* that structure needs to be destroyed and the * structure needs to be destroyed and the reference to the
* reference to the inode need to be dropped, when IO is * inode need to be dropped, when IO is complete, even with 0
* complete, even with 0 byte write, or failed. * byte write, or failed.
* *
* In the successful AIO DIO case, the io_end structure will be * In the successful AIO DIO case, the io_end structure will
* desctroyed and the reference to the inode will be dropped * be destroyed and the reference to the inode will be dropped
* after the end_io call back function is called. * after the end_io call back function is called.
* *
* In the case there is 0 byte write, or error case, since * In the case there is 0 byte write, or error case, since VFS
* VFS direct IO won't invoke the end_io call back function, * direct IO won't invoke the end_io call back function, we
* we need to free the end_io structure here. * need to free the end_io structure here.
*/ */
if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) { if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
ext4_free_io_end(iocb->private); ext4_free_io_end(iocb->private);
...@@ -3054,7 +3053,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, ...@@ -3054,7 +3053,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN); ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
} }
retake_lock: retake_lock:
/* take i_mutex locking again if we do a ovewrite dio */ /* take i_mutex locking again if we do a ovewrite dio */
if (overwrite) { if (overwrite) {
inode_dio_done(inode); inode_dio_done(inode);
...@@ -3063,10 +3062,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, ...@@ -3063,10 +3062,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
} }
return ret; return ret;
}
/* for write the the end of file case, we fall back to old way */
return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
} }
static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment