[PATCH 5/6] scsi: bsg: release io_uring request before user copyback
From: Wang Yingjie
Date: Sun Oct 18 2026 - 11:43:46 EST
From: Yingjie Wang <x-professor@xxxxxxxxxxx>
The BSG io_uring end-I/O callback returns RQ_END_IO_NONE, so task work
still owns the completed request and its tag. Task work then copies
READ bounce data and optional sense data to userspace. A fault on the
same one-tag device deadlocks nested I/O behind the retained request.
Snapshot the result, residual, and sense bytes into local storage, then
free the request before either userspace copy.
A current-mainline BSG INQUIRY into a nonresident mapping of the same
/dev/sr0 queue previously stuck in scsi_bsg_uring_task_cb ->
blk_rq_unmap_user -> filemap_fault. The fixed kernel completed 20/20
repetitions and left no blocked I/O or hung-task report.
Fixes: 7b6d3255e7f8 ("scsi: bsg: add io_uring passthrough handler")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: Yingjie Wang <x-professor@xxxxxxxxxxx>
---
drivers/scsi/scsi_bsg.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index f95dc5da7480..341142dda71d 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -35,32 +35,37 @@ static void scsi_bsg_uring_task_cb(struct io_tw_req tw_req, io_tw_token_t tw)
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);
+ u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+ u32 scsi_result = scmd->result;
+ u32 resid_len = scmd->resid_len;
u64 res2;
int ret = 0;
u8 driver_status = 0;
u8 sense_len_wr = 0;
- if (pdu->bio)
- blk_rq_unmap_user(pdu->bio);
-
- if (scsi_status_is_check_condition(scmd->result)) {
+ if (scsi_status_is_check_condition(scsi_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)
+ memcpy(sense_buffer, scmd->sense_buffer, sense_len_wr);
+
+ blk_mq_free_request(rq);
+ if (pdu->bio)
+ blk_rq_unmap_user(pdu->bio);
if (sense_len_wr) {
- if (copy_to_user(uptr64(pdu->response_addr), scmd->sense_buffer,
+ if (copy_to_user(uptr64(pdu->response_addr), sense_buffer,
sense_len_wr))
ret = -EFAULT;
}
- res2 = bsg_scsi_res2_build(status_byte(scmd->result), driver_status,
- host_byte(scmd->result), sense_len_wr,
- scmd->resid_len);
+ res2 = bsg_scsi_res2_build(status_byte(scsi_result),
+ driver_status, host_byte(scsi_result),
+ sense_len_wr, resid_len);
- blk_mq_free_request(rq);
io_uring_cmd_done32(ioucmd, ret, res2,
IO_URING_CMD_TASK_WORK_ISSUE_FLAGS);
}
--
2.43.0