It will be more efficient to execute quick endio process(eg. non-sync overwriting case) under irq process rather than starting a worker to do it. Add a flag to control DIO to be finished inline(under irq context), which can be used for non-sync overwriting case. Besides, skip invalidating pages if DIO is finished inline, which will keep the same logic with dio_bio_end_aio in non-sync overwriting case. Signed-off-by: Zhihao Cheng <chengzhihao1@xxxxxxxxxx> --- fs/iomap/direct-io.c | 10 ++++++++-- include/linux/iomap.h | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index bcd3f8cf5ea4..221715b38ce2 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -110,7 +110,8 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio) * ->end_io() when necessary, otherwise a racing buffer read would cache * zeros from unwritten extents. */ - if (!dio->error && dio->size && (dio->flags & IOMAP_DIO_WRITE)) + if (!dio->error && dio->size && (dio->flags & IOMAP_DIO_WRITE) && + !(dio->flags & IOMAP_DIO_INLINE_COMP)) kiocb_invalidate_post_direct_write(iocb, dio->size); inode_dio_end(file_inode(iocb->ki_filp)); @@ -122,8 +123,10 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio) * If this is a DSYNC write, make sure we push it to stable * storage now that we've written data. */ - if (dio->flags & IOMAP_DIO_NEED_SYNC) + if (dio->flags & IOMAP_DIO_NEED_SYNC) { + WARN_ON_ONCE(dio->flags & IOMAP_DIO_INLINE_COMP); ret = generic_write_sync(iocb, ret); + } if (ret > 0) ret += dio->done_before; } @@ -628,6 +631,9 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, */ if (!(iocb->ki_flags & IOCB_SYNC)) dio->flags |= IOMAP_DIO_WRITE_THROUGH; + } else if (dio_flags & IOMAP_DIO_MAY_INLINE_COMP) { + /* writes could complete inline */ + dio->flags |= IOMAP_DIO_INLINE_COMP; } /* diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 96dd0acbba44..f292b10028d0 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -382,6 +382,12 @@ struct iomap_dio_ops { */ #define IOMAP_DIO_PARTIAL (1 << 2) +/* + * DIO will be completed inline unless sync operation is needed after io is + * finished. + */ +#define IOMAP_DIO_MAY_INLINE_COMP (1 << 3) + ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, const struct iomap_ops *ops, const struct iomap_dio_ops *dops, unsigned int dio_flags, void *private, size_t done_before); -- 2.39.2