Signed-off-by: Christoph Hellwig --- drivers/scsi/scsi_lib.c | 67 ++++++++++++++++------------------------------- include/linux/blk-mq.h | 3 +++ 2 files changed, 25 insertions(+), 45 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 836f197..e6d87e3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1896,11 +1896,32 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) return q; } +static int scsi_init_request(void *data, struct blk_mq_hw_ctx *hctx, + struct request *rq, unsigned int nr) +{ + struct scsi_cmnd *cmd = rq->special; + + cmd->sense_buffer = kzalloc_node(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL, + hctx ? hctx->numa_node : -1); + if (!cmd->sense_buffer) + return -ENOMEM; + return 0; +} + +static void scsi_exit_request(struct blk_mq_hw_ctx *hctx, struct request *rq) +{ + struct scsi_cmnd *cmd = rq->special; + + kfree(cmd->sense_buffer); +} + static struct blk_mq_ops scsi_mq_ops = { .queue_rq = scsi_mq_queue_rq, .map_queue = blk_mq_map_queue, .alloc_hctx = blk_mq_alloc_single_hw_queue, .free_hctx = blk_mq_free_single_hw_queue, + .init_request = scsi_init_request, + .exit_request = scsi_exit_request, .complete = scsi_softirq_done, .timeout = scsi_times_out, }; @@ -1908,12 +1929,9 @@ static struct blk_mq_ops scsi_mq_ops = { struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev) { struct Scsi_Host *shost = sdev->host; - struct blk_mq_hw_ctx *hctx; struct request_queue *q; - struct request *rq; - struct scsi_cmnd *cmd; struct blk_mq_reg reg; - int i, j, sgl_size; + int sgl_size; memset(®, 0, sizeof(reg)); reg.ops = &scsi_mq_ops; @@ -1946,48 +1964,7 @@ struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev) __scsi_init_queue(shost, q); - /* - * XXX: figure out if we can get alignment right to allocate the sense - * buffer with the other chunks of memory. - * - * If not we'll need to find a way to have the blk-mq core call us to - * allocate/free commands so that we can properly clean up the - * allocation instead of leaking it. - */ - queue_for_each_hw_ctx(q, hctx, i) { - for (j = 0; j < hctx->queue_depth; j++) { - rq = hctx->rqs[j]; - cmd = rq->special; - - cmd->sense_buffer = kzalloc_node(SCSI_SENSE_BUFFERSIZE, - GFP_KERNEL, reg.numa_node); - if (!cmd->sense_buffer) - goto out_free_sense_buffers; - } - } - - rq = q->flush_rq; - cmd = blk_mq_rq_to_pdu(rq); - - cmd->sense_buffer = kzalloc_node(SCSI_SENSE_BUFFERSIZE, - GFP_KERNEL, reg.numa_node); - if (!cmd->sense_buffer) - goto out_free_sense_buffers; - return q; - -out_free_sense_buffers: - queue_for_each_hw_ctx(q, hctx, i) { - for (j = 0; j < hctx->queue_depth; j++) { - rq = hctx->rqs[j]; - cmd = rq->special; - - kfree(cmd->sense_buffer); - } - } - - blk_cleanup_queue(q); - return NULL; } /* diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 4d34957..ff194f8 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -68,6 +68,7 @@ typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int); typedef void (exit_hctx_fn)(struct blk_mq_hw_ctx *, unsigned int); typedef int (init_request_fn)(void *, struct blk_mq_hw_ctx *, struct request *, unsigned int); +typedef void (exit_request_fn)(struct blk_mq_hw_ctx *, struct request *); struct blk_mq_ops { /* @@ -104,8 +105,10 @@ struct blk_mq_ops { /* * Called for every command allocated by the block layer to allow * the driver to set up driver specific data. + * Ditto for exit/teardown. */ init_request_fn *init_request; + exit_request_fn *exit_request; }; enum { -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/