From d011e65a8936bc105e19b3fad64bfdece455de61 Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Tue, 7 Feb 2023 23:09:17 -0500 Subject: [PATCH] LU-13805 llite: Add copy of iovec to sub-dio It's very useful to move some of the direct I/O processing from the main thread to the ptlrpc threads. This is done by associating the processing with each sub DIO, or DIO 'chunk'. This requires a local copy of the iovec in each chunk, because we: A) need the chunk-current state of the iovec (as we move along the iovec as chunks are created) B) some operations will modify the iovec, and so to do them from multiple ptlrpc threads, each needs to work on a separate copy of the iovec. This will be used by copy_page_to_iter in completing unaligned DIO reads. This has been split out from the main unaligned DIO patch for simplification. Signed-off-by: Patrick Farrell Change-Id: I5645e904b6f9423eafc69cc0f59349cb3dcb9920 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49940 Reviewed-by: Zhenyu Xu Reviewed-by: Oleg Drokin Reviewed-by: Qian Yingjin Tested-by: Maloo Tested-by: jenkins --- lustre/include/cl_object.h | 4 +++- lustre/llite/rw26.c | 3 ++- lustre/obdclass/cl_io.c | 29 +++++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lustre/include/cl_object.h b/lustre/include/cl_object.h index da23150..845944b 100644 --- a/lustre/include/cl_object.h +++ b/lustre/include/cl_object.h @@ -2513,7 +2513,8 @@ int cl_sync_io_wait_recycle(const struct lu_env *env, struct cl_sync_io *anchor, long timeout, int ioret); struct cl_dio_aio *cl_dio_aio_alloc(struct kiocb *iocb, struct cl_object *obj, bool is_aio); -struct cl_sub_dio *cl_sub_dio_alloc(struct cl_dio_aio *ll_aio, bool write, +struct cl_sub_dio *cl_sub_dio_alloc(struct cl_dio_aio *ll_aio, + struct iov_iter *iter, bool write, bool sync); void cl_dio_aio_free(const struct lu_env *env, struct cl_dio_aio *aio); void cl_sub_dio_free(struct cl_sub_dio *sdio); @@ -2573,6 +2574,7 @@ struct cl_sub_dio { ssize_t csd_bytes; struct cl_dio_aio *csd_ll_aio; struct ll_dio_pages csd_dio_pages; + struct iov_iter csd_iter; unsigned csd_creator_free:1, csd_write:1; }; diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index aad6b20..3a5c85d 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -545,7 +545,8 @@ ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw) * otherwise it is freed on the final call to cl_sync_io_note * (either in this function or from a ptlrpcd daemon) */ - sdio = cl_sub_dio_alloc(ll_dio_aio, rw == WRITE, sync_submit); + sdio = cl_sub_dio_alloc(ll_dio_aio, iter, rw == WRITE, + sync_submit); if (!sdio) GOTO(out, result = -ENOMEM); diff --git a/lustre/obdclass/cl_io.c b/lustre/obdclass/cl_io.c index d4d85fa..8d7b6f2 100644 --- a/lustre/obdclass/cl_io.c +++ b/lustre/obdclass/cl_io.c @@ -1241,7 +1241,8 @@ struct cl_dio_aio *cl_dio_aio_alloc(struct kiocb *iocb, struct cl_object *obj, } EXPORT_SYMBOL(cl_dio_aio_alloc); -struct cl_sub_dio *cl_sub_dio_alloc(struct cl_dio_aio *ll_aio, bool write, +struct cl_sub_dio *cl_sub_dio_alloc(struct cl_dio_aio *ll_aio, + struct iov_iter *iter, bool write, bool sync) { struct cl_sub_dio *sdio; @@ -1260,7 +1261,26 @@ struct cl_sub_dio *cl_sub_dio_alloc(struct cl_dio_aio *ll_aio, bool write, atomic_add(1, &ll_aio->cda_sync.csi_sync_nr); sdio->csd_creator_free = sync; sdio->csd_write = write; + + /* we need to make a copy of the user iovec at this point in + * time so we: + * A) have the correct state of the iovec for this chunk of I/O + * B) have a chunk-local copy; some of the things we want to + * do to the iovec modify it, so to process each chunk from a + * separate thread requires a local copy of the iovec + */ + memcpy(&sdio->csd_iter, iter, + sizeof(struct iov_iter)); + OBD_ALLOC_PTR(sdio->csd_iter.iov); + if (sdio->csd_iter.iov == NULL) { + cl_sub_dio_free(sdio); + sdio = NULL; + goto out; + } + memcpy((void *) sdio->csd_iter.iov, iter->iov, + sizeof(struct iovec)); } +out: return sdio; } EXPORT_SYMBOL(cl_sub_dio_alloc); @@ -1276,8 +1296,13 @@ EXPORT_SYMBOL(cl_dio_aio_free); void cl_sub_dio_free(struct cl_sub_dio *sdio) { - if (sdio) + if (sdio) { + void *tmp = (void *) sdio->csd_iter.iov; + + if (tmp) + OBD_FREE(tmp, sizeof(struct iovec)); OBD_SLAB_FREE_PTR(sdio, cl_sub_dio_kmem); + } } EXPORT_SYMBOL(cl_sub_dio_free); -- 1.8.3.1