You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
blk-mq: split out tag initialization, support shared tags
Add a new blk_mq_tag_set structure that gets set up before we initialize the queue. A single blk_mq_tag_set structure can be shared by multiple queues. Signed-off-by: Christoph Hellwig <hch@lst.de> Modular export of blk_mq_{alloc,free}_tagset added by me. Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
committed by
Jens Axboe
parent
ed44832dea
commit
24d2f90309
+31
-17
@@ -30,6 +30,9 @@ struct virtio_blk
|
||||
/* The disk structure for the kernel. */
|
||||
struct gendisk *disk;
|
||||
|
||||
/* Block layer tags. */
|
||||
struct blk_mq_tag_set tag_set;
|
||||
|
||||
/* Process context for config space updates */
|
||||
struct work_struct config_work;
|
||||
|
||||
@@ -480,8 +483,9 @@ static const struct device_attribute dev_attr_cache_type_rw =
|
||||
__ATTR(cache_type, S_IRUGO|S_IWUSR,
|
||||
virtblk_cache_type_show, virtblk_cache_type_store);
|
||||
|
||||
static int virtblk_init_request(void *data, struct blk_mq_hw_ctx *hctx,
|
||||
struct request *rq, unsigned int nr)
|
||||
static int virtblk_init_request(void *data, struct request *rq,
|
||||
unsigned int hctx_idx, unsigned int request_idx,
|
||||
unsigned int numa_node)
|
||||
{
|
||||
struct virtio_blk *vblk = data;
|
||||
struct virtblk_req *vbr = blk_mq_rq_to_pdu(rq);
|
||||
@@ -495,18 +499,12 @@ static struct blk_mq_ops virtio_mq_ops = {
|
||||
.map_queue = blk_mq_map_queue,
|
||||
.alloc_hctx = blk_mq_alloc_single_hw_queue,
|
||||
.free_hctx = blk_mq_free_single_hw_queue,
|
||||
.init_request = virtblk_init_request,
|
||||
.complete = virtblk_request_done,
|
||||
.init_request = virtblk_init_request,
|
||||
};
|
||||
|
||||
static struct blk_mq_reg virtio_mq_reg = {
|
||||
.ops = &virtio_mq_ops,
|
||||
.nr_hw_queues = 1,
|
||||
.queue_depth = 0, /* Set in virtblk_probe */
|
||||
.numa_node = NUMA_NO_NODE,
|
||||
.flags = BLK_MQ_F_SHOULD_MERGE,
|
||||
};
|
||||
module_param_named(queue_depth, virtio_mq_reg.queue_depth, uint, 0444);
|
||||
static unsigned int virtblk_queue_depth;
|
||||
module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
|
||||
|
||||
static int virtblk_probe(struct virtio_device *vdev)
|
||||
{
|
||||
@@ -562,20 +560,32 @@ static int virtblk_probe(struct virtio_device *vdev)
|
||||
}
|
||||
|
||||
/* Default queue sizing is to fill the ring. */
|
||||
if (!virtio_mq_reg.queue_depth) {
|
||||
virtio_mq_reg.queue_depth = vblk->vq->num_free;
|
||||
if (!virtblk_queue_depth) {
|
||||
virtblk_queue_depth = vblk->vq->num_free;
|
||||
/* ... but without indirect descs, we use 2 descs per req */
|
||||
if (!virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC))
|
||||
virtio_mq_reg.queue_depth /= 2;
|
||||
virtblk_queue_depth /= 2;
|
||||
}
|
||||
virtio_mq_reg.cmd_size =
|
||||
|
||||
memset(&vblk->tag_set, 0, sizeof(vblk->tag_set));
|
||||
vblk->tag_set.ops = &virtio_mq_ops;
|
||||
vblk->tag_set.nr_hw_queues = 1;
|
||||
vblk->tag_set.queue_depth = virtblk_queue_depth;
|
||||
vblk->tag_set.numa_node = NUMA_NO_NODE;
|
||||
vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
|
||||
vblk->tag_set.cmd_size =
|
||||
sizeof(struct virtblk_req) +
|
||||
sizeof(struct scatterlist) * sg_elems;
|
||||
vblk->tag_set.driver_data = vblk;
|
||||
|
||||
q = vblk->disk->queue = blk_mq_init_queue(&virtio_mq_reg, vblk);
|
||||
err = blk_mq_alloc_tag_set(&vblk->tag_set);
|
||||
if (err)
|
||||
goto out_put_disk;
|
||||
|
||||
q = vblk->disk->queue = blk_mq_init_queue(&vblk->tag_set);
|
||||
if (!q) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_disk;
|
||||
goto out_free_tags;
|
||||
}
|
||||
|
||||
q->queuedata = vblk;
|
||||
@@ -678,6 +688,8 @@ static int virtblk_probe(struct virtio_device *vdev)
|
||||
out_del_disk:
|
||||
del_gendisk(vblk->disk);
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
out_free_tags:
|
||||
blk_mq_free_tag_set(&vblk->tag_set);
|
||||
out_put_disk:
|
||||
put_disk(vblk->disk);
|
||||
out_free_vq:
|
||||
@@ -704,6 +716,8 @@ static void virtblk_remove(struct virtio_device *vdev)
|
||||
del_gendisk(vblk->disk);
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
|
||||
blk_mq_free_tag_set(&vblk->tag_set);
|
||||
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user