On 2020-08-27 13:33, Alan Stern wrote:
It may not need to be that complicated. what about something like this?
Index: usb-devel/block/blk-core.c
--- usb-devel.orig/block/blk-core.c +++ usb-devel/block/blk-core.c @@ -420,11 +420,11 @@ EXPORT_SYMBOL(blk_cleanup_queue); /**
- blk_queue_enter() - try to increase q->q_usage_counter
- @q: request queue pointer
- @flags: BLK_MQ_REQ_NOWAIT and/or BLK_MQ_REQ_PREEMPT
*/
- @flags: BLK_MQ_REQ_NOWAIT and/or BLK_MQ_REQ_PM
int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags) {
- const bool pm = flags & BLK_MQ_REQ_PREEMPT;
- const bool pm = flags & BLK_MQ_REQ_PM;
while (true) { bool success = false; @@ -626,7 +626,8 @@ struct request *blk_get_request(struct r struct request *req; WARN_ON_ONCE(op & REQ_NOWAIT);
- WARN_ON_ONCE(flags & ~(BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_PREEMPT));
- WARN_ON_ONCE(flags & ~(BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_PREEMPT |
BLK_MQ_REQ_PM));
req = blk_mq_alloc_request(q, op, flags); if (!IS_ERR(req) && q->mq_ops->initialize_rq_fn) Index: usb-devel/drivers/scsi/scsi_lib.c =================================================================== --- usb-devel.orig/drivers/scsi/scsi_lib.c +++ usb-devel/drivers/scsi/scsi_lib.c @@ -245,11 +245,15 @@ int __scsi_execute(struct scsi_device *s { struct request *req; struct scsi_request *rq;
- blk_mq_req_flags_t mq_req_flags; int ret = DRIVER_ERROR << 24;
- mq_req_flags = BLK_MQ_REQ_PREEMPT;
- if (rq_flags & RQF_PM)
req = blk_get_request(sdev->request_queue, data_direction == DMA_TO_DEVICE ?mq_req_flags |= BLK_MQ_REQ_PM;
REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, BLK_MQ_REQ_PREEMPT);
if (IS_ERR(req)) return ret; rq = scsi_req(req);REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, mq_req_flags);
Index: usb-devel/include/linux/blk-mq.h
--- usb-devel.orig/include/linux/blk-mq.h +++ usb-devel/include/linux/blk-mq.h @@ -435,6 +435,8 @@ enum { BLK_MQ_REQ_RESERVED = (__force blk_mq_req_flags_t)(1 << 1), /* set RQF_PREEMPT */ BLK_MQ_REQ_PREEMPT = (__force blk_mq_req_flags_t)(1 << 3),
- /* used for power management */
- BLK_MQ_REQ_PM = (__force blk_mq_req_flags_t)(1 << 4),
}; struct request *blk_mq_alloc_request(struct request_queue *q, unsigned int op,
I think this patch will break SCSI domain validation. The SCSI domain validation code calls scsi_device_quiesce() and that function in turn calls blk_set_pm_only(). The SCSI domain validation code submits SCSI commands with the BLK_MQ_REQ_PREEMPT flag. Since the above code postpones such requests while blk_set_pm_only() is in effect, I think the above patch will cause the SCSI domain validation code to deadlock.
Bart.