#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);
]) # 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
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
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
# 5.2 - Check export
LC_ACCOUNT_PAGE_DIRTIED
+ # 6.0 - Check export
+ LC_HAVE_ADD_TO_PAGE_CACHE_LOCKED
+
]) # LC_PROG_LINUX
#
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
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 */
* 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
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;
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)
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