Whamcloud - gitweb
LU-17993 llite: add further check for user buffer 04/56404/8
authorShaun Tancheff <shaun.tancheff@hpe.com>
Tue, 24 Sep 2024 17:27:01 +0000 (00:27 +0700)
committerOleg Drokin <green@whamcloud.com>
Fri, 27 Sep 2024 23:55:43 +0000 (23:55 +0000)
The alignment check in ll_iov_iter_alignment for the user buffer
could be wrong if the IO count is less than PAGE_SIZE, add more
checks for it.

Linux commit v5.19-rc4-8-gcfa320f72882
   iov: introduce iov_iter_aligned

Added iov_iter_is_aligned which can do the additional checking,
provide an equivalent for older kernels.

Test-Parameters: testlist=sanity clientarch=aarch64 clientdistro=el9.3   serverdistro=el8.9 env=ONLY="119",SANITY_EXCEPT="119i",ONLY_REPEAT=50
Test-Parameters: testlist=sanity clientarch=ppc64le clientdistro=el8.9   serverdistro=el8.9 env=ONLY="119",SANITY_EXCEPT="119i",ONLY_REPEAT=50
Test-Parameters: testlist=sanity clientarch=aarch64 clientdistro=el9.3   serverversion=2.15.4 serverdistro=el8.9   env=ONLY="119",SANITY_EXCEPT="119i",ONLY_REPEAT=50
Test-Parameters: testlist=sanity clientarch=aarch64 clientdistro=el9.3   env=ONLY="119",SANITY_EXCEPT="119i",ONLY_REPEAT=50
Test-Parameters: testlist=sanity clientarch=x86_64 clientdistro=el8.10   env=ONLY="119",SANITY_EXCEPT="119i",ONLY_REPEAT=50
Test-Parameters: testlist=sanity clientarch=x86_64 clientdistro=el9.4   env=ONLY="119",SANITY_EXCEPT="119i",ONLY_REPEAT=50
Test-Parameters: testlist=sanity serverversion=2.15.4 serverdistro=el8.9   serverdistro=el8.9 env=ONLY="119",SANITY_EXCEPT="119i",ONLY_REPEAT=50
Signed-off-by: Hongchao Zhang <hongchao@whamcloud.com>
Signed-off-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Change-Id: I640dc417e52cc5497e5dd898ea3018f990da3fda
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56404
Reviewed-by: Patrick Farrell <patrick.farrell@oracle.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
libcfs/include/libcfs/linux/linux-misc.h
lustre/autoconf/lustre-core.m4
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/rw26.c
lustre/tests/sanity.sh

index be811dd..bff9e05 100644 (file)
 #ifndef HAVE_USER_BACKED_ITER
 #define iter_is_ubuf(iter)             0
 #define user_backed_iter(iter)         iter_is_iovec(iter)
-#endif
+#endif /* HAVE_USER_BACKED_ITER */
+
+#ifndef HAVE_IOV_ITER_IS_ALIGNED
+static inline bool iov_iter_aligned_iovec(const struct iov_iter *i,
+                                         unsigned addr_mask, unsigned len_mask)
+{
+       const struct iovec *iov = iter_iov(i);
+       size_t size = i->count;
+       size_t skip = i->iov_offset;
+
+       do {
+               size_t len = iov->iov_len - skip;
+
+               if (len > size)
+                       len = size;
+               if (len & len_mask)
+                       return false;
+               if ((unsigned long)(iov->iov_base + skip) & addr_mask)
+                       return false;
+
+               iov++;
+               size -= len;
+               skip = 0;
+       } while (size);
+
+       return true;
+}
+
+static inline bool iov_iter_is_aligned(const struct iov_iter *i,
+                                      unsigned addr_mask, unsigned len_mask)
+{
+       if (likely(iter_is_ubuf(i))) {
+               if (i->count & len_mask)
+                       return false;
+               if ((unsigned long)(iter_iov(i) + i->iov_offset) & addr_mask)
+                       return false;
+               return true;
+       }
+       if (likely(iter_is_iovec(i) || iov_iter_is_kvec(i)))
+               return iov_iter_aligned_iovec(i, addr_mask, len_mask);
+
+       return true;
+}
+#endif /* HAVE_IOV_ITER_IS_ALIGNED */
 
 int cfs_kernel_write(struct file *filp, const void *buf, size_t count,
                     loff_t *pos);
index 49ba06b..46286a0 100644 (file)
@@ -3960,6 +3960,30 @@ AC_DEFUN([LC_HAVE_USER_BACKED_ITER], [
 ]) # LC_HAVE_USER_BACKED_ITER
 
 #
+# LC_HAVE_IOV_ITER_IS_ALIGNED
+#
+# Linux commit v5.19-rc4-8-gcfa320f72882
+#    iov: introduce iov_iter_aligned
+#
+AC_DEFUN([LC_SRC_HAVE_IOV_ITER_IS_ALIGNED], [
+       LB2_LINUX_TEST_SRC([iov_iter_is_aligned], [
+               #include <linux/uio.h>
+       ],[
+               struct iov_iter *iter = NULL;
+               bool result __attribute__ ((unused));
+
+               result = iov_iter_is_aligned(iter, ~PAGE_MASK, ~PAGE_MASK);
+       ],[-Werror])
+])
+AC_DEFUN([LC_HAVE_IOV_ITER_IS_ALIGNED], [
+       LB2_MSG_LINUX_TEST_RESULT([if iov_iter_is_aligned() is available],
+       [iov_iter_is_aligned], [
+               AC_DEFINE(HAVE_IOV_ITER_IS_ALIGNED, 1,
+                       [iov_iter_is_aligned() is available])
+       ])
+]) # LC_HAVE_IOV_ITER_IS_ALIGNED
+
+#
 # LC_HAVE_GET_RANDOM_U32_AND_U64
 #
 # Linux commit v4.10-rc3-6-gc440408cf690
@@ -4893,7 +4917,7 @@ AC_DEFUN([LC_PROG_LINUX_SRC], [
        LC_SRC_HAVE_VFS_SETXATTR_NON_CONST_VALUE
        LC_SRC_HAVE_IOV_ITER_GET_PAGES_ALLOC2
        LC_SRC_HAVE_USER_BACKED_ITER
-       LC_HAVE_ADD_TO_PAGE_CACHE_LOCKED
+       LC_SRC_HAVE_IOV_ITER_IS_ALIGNED
 
        # 6.1
        LC_SRC_HAVE_GET_RANDOM_U32_AND_U64
@@ -5208,6 +5232,7 @@ AC_DEFUN([LC_PROG_LINUX_RESULTS], [
        LC_HAVE_VFS_SETXATTR_NON_CONST_VALUE
        LC_HAVE_IOV_ITER_GET_PAGES_ALLOC2
        LC_HAVE_USER_BACKED_ITER
+       LC_HAVE_IOV_ITER_IS_ALIGNED
 
        # 6.1
        LC_HAVE_GET_RANDOM_U32_AND_U64
@@ -5288,6 +5313,9 @@ AC_DEFUN([LC_PROG_LINUX], [
        # 5.2 - Check export
        LC_ACCOUNT_PAGE_DIRTIED
 
+       # 6.0 - Check export
+       LC_HAVE_ADD_TO_PAGE_CACHE_LOCKED
+
 ]) # LC_PROG_LINUX
 
 #
index 98c498f..49d938a 100644 (file)
@@ -2259,10 +2259,8 @@ static bool is_unaligned_directio(struct kiocb *iocb, struct iov_iter *iter,
        if (direct_io) {
                if (iocb->ki_pos & ~PAGE_MASK)
                        unaligned = true;
-               else if (iov_iter_count(iter) & ~PAGE_MASK)
-                       unaligned = true;
-               else if (ll_iov_iter_alignment(iter) & ~PAGE_MASK)
-                       unaligned = true;
+               else
+                       unaligned = ll_iov_iter_is_unaligned(iter);
        }
        return unaligned;
 #else
index c354030..bafc418 100644 (file)
@@ -2150,6 +2150,6 @@ bool ll_foreign_is_removable(struct dentry *dentry, bool unset);
 
 int ll_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 
-unsigned long ll_iov_iter_alignment(struct iov_iter *i);
+bool ll_iov_iter_is_unaligned(struct iov_iter *i);
 
 #endif /* LLITE_INTERNAL_H */
index 6b0d341..4f83756 100644 (file)
@@ -338,29 +338,35 @@ static unsigned long iov_iter_alignment_vfs(const struct iov_iter *i)
  * Lustre could relax a bit for alignment, io count is not
  * necessary page alignment.
  */
-unsigned long ll_iov_iter_alignment(struct iov_iter *i)
+bool ll_iov_iter_is_unaligned(struct iov_iter *i)
 {
        size_t orig_size = i->count;
        size_t count = orig_size & ~PAGE_MASK;
        unsigned long res;
 
+       if (iov_iter_count(i) & ~PAGE_MASK)
+               return true;
+
+       if (!iov_iter_is_aligned(i, ~PAGE_MASK, 0))
+               return true;
+
        if (!count)
-               return iov_iter_alignment_vfs(i);
+               return iov_iter_alignment_vfs(i) & ~PAGE_MASK;
 
        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;
+               return res & ~PAGE_MASK;
        }
 
        res = iov_iter_alignment_vfs(i);
        /* start address is page aligned */
        if ((res & ~PAGE_MASK) == orig_size)
-               return PAGE_SIZE;
+               return false;
 
-       return res;
+       return res & ~PAGE_MASK;
 }
 
 static int
@@ -487,7 +493,7 @@ ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw)
        ssize_t tot_bytes = 0, result = 0;
        loff_t file_offset = iocb->ki_pos;
        bool sync_submit = false;
-       bool unaligned = false;
+       bool unaligned;
        struct vvp_io *vio;
        ssize_t rc2;
 
@@ -495,13 +501,8 @@ ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw)
 
        if (file_offset & ~PAGE_MASK)
                unaligned = true;
-
-       if ((file_offset + count < i_size_read(inode)) && (count & ~PAGE_MASK))
-               unaligned = true;
-
-       /* Check that all user buffers are aligned as well */
-       if (ll_iov_iter_alignment(iter) & ~PAGE_MASK)
-               unaligned = true;
+       else
+               unaligned = ll_iov_iter_is_unaligned(iter);
 
        lcc = ll_cl_find(inode);
        if (lcc == NULL)
index c5485a4..93bd7f9 100755 (executable)
@@ -14775,6 +14775,7 @@ test_119i()
        unaligned_dio_or_ldiskfs_with_same_page_size
        (( $OSTCOUNT >= 2 )) || skip "needs >= 2 OSTs"
        which aiocp || skip_env "no aiocp installed"
+       skip "LU-18032: Unaligned AIO is disabled and may not be re-enabled"
 
        local stripe_size=$((1024 * 1024)) #1 MiB
        # Max i/o below is ~ 4 * stripe_size, so this gives ~5 i/os