Skip to content

Commit 48ae70d

Browse files
mikechristiemstsirkin
authored andcommitted
vhost_scsi: make SCSI cmd completion per vq
This patch separates the scsi cmd completion code paths so we can complete cmds based on their vq instead of having all cmds complete on the same worker/CPU. This will be useful with the next patches that allow us to create mulitple worker threads and bind them to different vqs, and we can have completions running on different threads/CPUs. Signed-off-by: Mike Christie <[email protected]> Reviewed-by: Stefan Hajnoczi <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 9e09d0e commit 48ae70d

File tree

1 file changed

+26
-30
lines changed

1 file changed

+26
-30
lines changed

drivers/vhost/scsi.c

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ MODULE_PARM_DESC(max_io_vqs, "Set the max number of IO virtqueues a vhost scsi d
167167

168168
struct vhost_scsi_virtqueue {
169169
struct vhost_virtqueue vq;
170+
struct vhost_scsi *vs;
170171
/*
171172
* Reference counting for inflight reqs, used for flush operation. At
172173
* each time, one reference tracks new commands submitted, while we
@@ -181,6 +182,9 @@ struct vhost_scsi_virtqueue {
181182
struct vhost_scsi_cmd *scsi_cmds;
182183
struct sbitmap scsi_tags;
183184
int max_cmds;
185+
186+
struct vhost_work completion_work;
187+
struct llist_head completion_list;
184188
};
185189

186190
struct vhost_scsi {
@@ -190,12 +194,8 @@ struct vhost_scsi {
190194

191195
struct vhost_dev dev;
192196
struct vhost_scsi_virtqueue *vqs;
193-
unsigned long *compl_bitmap;
194197
struct vhost_scsi_inflight **old_inflight;
195198

196-
struct vhost_work vs_completion_work; /* cmd completion work item */
197-
struct llist_head vs_completion_list; /* cmd completion queue */
198-
199199
struct vhost_work vs_event_work; /* evt injection work item */
200200
struct llist_head vs_event_list; /* evt injection queue */
201201

@@ -358,10 +358,11 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
358358
} else {
359359
struct vhost_scsi_cmd *cmd = container_of(se_cmd,
360360
struct vhost_scsi_cmd, tvc_se_cmd);
361-
struct vhost_scsi *vs = cmd->tvc_vhost;
361+
struct vhost_scsi_virtqueue *svq = container_of(cmd->tvc_vq,
362+
struct vhost_scsi_virtqueue, vq);
362363

363-
llist_add(&cmd->tvc_completion_list, &vs->vs_completion_list);
364-
vhost_work_queue(&vs->dev, &vs->vs_completion_work);
364+
llist_add(&cmd->tvc_completion_list, &svq->completion_list);
365+
vhost_vq_work_queue(&svq->vq, &svq->completion_work);
365366
}
366367
}
367368

@@ -509,17 +510,17 @@ static void vhost_scsi_evt_work(struct vhost_work *work)
509510
*/
510511
static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
511512
{
512-
struct vhost_scsi *vs = container_of(work, struct vhost_scsi,
513-
vs_completion_work);
513+
struct vhost_scsi_virtqueue *svq = container_of(work,
514+
struct vhost_scsi_virtqueue, completion_work);
514515
struct virtio_scsi_cmd_resp v_rsp;
515516
struct vhost_scsi_cmd *cmd, *t;
516517
struct llist_node *llnode;
517518
struct se_cmd *se_cmd;
518519
struct iov_iter iov_iter;
519-
int ret, vq;
520+
bool signal = false;
521+
int ret;
520522

521-
bitmap_zero(vs->compl_bitmap, vs->dev.nvqs);
522-
llnode = llist_del_all(&vs->vs_completion_list);
523+
llnode = llist_del_all(&svq->completion_list);
523524
llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) {
524525
se_cmd = &cmd->tvc_se_cmd;
525526

@@ -539,21 +540,17 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
539540
cmd->tvc_in_iovs, sizeof(v_rsp));
540541
ret = copy_to_iter(&v_rsp, sizeof(v_rsp), &iov_iter);
541542
if (likely(ret == sizeof(v_rsp))) {
542-
struct vhost_scsi_virtqueue *q;
543+
signal = true;
544+
543545
vhost_add_used(cmd->tvc_vq, cmd->tvc_vq_desc, 0);
544-
q = container_of(cmd->tvc_vq, struct vhost_scsi_virtqueue, vq);
545-
vq = q - vs->vqs;
546-
__set_bit(vq, vs->compl_bitmap);
547546
} else
548547
pr_err("Faulted on virtio_scsi_cmd_resp\n");
549548

550549
vhost_scsi_release_cmd_res(se_cmd);
551550
}
552551

553-
vq = -1;
554-
while ((vq = find_next_bit(vs->compl_bitmap, vs->dev.nvqs, vq + 1))
555-
< vs->dev.nvqs)
556-
vhost_signal(&vs->dev, &vs->vqs[vq].vq);
552+
if (signal)
553+
vhost_signal(&svq->vs->dev, &svq->vq);
557554
}
558555

559556
static struct vhost_scsi_cmd *
@@ -1770,6 +1767,7 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
17701767

17711768
static int vhost_scsi_open(struct inode *inode, struct file *f)
17721769
{
1770+
struct vhost_scsi_virtqueue *svq;
17731771
struct vhost_scsi *vs;
17741772
struct vhost_virtqueue **vqs;
17751773
int r = -ENOMEM, i, nvqs = vhost_scsi_max_io_vqs;
@@ -1788,10 +1786,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
17881786
}
17891787
nvqs += VHOST_SCSI_VQ_IO;
17901788

1791-
vs->compl_bitmap = bitmap_alloc(nvqs, GFP_KERNEL);
1792-
if (!vs->compl_bitmap)
1793-
goto err_compl_bitmap;
1794-
17951789
vs->old_inflight = kmalloc_array(nvqs, sizeof(*vs->old_inflight),
17961790
GFP_KERNEL | __GFP_ZERO);
17971791
if (!vs->old_inflight)
@@ -1806,7 +1800,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
18061800
if (!vqs)
18071801
goto err_local_vqs;
18081802

1809-
vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work);
18101803
vhost_work_init(&vs->vs_event_work, vhost_scsi_evt_work);
18111804

18121805
vs->vs_events_nr = 0;
@@ -1817,8 +1810,14 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
18171810
vs->vqs[VHOST_SCSI_VQ_CTL].vq.handle_kick = vhost_scsi_ctl_handle_kick;
18181811
vs->vqs[VHOST_SCSI_VQ_EVT].vq.handle_kick = vhost_scsi_evt_handle_kick;
18191812
for (i = VHOST_SCSI_VQ_IO; i < nvqs; i++) {
1820-
vqs[i] = &vs->vqs[i].vq;
1821-
vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
1813+
svq = &vs->vqs[i];
1814+
1815+
vqs[i] = &svq->vq;
1816+
svq->vs = vs;
1817+
init_llist_head(&svq->completion_list);
1818+
vhost_work_init(&svq->completion_work,
1819+
vhost_scsi_complete_cmd_work);
1820+
svq->vq.handle_kick = vhost_scsi_handle_kick;
18221821
}
18231822
vhost_dev_init(&vs->dev, vqs, nvqs, UIO_MAXIOV,
18241823
VHOST_SCSI_WEIGHT, 0, true, NULL);
@@ -1833,8 +1832,6 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
18331832
err_vqs:
18341833
kfree(vs->old_inflight);
18351834
err_inflight:
1836-
bitmap_free(vs->compl_bitmap);
1837-
err_compl_bitmap:
18381835
kvfree(vs);
18391836
err_vs:
18401837
return r;
@@ -1854,7 +1851,6 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
18541851
kfree(vs->dev.vqs);
18551852
kfree(vs->vqs);
18561853
kfree(vs->old_inflight);
1857-
bitmap_free(vs->compl_bitmap);
18581854
kvfree(vs);
18591855
return 0;
18601856
}

0 commit comments

Comments
 (0)