From 45c46c6effd8273dc4ca52f32447f9f7103057b1 Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Mon, 2 Nov 2020 14:46:42 +0800 Subject: [PATCH] LU-14043 llite: allow DIO with unaligned IO count DIO only require user buffer page aligned and IO offset page aligned, it is ok that io count is not page aligned, remove this unnecessary limit so that we could use DIO with file not aligned with PAGE SIZE. Change-Id: Iaf1e224b3f180f91d1b54016c6e6b7adaf674bf8 Signed-off-by: Wang Shilong Reviewed-on: https://review.whamcloud.com/40392 Tested-by: jenkins Tested-by: Maloo Reviewed-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Reviewed-by: Oleg Drokin --- lustre/llite/rw26.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index 1415d79..1da442e 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -250,12 +250,12 @@ static ssize_t ll_get_user_pages(int rw, struct iov_iter *iter, /* iov_iter_alignment() is introduced in 3.16 similar to HAVE_DIO_ITER */ #if defined(HAVE_DIO_ITER) -static unsigned long ll_iov_iter_alignment(const struct iov_iter *i) +static unsigned long iov_iter_alignment_vfs(const struct iov_iter *i) { return iov_iter_alignment(i); } #else /* copied from alignment_iovec() */ -static unsigned long ll_iov_iter_alignment(const struct iov_iter *i) +static unsigned long iov_iter_alignment_vfs(const struct iov_iter *i) { const struct iovec *iov = i->iov; unsigned long res; @@ -282,6 +282,35 @@ static unsigned long ll_iov_iter_alignment(const struct iov_iter *i) } #endif +/* + * Lustre could relax a bit for alignment, io count is not + * necessary page alignment. + */ +static unsigned long ll_iov_iter_alignment(struct iov_iter *i) +{ + size_t orig_size = i->count; + size_t count = orig_size & ~PAGE_MASK; + unsigned long res; + + if (!count) + return iov_iter_alignment_vfs(i); + + if (orig_size > PAGE_SIZE) { + iov_iter_truncate(i, orig_size - count); + res = iov_iter_alignment_vfs(i); + iov_iter_reexpand(i, orig_size); + + return res; + } + + res = iov_iter_alignment_vfs(i); + /* start address is page aligned */ + if ((res & ~PAGE_MASK) == orig_size) + return PAGE_SIZE; + + return res; +} + /** direct IO pages */ struct ll_dio_pages { struct cl_dio_aio *ldp_aio; @@ -433,8 +462,8 @@ ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw) return 0; /* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */ - if ((file_offset & ~PAGE_MASK) || (count & ~PAGE_MASK)) - return -EINVAL; + if (file_offset & ~PAGE_MASK) + RETURN(-EINVAL); CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), size=%zd (max %lu), " "offset=%lld=%llx, pages %zd (max %lu)\n", @@ -444,7 +473,7 @@ ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw) /* Check that all user buffers are aligned as well */ if (ll_iov_iter_alignment(iter) & ~PAGE_MASK) - return -EINVAL; + RETURN(-EINVAL); lcc = ll_cl_find(file); if (lcc == NULL) -- 1.8.3.1