FAILED: patch "[PATCH] block: fix queue limits checks in blk_rq_map_user_bvec for" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x be0e822bb3f5259c7f9424ba97e8175211288813
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024110618-voicing-yield-48ff@gregkh' --subject-prefix 'PATCH 6.1.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From be0e822bb3f5259c7f9424ba97e8175211288813 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <[email protected]>
Date: Mon, 28 Oct 2024 10:07:48 +0100
Subject: [PATCH] block: fix queue limits checks in blk_rq_map_user_bvec for
real
blk_rq_map_user_bvec currently only has ad-hoc checks for queue limits, and the last fix to it enabled valid NVMe I/O to pass, but also allowed invalid one for drivers that set a max_segment_size or seg_boundary limit.
Fix it once for all by using the bio_split_rw_at helper from the I/O path that indicates if and where a bio would be have to be split to adhere to the queue limits, and it returns a positive value, turn that into -EREMOTEIO to retry using the copy path.
block/blk-map.c +17 -39
@@ -561,55 +561,33 @@ EXPORT_SYMBOL(blk_rq_append_bio);/* Prepare bio for passthrough IO given ITER_BVEC iter */ static int blk_rq_map_user_bvec (struct request *rq,const struct iov_iter *iter) { -struct request_queue *q = rq->q; -size_t nr_iter =iov_iter_count (iter); -size_t nr_segs = iter->nr_segs; -struct bio_vec *bvecs, *bvprvp =NULL ; -const struct queue_limits *lim = &q->limits; -unsigned int nsegs =0 , bytes =0 ; +const struct queue_limits *lim = &rq->q->limits; +unsigned int max_bytes = lim->max_hw_sectors <<SECTOR_SHIFT ; +unsigned int nsegs;struct bio *bio; -size_t i; +int ret; -if (!nr_iter || (nr_iter >>SECTOR_SHIFT ) >queue_max_hw_sectors (q)) -return -EINVAL ; -if (nr_segs >queue_max_segments (q)) +if (!iov_iter_count (iter) ||iov_iter_count (iter) > max_bytes)return -EINVAL ; -/* no iovecs to alloc, as we already have a BVEC iterator */ +/* reuse the bvecs from the iterator instead of allocating new ones */ bio =blk_rq_map_bio_alloc (rq,0 ,GFP_KERNEL ); -if (bio ==NULL ) +if (!bio)return -ENOMEM ; -bio_iov_bvec_set (bio, (struct iov_iter *)iter); -blk_rq_bio_prep (rq, bio, nr_segs); -/* loop to perform a bunch of sanity checks */ - bvecs = (struct bio_vec *)iter->bvec; -for (i =0 ; i < nr_segs; i++) { -struct bio_vec *bv = &bvecs[i]; - -/* -* If the queue doesn't support SG gaps and adding this -* offset would create a gap, fallback to copy. -*/ -if (bvprvp &&bvec_gap_to_prev (lim, bvprvp, bv->bv_offset)) { -blk_mq_map_bio_put (bio); -return -EREMOTEIO ; - } -/* check full condition */ -if (nsegs >= nr_segs || bytes >UINT_MAX - bv->bv_len) - goto put_bio; -if (bytes + bv->bv_len > nr_iter) -break ; - - nsegs++; - bytes += bv->bv_len; - bvprvp = bv; +/* check that the data layout matches the hardware restrictions */ + ret =bio_split_rw_at (bio, lim, &nsegs, max_bytes); +if (ret) { +/* if we would have to split the bio, copy instead */ +if (ret >0 ) + ret = -EREMOTEIO ; +blk_mq_map_bio_put (bio); +return ret; } + +blk_rq_bio_prep (rq, bio, nsegs);return 0 ; -put_bio: -blk_mq_map_bio_put (bio); -return -EINVAL ; }/**