Skip to content
Permalink
Browse files
iomap: Pass original DIO size to completion handler
When extending a file with direct IO write, ext4 needs to know whether IO
has succeeded for the whole range that was prepared for it (the common fast
path). In that case we can piggy back the orphan list update with the
inode size update. In case write was actually shorter than originally
intended, we must leave inode on the orphan list until we cleanup blocks
beyond i_size. So provide the original IO size to the direct IO ->end_io
handler.

Signed-off-by: Jan Kara <jack@suse.cz>
  • Loading branch information
jankara authored and intel-lab-lkp committed Apr 12, 2021
1 parent fcdf3c3 commit 0d289243d061378ac42188ff5079287885575bb3
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 5 deletions.
@@ -369,7 +369,8 @@ static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset,
}

static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
int error, unsigned int flags)
ssize_t orig_size, int error,
unsigned int flags)
{
loff_t offset = iocb->ki_pos;
struct inode *inode = file_inode(iocb->ki_filp);
@@ -28,6 +28,7 @@ struct iomap_dio {
const struct iomap_dio_ops *dops;
loff_t i_size;
loff_t size;
loff_t orig_size;
atomic_t ref;
unsigned flags;
int error;
@@ -85,7 +86,8 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio)
ssize_t ret = dio->error;

if (dops && dops->end_io)
ret = dops->end_io(iocb, dio->size, ret, dio->flags);
ret = dops->end_io(iocb, dio->size, dio->orig_size, ret,
dio->flags);

if (likely(!ret)) {
ret = dio->size;
@@ -473,6 +475,7 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
dio->iocb = iocb;
atomic_set(&dio->ref, 1);
dio->size = 0;
dio->orig_size = count;
dio->i_size = i_size_read(inode);
dio->dops = dops;
dio->error = 0;
@@ -442,6 +442,7 @@ static int
xfs_dio_write_end_io(
struct kiocb *iocb,
ssize_t size,
ssize_t orig_size,
int error,
unsigned flags)
{
@@ -652,7 +652,8 @@ static loff_t zonefs_file_llseek(struct file *file, loff_t offset, int whence)
}

static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size,
int error, unsigned int flags)
ssize_t orig_size, int error,
unsigned int flags)
{
struct inode *inode = file_inode(iocb->ki_filp);
struct zonefs_inode_info *zi = ZONEFS_I(inode);
@@ -252,8 +252,8 @@ int iomap_writepages(struct address_space *mapping,
#define IOMAP_DIO_COW (1 << 1) /* covers COW extent(s) */

struct iomap_dio_ops {
int (*end_io)(struct kiocb *iocb, ssize_t size, int error,
unsigned flags);
int (*end_io)(struct kiocb *iocb, ssize_t size, ssize_t orig_size,
int error, unsigned flags);
blk_qc_t (*submit_io)(struct inode *inode, struct iomap *iomap,
struct bio *bio, loff_t file_offset);
};

0 comments on commit 0d28924

Please sign in to comment.