s390/dasd: Snapshot intrc before freeing the request block

__dasd_cleanup_cqr() maps the completion result to a block status by
reading cqr->intrc, but only after discipline->free_cp() has returned the
request block to its memory pool (dasd_eckd_free_cp() ends in
dasd_sfree_request()). On SMP another CPU can reallocate that block and
overwrite cqr->intrc before it is read, completing the request with the
wrong error. proc_bytes is already snapshotted before free_cp() for the
same reason; do the same for intrc.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Link: https://patch.msgid.link/20260805111612.1285190-5-sth@linux.ibm.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Stefan Haberland
2026-08-05 13:15:57 +02:00
committed by Jens Axboe
parent 2a1780f9fc
commit dc3e3f7306

View File

@@ -2687,17 +2687,23 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
struct request *req;
blk_status_t error = BLK_STS_OK;
unsigned int proc_bytes;
int status;
int status, intrc;
req = (struct request *) cqr->callback_data;
dasd_profile_end(cqr->block, cqr, req);
/*
* free_cp() returns the request block to its memory pool, so snapshot
* everything still needed from cqr before calling it - another CPU can
* reallocate and overwrite the block right after.
*/
proc_bytes = cqr->proc_bytes;
intrc = cqr->intrc;
status = cqr->block->base->discipline->free_cp(cqr, req);
if (status < 0)
error = errno_to_blk_status(status);
else if (status == 0) {
switch (cqr->intrc) {
switch (intrc) {
case -EPERM:
/*
* DASD doesn't implement SCSI/NVMe reservations, but it