]> www.infradead.org Git - nvme.git/commitdiff
io_uring/rsrc: ensure segments counts are correct on kbuf buffers
authorJens Axboe <axboe@kernel.dk>
Wed, 16 Apr 2025 22:48:26 +0000 (16:48 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 17 Apr 2025 17:59:12 +0000 (11:59 -0600)
kbuf imports have the front offset adjusted and segments removed, but
the tail segments are still included in the segment count that gets
passed in the iov_iter. As the segments aren't necessarily all the
same size, move importing to a separate helper and iterate the
mapped length to get an exact count.

Reviewed-by: Nitesh Shetty <nj.shetty@samsung.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/rsrc.c

index 0c6d7e7415c8b7e32762d3a0d49eaccf76f83647..f80a77c4973f30b87a0c57a364487c61c9f94882 100644 (file)
@@ -1032,6 +1032,26 @@ static int validate_fixed_range(u64 buf_addr, size_t len,
        return 0;
 }
 
+static int io_import_kbuf(int ddir, struct iov_iter *iter,
+                         struct io_mapped_ubuf *imu, size_t len, size_t offset)
+{
+       size_t count = len + offset;
+
+       iov_iter_bvec(iter, ddir, imu->bvec, imu->nr_bvecs, count);
+       iov_iter_advance(iter, offset);
+
+       if (count < imu->len) {
+               const struct bio_vec *bvec = iter->bvec;
+
+               while (len > bvec->bv_len) {
+                       len -= bvec->bv_len;
+                       bvec++;
+               }
+               iter->nr_segs = 1 + bvec - iter->bvec;
+       }
+       return 0;
+}
+
 static int io_import_fixed(int ddir, struct iov_iter *iter,
                           struct io_mapped_ubuf *imu,
                           u64 buf_addr, size_t len)
@@ -1052,11 +1072,8 @@ static int io_import_fixed(int ddir, struct iov_iter *iter,
 
        offset = buf_addr - imu->ubuf;
 
-       if (imu->is_kbuf) {
-               iov_iter_bvec(iter, ddir, imu->bvec, imu->nr_bvecs, offset + len);
-               iov_iter_advance(iter, offset);
-               return 0;
-       }
+       if (imu->is_kbuf)
+               return io_import_kbuf(ddir, iter, imu, len, offset);
 
        /*
         * Don't use iov_iter_advance() here, as it's really slow for