Add function to check if a SCSI command originates from the reserved tag pool and update scsi_put_reserved_cmd() to only free commands if they originate from the reserved tag pool. Signed-off-by: Hannes Reinecke <hare@xxxxxxxx> --- block/blk-mq.c | 15 +++++++++++++++ drivers/scsi/scsi_lib.c | 7 +++++-- include/linux/blk-mq.h | 1 + include/scsi/scsi_cmnd.h | 13 +++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 8e56884fd2e9..44482aaed11e 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -604,6 +604,21 @@ static void __blk_mq_complete_request(struct request *rq) put_cpu(); } +/** + * blk_mq_rq_is_reserved - Check for reserved request + * + * @rq: Request to check + * + * Returns true if the request originates from the reserved tag pool. + */ +bool blk_mq_rq_is_reserved(struct request *rq) +{ + struct blk_mq_hw_ctx *hctx = rq->mq_hctx; + + return blk_mq_tag_is_reserved(hctx->tags, rq->tag); +} +EXPORT_SYMBOL_GPL(blk_mq_rq_is_reserved); + static void hctx_unlock(struct blk_mq_hw_ctx *hctx, int srcu_idx) __releases(hctx->srcu) { diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index d0972744ea7f..30f9ca9fce22 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1930,9 +1930,12 @@ EXPORT_SYMBOL_GPL(scsi_get_reserved_cmd); */ void scsi_put_reserved_cmd(struct scsi_cmnd *scmd) { - struct request *rq = blk_mq_rq_from_pdu(scmd); + struct request *rq; - blk_mq_free_request(rq); + if (scmd && scsi_cmd_is_reserved(scmd)) { + rq = blk_mq_rq_from_pdu(scmd); + blk_mq_free_request(rq); + } } EXPORT_SYMBOL_GPL(scsi_put_reserved_cmd); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index f389d7c724bd..c186dc25fc1c 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -494,6 +494,7 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list); void blk_mq_kick_requeue_list(struct request_queue *q); void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs); bool blk_mq_complete_request(struct request *rq); +bool blk_mq_rq_is_reserved(struct request *rq); bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, struct bio *bio, unsigned int nr_segs); bool blk_mq_queue_stopped(struct request_queue *q); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 80ac89e47b47..2cd894fbdcfa 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -159,6 +159,19 @@ static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) return *(struct scsi_driver **)cmd->request->rq_disk->private_data; } +/** + * scsi_cmd_is_reserved - check for reserved scsi command + * @scmd: command to check + * + * Returns true if @scmd originates from the reserved tag pool. + */ +static inline bool scsi_cmd_is_reserved(struct scsi_cmnd *scmd) +{ + struct request *rq = blk_mq_rq_from_pdu(scmd); + + return blk_mq_rq_is_reserved(rq); +} + extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, -- 2.16.4