Re: [PATCH v7 08/19] s390/dasd: Add infrastructure for ESE full-track write

[email protected] Sat, 01 Aug 2026 18:21:53 +0000
Newsgroups org.kernel.vger.linux-s390
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Block Layer Double Completion due to incorrect handling of aborted origin requests
--

--- Patch [8]: [PATCH v7 08/19] s390/dasd: Add infrastructure for ESE full-track write ---
commit f91cc6aad616495ff0e65f3a49886e5137daade3
Author: Stefan Haberland <[email protected]>

s390/dasd: Add infrastructure for ESE full-track write

This commit adds the driver internals to build WRITE_FULL_TRACK FCX channel
programs in response to unformatted tracks on ESE devices. It introduces
new CQR states (DASD_CQR_ABORT/ABORTED) intended to retire the origin CQR
of a replaced write without completing it to the block layer.

> diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
> --- a/drivers/s390/block/dasd.c
> +++ b/drivers/s390/block/dasd.c
[ ... ]
> @@ -1884,6 +1924,17 @@ static void __dasd_process_cqr(struct dasd_device *device,
>  	case DASD_CQR_CLEARED:
>  		cqr->status = DASD_CQR_TERMINATED;
>  		break;
> +	case DASD_CQR_ABORT:
> +		cqr->status = DASD_CQR_ABORTED;
> +		/*
> +		 * ABORT is only set on the block-layer origin write that a
> +		 * full-track format replaces. Clear the callback so the request
> +		 * is not completed here - the replacement completes it. Internal
> +		 * requests never take this path, so no sleep_on waiter is left
> +		 * without its wakeup.
> +		 */
> +		cqr->callback = NULL;

[Severity: High]
Will clearing cqr->callback actually prevent the block layer completion?

Clearing the callback avoids the immediate wakeup triggered at the end of
__dasd_process_cqr(), but it appears the request might still be completed
by the block tasklet.

> +		break;
>  	default:
>  		dev_err(&device->cdev->dev,
>  			"Unexpected CQR status %02x", cqr->status);
[ ... ]
> @@ -2767,7 +2819,8 @@ static void __dasd_process_block_ccw_queue(struct dasd_block *block,
>  		if (cqr->status != DASD_CQR_DONE &&
>  		    cqr->status != DASD_CQR_FAILED &&
>  		    cqr->status != DASD_CQR_NEED_ERP &&
> -		    cqr->status != DASD_CQR_TERMINATED)
> +		    cqr->status != DASD_CQR_TERMINATED &&
> +		    cqr->status != DASD_CQR_ABORTED)
>  			continue;
>  
>  		if (cqr->status == DASD_CQR_TERMINATED) {

[Severity: High]
If DASD_CQR_ABORTED requests fall through this check, they are moved to the
final_queue. When dasd_block_tasklet() executes, it iterates over
final_queue and calls __dasd_cleanup_cqr() unconditionally for each request:

dasd_block_tasklet()
    list_for_each_entry_safe(cqr, n, &final_queue, blocklist)
        __dasd_cleanup_cqr(cqr);

Since __dasd_cleanup_cqr() ignores cqr->callback and goes on to call
blk_mq_end_request(req, error), could this cause a double-completion in the
block layer, given that the replacement format CQR is also expected to
complete this same request?

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=8