From 2ee5b51a57cb45992fb783ffa95c7fbea19153ed Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Mon, 12 May 2025 02:46:40 +1000 Subject: [PATCH] linux/uio: remove "skip" offset for UIO_ITER For UIO_ITER, we are just wrapping a kernel iterator. It will take care of its own offsets if necessary. We don't need to do anything, and if we do try to do anything with it (like advancing the iterator by the skip in zfs_uio_advance) we're just confusing the kernel iterator, ending up at the wrong position or worse, off the end of the memory region. Sponsored-by: https://despairlabs.com/sponsor/ Reviewed-by: Tony Hutter Reviewed-by: Alexander Motin Reviewed-by: Tino Reichardt Reviewed-by: Brian Atkinson Signed-off-by: Rob Norris Closes #17298 --- include/os/linux/spl/sys/uio.h | 4 ++-- module/os/linux/zfs/zfs_uio.c | 11 +++++------ module/os/linux/zfs/zpl_file.c | 5 ++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/include/os/linux/spl/sys/uio.h b/include/os/linux/spl/sys/uio.h index f66da5d5a..26c2c387c 100644 --- a/include/os/linux/spl/sys/uio.h +++ b/include/os/linux/spl/sys/uio.h @@ -174,7 +174,7 @@ zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq) static inline void zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset, - ssize_t resid, size_t skip) + ssize_t resid) { uio->uio_iter = iter; uio->uio_iovcnt = iter->nr_segs; @@ -184,7 +184,7 @@ zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset, uio->uio_fmode = 0; uio->uio_extflg = 0; uio->uio_resid = resid; - uio->uio_skip = skip; + uio->uio_skip = 0; uio->uio_soffset = uio->uio_loffset; memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t)); } diff --git a/module/os/linux/zfs/zfs_uio.c b/module/os/linux/zfs/zfs_uio.c index 901bd191f..d282f6d95 100644 --- a/module/os/linux/zfs/zfs_uio.c +++ b/module/os/linux/zfs/zfs_uio.c @@ -233,9 +233,6 @@ zfs_uiomove_iter(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio, { size_t cnt = MIN(n, uio->uio_resid); - if (uio->uio_skip) - iov_iter_advance(uio->uio_iter, uio->uio_skip); - if (rw == UIO_READ) cnt = copy_to_iter(p, cnt, uio->uio_iter); else @@ -507,12 +504,14 @@ static int zfs_uio_pin_user_pages(zfs_uio_t *uio, zfs_uio_rw_t rw) { long res; - size_t skip = uio->uio_skip; + size_t skip = uio->uio_iter->iov_offset; size_t len = uio->uio_resid - skip; unsigned int gup_flags = 0; unsigned long addr; unsigned long nr_pages; + ASSERT3U(uio->uio_segflg, ==, UIO_ITER); + /* * Kernel 6.2 introduced the FOLL_PCI_P2PDMA flag. This flag could * possibly be used here in the future to allow for P2P operations with @@ -577,7 +576,7 @@ static int zfs_uio_get_dio_pages_iov_iter(zfs_uio_t *uio, zfs_uio_rw_t rw) { size_t start; - size_t wanted = uio->uio_resid - uio->uio_skip; + size_t wanted = uio->uio_resid; ssize_t rollback = 0; ssize_t cnt; unsigned maxpages = DIV_ROUND_UP(wanted, PAGE_SIZE); @@ -611,7 +610,7 @@ zfs_uio_get_dio_pages_iov_iter(zfs_uio_t *uio, zfs_uio_rw_t rw) #endif } - ASSERT3U(rollback, ==, uio->uio_resid - uio->uio_skip); + ASSERT3U(rollback, ==, uio->uio_resid); iov_iter_revert(uio->uio_iter, rollback); return (0); diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c index 33307eedb..d27e8e8e8 100644 --- a/module/os/linux/zfs/zpl_file.c +++ b/module/os/linux/zfs/zpl_file.c @@ -226,7 +226,7 @@ zpl_iter_read(struct kiocb *kiocb, struct iov_iter *to) ssize_t count = iov_iter_count(to); zfs_uio_t uio; - zfs_uio_iov_iter_init(&uio, to, kiocb->ki_pos, count, 0); + zfs_uio_iov_iter_init(&uio, to, kiocb->ki_pos, count); crhold(cr); cookie = spl_fstrans_mark(); @@ -276,8 +276,7 @@ zpl_iter_write(struct kiocb *kiocb, struct iov_iter *from) if (ret) return (ret); - zfs_uio_iov_iter_init(&uio, from, kiocb->ki_pos, count, - from->iov_offset); + zfs_uio_iov_iter_init(&uio, from, kiocb->ki_pos, count); crhold(cr); cookie = spl_fstrans_mark();