mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback
@ 2026-10-26  8:29 Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 1/6] scsi: core: release SG_IO request " Yingjie Wang
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Yingjie Wang @ 2026-10-26  8:29 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Bart Van Assche, Yang Xiuwei, Jens Axboe, io-uring,
	linux-kernel

This rerolls the request-lifetime changes from the original six-patch
series. The independent data-copyback error fixes have already been
posted separately and received Yang Xiuwei's Reviewed-by for the series:

  https://lore.kernel.org/r/cover.1792772194.git.x-professor@outlook.com

This series is based on those two patches applied to mainline
390febb5805d ("Merge tag 'for-7.4-part2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux").
The base and prerequisite patch IDs are recorded below.

Changes since the original series:

- Release completed synchronous requests before sense/data copyback,
  with the request-backed output fields saved first. The original BIO
  chain remains owned by the user mapping until it is unmapped.
- Include SCSI_IOCTL_SEND_COMMAND as a separate fix for the legacy
  sibling identified during review.
- Rework BSG io_uring so end-I/O saves completion state and returns
  RQ_END_IO_FREE. Task work does not use rq or scmd. Optional sense
  storage is allocated and charged to memcg before acquiring the request;
  nonblocking allocation failure returns -EAGAIN for retry.
- Keep the pre-existing sense-length reporting error in a separate
  patch, and bound the new snapshot by its allocated capacity.
- Trace the synchronous lifetime dependency back through the file
  moves to the scsi-mq request pool, rather than a 2005 merge commit.

The old 1/6, 2/6, 3/6 and 5/6 correspond to the new 1/6, 3/6, 4/6 and
6/6. The new 2/6 and 5/6 address the legacy ioctl and sense-length
reporting respectively. Transport BSG remains outside this series: its
separate queue needs its own resource-dependency analysis.

Validation used matching x86-64 KASAN/lockdep configurations with QEMU
and virtual SCSI disk/CD-ROM devices. Before this series, 20/20 traced
DEFER_TASKRUN completions retained their request before task work ran;
afterward, the request was released in that window. The tests also
cover synchronous ioctls, sense/data copy errors, fixed buffers, io-wq,
pending-ring close, and fault-injected allocation failures. CDDA testing
exercised the virtual device's error path, not successful audio extraction
from real media. Each intermediate commit was built independently; i386
and modular SCSI with IO_URING disabled were also object-built.

The earlier one-tag fault results are historical evidence, not newly
rerun deadlock tests of this revision. The dependency when completed
requests retain all tags available to nested I/O is a source-level
argument; it is not a claim of a new multi-tag exhaustion experiment.


v1: https://lore.kernel.org/r/cover.1792237341.git.x-professor@outlook.com
Review follow-up: https://lore.kernel.org/r/20261022.scsi-copyback-review.31b8d6a70f4c@outlook.com
CDDA reply: https://lore.kernel.org/r/20261022.scsi-cdda-lifetime.8f31a2c97b42@outlook.com

Yingjie Wang (6):
  scsi: core: release SG_IO request before user copyback
  scsi: core: release legacy ioctl request before user copyback
  scsi: sr: release CDDA request before user copyback
  scsi: bsg: release synchronous request before user copyback
  scsi: bsg: clear io_uring sense length on copy failure
  scsi: bsg: release io_uring requests in end-I/O

 drivers/scsi/scsi_bsg.c   | 102 ++++++++++++++++++++++++--------------
 drivers/scsi/scsi_ioctl.c |  34 +++++++++----
 drivers/scsi/sr.c         |   3 ++
 3 files changed, 92 insertions(+), 47 deletions(-)


base-commit: 390febb5805d3bb830402679f277f1d5f309e6bc
prerequisite-patch-id: 8dbaa81edcd4c0acbe43169d7d1c7012f6bec995
prerequisite-patch-id: 321b182025cad20ba75cc00122e50daba8d1a52f
-- 
2.43.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/6] scsi: core: release SG_IO request before user copyback
  2026-10-26  8:29 [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback Yingjie Wang
@ 2026-10-26  8:29 ` Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 2/6] scsi: core: release legacy ioctl " Yingjie Wang
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Yingjie Wang @ 2026-10-26  8:29 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Bart Van Assche, Yang Xiuwei, Jens Axboe, io-uring,
	linux-kernel, stable

From: Yingjie Wang <x-professor@outlook.com>

The block-device SG_IO path retains its completed request while copying
sense data and unmapping the user data buffer. Either operation can fault.
If the fault needs I/O from the same queue and completed requests retain
the available tags, the nested I/O cannot make progress.

Fill the kernel-resident output header and save the bounded sense data
before releasing the request. Then perform the user copies and unmap the
original BIO chain, preserving the existing sense-copy error precedence.
The saved mapping owns its BIO references independently of the request.

The fixed request pool was introduced by scsi-mq; the later move of this
ioctl implementation into drivers/scsi did not introduce the dependency.

Fixes: d285203cf647 ("scsi: add support for a blk-mq based I/O path.")
Link: https://lore.kernel.org/r/20261022.scsi-copyback-review.31b8d6a70f4c@outlook.com
Cc: stable@vger.kernel.org
Signed-off-by: Yingjie Wang <x-professor@outlook.com>
---
 drivers/scsi/scsi_ioctl.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 122403ec3ab8d..68e84705634c9 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -393,6 +393,8 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
 		struct bio *bio)
 {
 	struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
+	u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+	unsigned int sense_len = 0;
 	int r, ret = 0;
 
 	/*
@@ -412,10 +414,16 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
 	hdr->sb_len_wr = 0;
 
 	if (scmd->sense_len && hdr->sbp) {
-		int len = min((unsigned int) hdr->mx_sb_len, scmd->sense_len);
+		sense_len = min3(hdr->mx_sb_len, scmd->sense_len,
+				 sizeof(sense_buffer));
+		memcpy(sense_buffer, scmd->sense_buffer, sense_len);
+	}
+
+	blk_mq_free_request(rq);
 
-		if (!copy_to_user(hdr->sbp, scmd->sense_buffer, len))
-			hdr->sb_len_wr = len;
+	if (sense_len) {
+		if (!copy_to_user(hdr->sbp, sense_buffer, sense_len))
+			hdr->sb_len_wr = sense_len;
 		else
 			ret = -EFAULT;
 	}
@@ -488,7 +496,7 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr,
 
 	hdr->duration = jiffies_to_msecs(jiffies - start_time);
 
-	ret = scsi_complete_sghdr_rq(rq, hdr, bio);
+	return scsi_complete_sghdr_rq(rq, hdr, bio);
 
 out_put_request:
 	blk_mq_free_request(rq);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 2/6] scsi: core: release legacy ioctl request before user copyback
  2026-10-26  8:29 [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 1/6] scsi: core: release SG_IO request " Yingjie Wang
@ 2026-10-26  8:29 ` Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 3/6] scsi: sr: release CDDA " Yingjie Wang
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Yingjie Wang @ 2026-10-26  8:29 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Bart Van Assche, Yang Xiuwei, Jens Axboe, io-uring,
	linux-kernel, stable

From: Yingjie Wang <x-professor@outlook.com>

SCSI_IOCTL_SEND_COMMAND copies sense or command data to userspace while
the completed request still occupies its queue tag. A fault that needs
the same queue can therefore wait for a resource held by the ioctl.

Save the command status and the compatibility-limited sense data, then
release the request before copying to userspace. The data buffer is a
separate allocation and remains valid until the existing buffer cleanup.
Keep the positive SCSI status and -EFAULT return conventions unchanged.

This complements the SG_IO fix by covering the legacy
SCSI_IOCTL_SEND_COMMAND path.

Fixes: d285203cf647 ("scsi: add support for a blk-mq based I/O path.")
Link: https://lore.kernel.org/r/20261022.scsi-copyback-review.31b8d6a70f4c@outlook.com
Cc: stable@vger.kernel.org
Signed-off-by: Yingjie Wang <x-professor@outlook.com>
---
 drivers/scsi/scsi_ioctl.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 68e84705634c9..95e91ae1332c4 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -533,6 +533,8 @@ static int sg_scsi_ioctl(struct request_queue *q, bool open_for_write,
 		struct scsi_ioctl_command __user *sic)
 {
 	struct request *rq;
+	u8 sense_buffer[16];
+	unsigned int sense_len = 0;
 	int err;
 	unsigned int in_len, out_len, bytes, opcode, cmdlen;
 	struct scsi_cmnd *scmd;
@@ -621,17 +623,21 @@ static int sg_scsi_ioctl(struct request_queue *q, bool open_for_write,
 	blk_execute_rq(rq, false);
 
 	err = scmd->result & 0xff;	/* only 8 bit SCSI status */
+	if (err && scmd->sense_len && scmd->sense_buffer) {
+		/* limit sense len for backward compatibility */
+		sense_len = min(scmd->sense_len, sizeof(sense_buffer));
+		memcpy(sense_buffer, scmd->sense_buffer, sense_len);
+	}
+	blk_mq_free_request(rq);
+
 	if (err) {
-		if (scmd->sense_len && scmd->sense_buffer) {
-			/* limit sense len for backward compatibility */
-			if (copy_to_user(sic->data, scmd->sense_buffer,
-					 min(scmd->sense_len, 16U)))
-				err = -EFAULT;
-		}
+		if (sense_len && copy_to_user(sic->data, sense_buffer, sense_len))
+			err = -EFAULT;
 	} else {
 		if (copy_to_user(sic->data, buffer, out_len))
 			err = -EFAULT;
 	}
+	goto error_free_buffer;
 
 error:
 	blk_mq_free_request(rq);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 3/6] scsi: sr: release CDDA request before user copyback
  2026-10-26  8:29 [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 1/6] scsi: core: release SG_IO request " Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 2/6] scsi: core: release legacy ioctl " Yingjie Wang
@ 2026-10-26  8:29 ` Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 4/6] scsi: bsg: release synchronous " Yingjie Wang
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Yingjie Wang @ 2026-10-26  8:29 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Bart Van Assche, Yang Xiuwei, Jens Axboe, io-uring,
	linux-kernel, stable

From: Yingjie Wang <x-professor@outlook.com>

sr_read_cdda_bpc() retains its completed request while unmapping the user
buffer. For a bounced data-in mapping, unmapping can copy to userspace
and fault. A fault that needs I/O from the same queue cannot progress if
the completed request retains the available tag.

Release the request after consuming its command result and sense data,
before unmapping the original BIO chain saved at submission. No request
or SCSI command field is accessed after the release. The mapping's BIO
references remain owned by blk_rq_unmap_user().

The scsi-mq request pool introduced this tag dependency. The later move
of the CDDA implementation from drivers/cdrom into sr was a relocation.

Fixes: d285203cf647 ("scsi: add support for a blk-mq based I/O path.")
Link: https://lore.kernel.org/r/20261022.scsi-cdda-lifetime.8f31a2c97b42@outlook.com
Cc: stable@vger.kernel.org
Signed-off-by: Yingjie Wang <x-professor@outlook.com>
---
 drivers/scsi/sr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 4f2e8d1be6da8..c64c25e9f4047 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -969,8 +969,11 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf,
 		ret = -EIO;
 	}
 
+	blk_mq_free_request(rq);
 	if (blk_rq_unmap_user(bio))
 		ret = -EFAULT;
+	return ret;
+
 out_put_request:
 	blk_mq_free_request(rq);
 	return ret;
-- 
2.43.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 4/6] scsi: bsg: release synchronous request before user copyback
  2026-10-26  8:29 [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback Yingjie Wang
                   ` (2 preceding siblings ...)
  2026-10-26  8:29 ` [PATCH v2 3/6] scsi: sr: release CDDA " Yingjie Wang
@ 2026-10-26  8:29 ` Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 5/6] scsi: bsg: clear io_uring sense length on copy failure Yingjie Wang
  2026-10-26  8:29 ` [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O Yingjie Wang
  5 siblings, 0 replies; 11+ messages in thread
From: Yingjie Wang @ 2026-10-26  8:29 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Bart Van Assche, Yang Xiuwei, Jens Axboe, io-uring,
	linux-kernel, stable

From: Yingjie Wang <x-professor@outlook.com>

The synchronous SCSI BSG ioctl copies sense data and unmaps its user
data buffer while retaining the completed request. Copyback can fault
and need I/O from the same queue, which cannot progress when completed
requests retain the available tags.

Fill the kernel-resident output fields and save the bounded sense data
before releasing the request. Perform both user copies afterward, using
the original BIO chain saved at mapping time. Preserve the copyback
error precedence established by the separate error-propagation fix.

The SG_IO v4 implementation predates scsi-mq. The fixed scsi-mq request
pool introduced this dependency; moving the callback into scsi_bsg.c
did not change its ownership ordering.

Fixes: d285203cf647 ("scsi: add support for a blk-mq based I/O path.")
Link: https://lore.kernel.org/r/20261022.scsi-copyback-review.31b8d6a70f4c@outlook.com
Cc: stable@vger.kernel.org
Signed-off-by: Yingjie Wang <x-professor@outlook.com>
---
 drivers/scsi/scsi_bsg.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index e4a65d7a23742..650facb16ed23 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -199,6 +199,8 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
 	struct scsi_cmnd *scmd;
 	struct request *rq;
 	struct bio *bio;
+	u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+	unsigned int sense_len = 0;
 	int ret, unmap_ret;
 
 	if (hdr->protocol != BSG_PROTOCOL_SCSI  ||
@@ -258,24 +260,28 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
 	hdr->response_len = 0;
 
 	if (scmd->sense_len && hdr->response) {
-		int len = min_t(unsigned int, hdr->max_response_len,
-				scmd->sense_len);
-
-		if (copy_to_user(uptr64(hdr->response), scmd->sense_buffer,
-				 len))
-			ret = -EFAULT;
-		else
-			hdr->response_len = len;
+		sense_len = min3(hdr->max_response_len, scmd->sense_len,
+				 sizeof(sense_buffer));
+		memcpy(sense_buffer, scmd->sense_buffer, sense_len);
 	}
 
 	if (rq_data_dir(rq) == READ)
 		hdr->din_resid = scmd->resid_len;
 	else
 		hdr->dout_resid = scmd->resid_len;
+	blk_mq_free_request(rq);
+
+	if (sense_len) {
+		if (copy_to_user(uptr64(hdr->response), sense_buffer, sense_len))
+			ret = -EFAULT;
+		else
+			hdr->response_len = sense_len;
+	}
 
 	unmap_ret = blk_rq_unmap_user(bio);
 	if (!ret)
 		ret = unmap_ret;
+	return ret;
 
 out_put_request:
 	blk_mq_free_request(rq);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 5/6] scsi: bsg: clear io_uring sense length on copy failure
  2026-10-26  8:29 [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback Yingjie Wang
                   ` (3 preceding siblings ...)
  2026-10-26  8:29 ` [PATCH v2 4/6] scsi: bsg: release synchronous " Yingjie Wang
@ 2026-10-26  8:29 ` Yingjie Wang
  2026-10-26  9:40   ` Yang Xiuwei
  2026-10-26  8:29 ` [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O Yingjie Wang
  5 siblings, 1 reply; 11+ messages in thread
From: Yingjie Wang @ 2026-10-26  8:29 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Bart Van Assche, Yang Xiuwei, Jens Axboe, io-uring,
	linux-kernel

From: Yingjie Wang <x-professor@outlook.com>

The SCSI BSG io_uring completion reports sense_len_wr in res2 as the
number of sense bytes written to the response buffer. If copy_to_user()
fails, the callback returns -EFAULT but leaves that field nonzero.

Clear the reported sense length on a failed copy, matching the
synchronous BSG and SG_IO interfaces. This reporting error predates the
request-lifetime changes and can be fixed independently.

Fixes: 7b6d3255e7f8 ("scsi: bsg: add io_uring passthrough handler")
Link: https://lore.kernel.org/r/20261022.scsi-copyback-review.31b8d6a70f4c@outlook.com
Signed-off-by: Yingjie Wang <x-professor@outlook.com>
---
 drivers/scsi/scsi_bsg.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index 650facb16ed23..98c9db1cae653 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -52,8 +52,10 @@ static void scsi_bsg_uring_task_cb(struct io_tw_req tw_req, io_tw_token_t tw)
 
 	if (sense_len_wr) {
 		if (copy_to_user(uptr64(pdu->response_addr), scmd->sense_buffer,
-				 sense_len_wr))
+				 sense_len_wr)) {
 			ret = -EFAULT;
+			sense_len_wr = 0;
+		}
 	}
 
 	res2 = bsg_scsi_res2_build(status_byte(scmd->result), driver_status,
-- 
2.43.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O
  2026-10-26  8:29 [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback Yingjie Wang
                   ` (4 preceding siblings ...)
  2026-10-26  8:29 ` [PATCH v2 5/6] scsi: bsg: clear io_uring sense length on copy failure Yingjie Wang
@ 2026-10-26  8:29 ` Yingjie Wang
  2026-10-26  9:40   ` Yang Xiuwei
  2026-10-26 15:56   ` Bart Van Assche
  5 siblings, 2 replies; 11+ messages in thread
From: Yingjie Wang @ 2026-10-26  8:29 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Bart Van Assche, Yang Xiuwei, Jens Axboe, io-uring,
	linux-kernel, stable

From: Yingjie Wang <x-professor@outlook.com>

The SCSI BSG end-I/O callback returns RQ_END_IO_NONE and leaves the
completed request for task work to release. The request therefore
retains its tag before task work runs as well as during user copyback.
With deferred task work, completing the device command alone does not
make that request available to other I/O.

Save the status, residual count and bounded sense data in end-I/O, then
return RQ_END_IO_FREE. Task work can unmap the saved BIO, copy the saved
sense data and publish the CQE without accessing the request or scmd.

Allocate sense storage at submission only when a nonempty response
buffer was requested. Charge this user-triggered allocation to memcg.
Do this before acquiring the request, respect nonblocking allocation,
and return -EAGAIN for an allocation failure that can be retried in
blocking context. Free the storage on submission failure or after
task-work copyback. Reuse the snapshot-capacity field for the packed
completion result after the end-I/O snapshot, keeping the PDU within
32 bytes.

Preallocation avoids relying on a non-sleeping allocation in end-I/O
to preserve sense data after a command has already completed.

Fixes: 7b6d3255e7f8 ("scsi: bsg: add io_uring passthrough handler")
Link: https://lore.kernel.org/r/20261022.scsi-copyback-review.31b8d6a70f4c@outlook.com
Cc: stable@vger.kernel.org
Signed-off-by: Yingjie Wang <x-professor@outlook.com>
---
 drivers/scsi/scsi_bsg.c | 78 ++++++++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 29 deletions(-)

diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index 98c9db1cae653..fafa5c2cdac0e 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/bsg.h>
 #include <linux/io_uring/cmd.h>
+#include <linux/slab.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_cmnd.h>
@@ -16,9 +17,13 @@
  */
 struct scsi_bsg_uring_cmd_pdu {
 	struct bio *bio;		/* mapped user buffer, unmap in task work */
-	struct request *req;		/* block request, freed in task work */
+	u8 *sense_buffer;		/* allocated at submission, freed in task work */
 	u64 response_addr;		/* user space response buffer address */
-	u32 max_response_len;		/* user response buffer size */
+	/* max_response_len is replaced by res2 after the end-I/O snapshot. */
+	union {
+		u32 max_response_len;	/* maximum sense snapshot size */
+		u64 res2;		/* saved completion result */
+	};
 };
 static_assert(sizeof(struct scsi_bsg_uring_cmd_pdu) <= sizeof_field(struct io_uring_cmd, pdu));
 
@@ -28,41 +33,30 @@ static inline struct scsi_bsg_uring_cmd_pdu *scsi_bsg_uring_cmd_pdu(
 	return io_uring_cmd_to_pdu(ioucmd, struct scsi_bsg_uring_cmd_pdu);
 }
 
-/* Task work: build res2 (layout in uapi/linux/bsg.h) and copy sense to user. */
+/* Task work: unmap the saved BIO and copy sense to userspace. */
 static void scsi_bsg_uring_task_cb(struct io_tw_req tw_req, io_tw_token_t tw)
 {
 	struct io_uring_cmd *ioucmd = io_uring_cmd_from_tw(tw_req);
 	struct scsi_bsg_uring_cmd_pdu *pdu = scsi_bsg_uring_cmd_pdu(ioucmd);
-	struct request *rq = pdu->req;
-	struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
-	u64 res2;
+	u64 res2 = pdu->res2;
 	int ret = 0;
-	u8 driver_status = 0;
-	u8 sense_len_wr = 0;
+	u8 sense_len_wr = bsg_scsi_res2_sense_len(res2);
 
 	if (pdu->bio)
 		ret = blk_rq_unmap_user(pdu->bio);
 
-	if (scsi_status_is_check_condition(scmd->result)) {
-		driver_status = DRIVER_SENSE;
-		if (pdu->response_addr)
-			sense_len_wr = min_t(unsigned int, pdu->max_response_len,
-					     scmd->sense_len);
-	}
-
 	if (sense_len_wr) {
-		if (copy_to_user(uptr64(pdu->response_addr), scmd->sense_buffer,
+		if (copy_to_user(uptr64(pdu->response_addr), pdu->sense_buffer,
 				 sense_len_wr)) {
 			ret = -EFAULT;
-			sense_len_wr = 0;
+			res2 = bsg_scsi_res2_build(bsg_scsi_res2_device_status(res2),
+						   bsg_scsi_res2_driver_status(res2),
+						   bsg_scsi_res2_host_status(res2), 0,
+						   bsg_scsi_res2_resid_len(res2));
 		}
 	}
 
-	res2 = bsg_scsi_res2_build(status_byte(scmd->result), driver_status,
-				  host_byte(scmd->result), sense_len_wr,
-				  scmd->resid_len);
-
-	blk_mq_free_request(rq);
+	kfree(pdu->sense_buffer);
 	io_uring_cmd_done32(ioucmd, ret, res2,
 			    IO_URING_CMD_TASK_WORK_ISSUE_FLAGS);
 }
@@ -72,9 +66,24 @@ static enum rq_end_io_ret scsi_bsg_uring_cmd_done(struct request *req,
 						  const struct io_comp_batch *iocb)
 {
 	struct io_uring_cmd *ioucmd = req->end_io_data;
+	struct scsi_bsg_uring_cmd_pdu *pdu = scsi_bsg_uring_cmd_pdu(ioucmd);
+	struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req);
+	u8 driver_status = 0;
+	u8 sense_len = 0;
+
+	if (scsi_status_is_check_condition(scmd->result)) {
+		driver_status = DRIVER_SENSE;
+		if (pdu->sense_buffer) {
+			sense_len = min(pdu->max_response_len, scmd->sense_len);
+			memcpy(pdu->sense_buffer, scmd->sense_buffer, sense_len);
+		}
+	}
+	pdu->res2 = bsg_scsi_res2_build(status_byte(scmd->result), driver_status,
+					host_byte(scmd->result), sense_len,
+					scmd->resid_len);
 
 	io_uring_cmd_do_in_task_lazy(ioucmd, scsi_bsg_uring_task_cb);
-	return RQ_END_IO_NONE;
+	return RQ_END_IO_FREE;
 }
 
 static int scsi_bsg_map_user_buffer(struct request *req,
@@ -139,10 +148,23 @@ static int scsi_bsg_uring_cmd(struct request_queue *q, struct io_uring_cmd *iouc
 		gfp_mask = GFP_NOWAIT;
 	}
 
+	pdu->response_addr = READ_ONCE(cmd->response);
+	pdu->max_response_len = min(READ_ONCE(cmd->max_response_len),
+				    SCSI_SENSE_BUFFERSIZE);
+	pdu->sense_buffer = NULL;
+	if (pdu->response_addr && pdu->max_response_len) {
+		pdu->sense_buffer = kmalloc(pdu->max_response_len,
+					    gfp_mask | __GFP_ACCOUNT);
+		if (!pdu->sense_buffer)
+			return (issue_flags & IO_URING_F_NONBLOCK) ? -EAGAIN : -ENOMEM;
+	}
+
 	req = scsi_alloc_request(q, dout_xfer_len ?
 				 REQ_OP_DRV_OUT : REQ_OP_DRV_IN, blk_flags);
-	if (IS_ERR(req))
-		return PTR_ERR(req);
+	if (IS_ERR(req)) {
+		ret = PTR_ERR(req);
+		goto out_free_sense;
+	}
 
 	scmd = blk_mq_rq_to_pdu(req);
 	if (request_len > sizeof(scmd->cmnd)) {
@@ -162,9 +184,6 @@ static int scsi_bsg_uring_cmd(struct request_queue *q, struct io_uring_cmd *iouc
 		goto out_free_req;
 	}
 
-	pdu->response_addr = cmd->response;
-	pdu->max_response_len = cmd->max_response_len;
-
 	if (dout_xfer_len || din_xfer_len) {
 		bool is_write = dout_xfer_len > 0;
 		u64 buf_addr = is_write ? dout_xferp : din_xferp;
@@ -185,13 +204,14 @@ static int scsi_bsg_uring_cmd(struct request_queue *q, struct io_uring_cmd *iouc
 
 	req->end_io = scsi_bsg_uring_cmd_done;
 	req->end_io_data = ioucmd;
-	pdu->req = req;
 
 	blk_execute_rq_nowait(req, false);
 	return -EIOCBQUEUED;
 
 out_free_req:
 	blk_mq_free_request(req);
+out_free_sense:
+	kfree(pdu->sense_buffer);
 	return ret;
 }
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 5/6] scsi: bsg: clear io_uring sense length on copy failure
  2026-10-26  8:29 ` [PATCH v2 5/6] scsi: bsg: clear io_uring sense length on copy failure Yingjie Wang
@ 2026-10-26  9:40   ` Yang Xiuwei
  0 siblings, 0 replies; 11+ messages in thread
From: Yang Xiuwei @ 2026-10-26  9:40 UTC (permalink / raw)
  To: x-professor
  Cc: mkp, James.Bottomley, linux-scsi, bvanassche, axboe, io-uring,
	linux-kernel

Hi Yingjie,

On Mon, 26 Oct 2026, Yingjie Wang wrote:
> This reporting error predates the request-lifetime changes and can be
> fixed independently.

6/6 drops sense_len_wr and rebuilds res2 with a zero sense length,
so this does not need to be a separate patch.

Thanks,
Yang Xiuwei


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O
  2026-10-26  8:29 ` [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O Yingjie Wang
@ 2026-10-26  9:40   ` Yang Xiuwei
  2026-10-27  9:35     ` Yang Xiuwei
  2026-10-26 15:56   ` Bart Van Assche
  1 sibling, 1 reply; 11+ messages in thread
From: Yang Xiuwei @ 2026-10-26  9:40 UTC (permalink / raw)
  To: x-professor
  Cc: mkp, James.Bottomley, linux-scsi, bvanassche, axboe, io-uring,
	linux-kernel

Hi Yingjie,

On Mon, 26 Oct 2026, Yingjie Wang wrote:
> +		pdu->sense_buffer = kmalloc(pdu->max_response_len,
> +					    gfp_mask | __GFP_ACCOUNT);

Tested in a VM: INQUIRY batch latency went from 30us to 42us with this
allocation.

The long tag hold is IORING_SETUP_DEFER_TASKRUN. Returning -EOPNOTSUPP
for that flag seems like a compromise. I'd like to hear what others
think.

Thanks,
Yang Xiuwei


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O
  2026-10-26  8:29 ` [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O Yingjie Wang
  2026-10-26  9:40   ` Yang Xiuwei
@ 2026-10-26 15:56   ` Bart Van Assche
  1 sibling, 0 replies; 11+ messages in thread
From: Bart Van Assche @ 2026-10-26 15:56 UTC (permalink / raw)
  To: Yingjie Wang, Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, Yang Xiuwei, Jens Axboe, io-uring, linux-kernel, stable

On 10/26/26 1:29 AM, Yingjie Wang wrote:
> +	pdu->response_addr = READ_ONCE(cmd->response);
> +	pdu->max_response_len = min(READ_ONCE(cmd->max_response_len),
> +				    SCSI_SENSE_BUFFERSIZE);
> +	pdu->sense_buffer = NULL;
> +	if (pdu->response_addr && pdu->max_response_len) {
> +		pdu->sense_buffer = kmalloc(pdu->max_response_len,
> +					    gfp_mask | __GFP_ACCOUNT);
> +		if (!pdu->sense_buffer)
> +			return (issue_flags & IO_URING_F_NONBLOCK) ? -EAGAIN : -ENOMEM;
> +	}

No new kmalloc() calls in the I/O path please. These have a measurable
performance impact.

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O
  2026-10-26  9:40   ` Yang Xiuwei
@ 2026-10-27  9:35     ` Yang Xiuwei
  0 siblings, 0 replies; 11+ messages in thread
From: Yang Xiuwei @ 2026-10-27  9:35 UTC (permalink / raw)
  To: x-professor
  Cc: mkp, James.Bottomley, linux-scsi, bvanassche, axboe, io-uring,
	linux-kernel

Hi Yingjie,

On Mon, 26 Oct 2026, Yang Xiuwei wrote:
> Tested in a VM: INQUIRY batch latency went from 30us to 42us with this
> allocation.

For reference: scsi_mq_init_request() already allocates sense_buffer
from scsi_sense_cache. A second buffer from that cache, bsg_sense, can
hold the copy.

Thanks,
Yang Xiuwei


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-10-27  9:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26  8:29 [PATCH v2 0/6] scsi: release completed passthrough requests before user copyback Yingjie Wang
2026-10-26  8:29 ` [PATCH v2 1/6] scsi: core: release SG_IO request " Yingjie Wang
2026-10-26  8:29 ` [PATCH v2 2/6] scsi: core: release legacy ioctl " Yingjie Wang
2026-10-26  8:29 ` [PATCH v2 3/6] scsi: sr: release CDDA " Yingjie Wang
2026-10-26  8:29 ` [PATCH v2 4/6] scsi: bsg: release synchronous " Yingjie Wang
2026-10-26  8:29 ` [PATCH v2 5/6] scsi: bsg: clear io_uring sense length on copy failure Yingjie Wang
2026-10-26  9:40   ` Yang Xiuwei
2026-10-26  8:29 ` [PATCH v2 6/6] scsi: bsg: release io_uring requests in end-I/O Yingjie Wang
2026-10-26  9:40   ` Yang Xiuwei
2026-10-27  9:35     ` Yang Xiuwei
2026-10-26 15:56   ` Bart Van Assche

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®