Passthrough request from userspace has one active block_device/disk associated, so they can be accounted via rq->q->disk. For other passthrough request, there may not be disk/block_device for the queue, since either the queue has not a disk or the disk may be deleted already. Add flag of BLK_MQ_REQ_USER_IO for only accounting passthrough request from userspace. Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> --- block/blk-mq.c | 13 ++++++++++++- drivers/nvme/host/ioctl.c | 2 +- drivers/scsi/scsi_ioctl.c | 3 ++- include/linux/blk-mq.h | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index a6d4780580fc..0d25cc5778c9 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -336,6 +336,17 @@ void blk_rq_init(struct request_queue *q, struct request *rq) } EXPORT_SYMBOL(blk_rq_init); +static inline bool blk_mq_io_may_account(struct blk_mq_alloc_data *data) +{ + if (!blk_op_is_passthrough(data->cmd_flags)) + return true; + + if (data->flags & BLK_MQ_REQ_USER_IO) + return true; + + return false; +} + static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, struct blk_mq_tags *tags, unsigned int tag, u64 alloc_time_ns) { @@ -351,7 +362,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data, if (data->flags & BLK_MQ_REQ_PM) data->rq_flags |= RQF_PM; - if (blk_queue_io_stat(q)) + if (blk_queue_io_stat(q) && blk_mq_io_may_account(data)) data->rq_flags |= RQF_IO_STAT; rq->rq_flags = data->rq_flags; diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index 22314962842d..f94afc38a6e3 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -66,7 +66,7 @@ static int nvme_submit_user_cmd(struct request_queue *q, void *meta = NULL; int ret; - req = nvme_alloc_request(q, cmd, 0); + req = nvme_alloc_request(q, cmd, BLK_MQ_REQ_USER_IO); if (IS_ERR(req)) return PTR_ERR(req); diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index e13fd380deb6..b262fe06dacc 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -440,7 +440,8 @@ static int sg_io(struct scsi_device *sdev, struct sg_io_hdr *hdr, fmode_t mode) ret = -ENOMEM; rq = scsi_alloc_request(sdev->request_queue, writing ? - REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0); + REQ_OP_DRV_OUT : REQ_OP_DRV_IN, + BLK_MQ_REQ_USER_IO); if (IS_ERR(rq)) return PTR_ERR(rq); req = scsi_req(rq); diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index d319ffa59354..d2ad2ed11723 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -709,6 +709,8 @@ enum { BLK_MQ_REQ_RESERVED = (__force blk_mq_req_flags_t)(1 << 1), /* set RQF_PM */ BLK_MQ_REQ_PM = (__force blk_mq_req_flags_t)(1 << 2), + /* user IO request */ + BLK_MQ_REQ_USER_IO = (__force blk_mq_req_flags_t)(1 << 3), }; struct request *blk_mq_alloc_request(struct request_queue *q, unsigned int op, -- 2.31.1