Skip to content

Commit 3c81bdd

Browse files
committed
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull vhost infrastructure updates from Michael S. Tsirkin: "This reworks vhost core dropping unnecessary RCU uses in favor of VQ mutexes which are used on fast path anyway. This fixes worst-case latency for users which change the memory mappings a lot. Memory allocation for vhost-net now supports fallback on vmalloc (same as for vhost-scsi) this makes it possible to create the device on systems where memory is very fragmented, with slightly lower performance" * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: vhost: move memory pointer to VQs vhost: move acked_features to VQs vhost: replace rcu with mutex vhost-net: extend device allocation to vmalloc
2 parents 7ec6131 + 47283be commit 3c81bdd

File tree

5 files changed

+101
-87
lines changed

5 files changed

+101
-87
lines changed

drivers/vhost/net.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/workqueue.h>
1818
#include <linux/file.h>
1919
#include <linux/slab.h>
20+
#include <linux/vmalloc.h>
2021

2122
#include <linux/net.h>
2223
#include <linux/if_packet.h>
@@ -373,7 +374,7 @@ static void handle_tx(struct vhost_net *net)
373374
% UIO_MAXIOV == nvq->done_idx))
374375
break;
375376

376-
head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
377+
head = vhost_get_vq_desc(vq, vq->iov,
377378
ARRAY_SIZE(vq->iov),
378379
&out, &in,
379380
NULL, NULL);
@@ -505,7 +506,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
505506
r = -ENOBUFS;
506507
goto err;
507508
}
508-
r = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
509+
r = vhost_get_vq_desc(vq, vq->iov + seg,
509510
ARRAY_SIZE(vq->iov) - seg, &out,
510511
&in, log, log_num);
511512
if (unlikely(r < 0))
@@ -584,9 +585,9 @@ static void handle_rx(struct vhost_net *net)
584585
vhost_hlen = nvq->vhost_hlen;
585586
sock_hlen = nvq->sock_hlen;
586587

587-
vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
588+
vq_log = unlikely(vhost_has_feature(vq, VHOST_F_LOG_ALL)) ?
588589
vq->log : NULL;
589-
mergeable = vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF);
590+
mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF);
590591

591592
while ((sock_len = peek_head_len(sock->sk))) {
592593
sock_len += sock_hlen;
@@ -699,18 +700,30 @@ static void handle_rx_net(struct vhost_work *work)
699700
handle_rx(net);
700701
}
701702

703+
static void vhost_net_free(void *addr)
704+
{
705+
if (is_vmalloc_addr(addr))
706+
vfree(addr);
707+
else
708+
kfree(addr);
709+
}
710+
702711
static int vhost_net_open(struct inode *inode, struct file *f)
703712
{
704-
struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL);
713+
struct vhost_net *n;
705714
struct vhost_dev *dev;
706715
struct vhost_virtqueue **vqs;
707716
int i;
708717

709-
if (!n)
710-
return -ENOMEM;
718+
n = kmalloc(sizeof *n, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
719+
if (!n) {
720+
n = vmalloc(sizeof *n);
721+
if (!n)
722+
return -ENOMEM;
723+
}
711724
vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
712725
if (!vqs) {
713-
kfree(n);
726+
vhost_net_free(n);
714727
return -ENOMEM;
715728
}
716729

@@ -827,7 +840,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
827840
* since jobs can re-queue themselves. */
828841
vhost_net_flush(n);
829842
kfree(n->dev.vqs);
830-
kfree(n);
843+
vhost_net_free(n);
831844
return 0;
832845
}
833846

@@ -1038,15 +1051,13 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features)
10381051
mutex_unlock(&n->dev.mutex);
10391052
return -EFAULT;
10401053
}
1041-
n->dev.acked_features = features;
1042-
smp_wmb();
10431054
for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
10441055
mutex_lock(&n->vqs[i].vq.mutex);
1056+
n->vqs[i].vq.acked_features = features;
10451057
n->vqs[i].vhost_hlen = vhost_hlen;
10461058
n->vqs[i].sock_hlen = sock_hlen;
10471059
mutex_unlock(&n->vqs[i].vq.mutex);
10481060
}
1049-
vhost_net_flush(n);
10501061
mutex_unlock(&n->dev.mutex);
10511062
return 0;
10521063
}

drivers/vhost/scsi.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ tcm_vhost_do_evt_work(struct vhost_scsi *vs, struct tcm_vhost_evt *evt)
606606

607607
again:
608608
vhost_disable_notify(&vs->dev, vq);
609-
head = vhost_get_vq_desc(&vs->dev, vq, vq->iov,
609+
head = vhost_get_vq_desc(vq, vq->iov,
610610
ARRAY_SIZE(vq->iov), &out, &in,
611611
NULL, NULL);
612612
if (head < 0) {
@@ -945,7 +945,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
945945
vhost_disable_notify(&vs->dev, vq);
946946

947947
for (;;) {
948-
head = vhost_get_vq_desc(&vs->dev, vq, vq->iov,
948+
head = vhost_get_vq_desc(vq, vq->iov,
949949
ARRAY_SIZE(vq->iov), &out, &in,
950950
NULL, NULL);
951951
pr_debug("vhost_get_vq_desc: head: %d, out: %u in: %u\n",
@@ -1373,6 +1373,9 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs,
13731373

13741374
static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
13751375
{
1376+
struct vhost_virtqueue *vq;
1377+
int i;
1378+
13761379
if (features & ~VHOST_SCSI_FEATURES)
13771380
return -EOPNOTSUPP;
13781381

@@ -1382,9 +1385,13 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
13821385
mutex_unlock(&vs->dev.mutex);
13831386
return -EFAULT;
13841387
}
1385-
vs->dev.acked_features = features;
1386-
smp_wmb();
1387-
vhost_scsi_flush(vs);
1388+
1389+
for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
1390+
vq = &vs->vqs[i].vq;
1391+
mutex_lock(&vq->mutex);
1392+
vq->acked_features = features;
1393+
mutex_unlock(&vq->mutex);
1394+
}
13881395
mutex_unlock(&vs->dev.mutex);
13891396
return 0;
13901397
}
@@ -1591,10 +1598,6 @@ tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg,
15911598
return;
15921599

15931600
mutex_lock(&vs->dev.mutex);
1594-
if (!vhost_has_feature(&vs->dev, VIRTIO_SCSI_F_HOTPLUG)) {
1595-
mutex_unlock(&vs->dev.mutex);
1596-
return;
1597-
}
15981601

15991602
if (plug)
16001603
reason = VIRTIO_SCSI_EVT_RESET_RESCAN;
@@ -1603,8 +1606,9 @@ tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg,
16031606

16041607
vq = &vs->vqs[VHOST_SCSI_VQ_EVT].vq;
16051608
mutex_lock(&vq->mutex);
1606-
tcm_vhost_send_evt(vs, tpg, lun,
1607-
VIRTIO_SCSI_T_TRANSPORT_RESET, reason);
1609+
if (vhost_has_feature(vq, VIRTIO_SCSI_F_HOTPLUG))
1610+
tcm_vhost_send_evt(vs, tpg, lun,
1611+
VIRTIO_SCSI_T_TRANSPORT_RESET, reason);
16081612
mutex_unlock(&vq->mutex);
16091613
mutex_unlock(&vs->dev.mutex);
16101614
}

drivers/vhost/test.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static void handle_vq(struct vhost_test *n)
5353
vhost_disable_notify(&n->dev, vq);
5454

5555
for (;;) {
56-
head = vhost_get_vq_desc(&n->dev, vq, vq->iov,
56+
head = vhost_get_vq_desc(vq, vq->iov,
5757
ARRAY_SIZE(vq->iov),
5858
&out, &in,
5959
NULL, NULL);
@@ -241,15 +241,18 @@ static long vhost_test_reset_owner(struct vhost_test *n)
241241

242242
static int vhost_test_set_features(struct vhost_test *n, u64 features)
243243
{
244+
struct vhost_virtqueue *vq;
245+
244246
mutex_lock(&n->dev.mutex);
245247
if ((features & (1 << VHOST_F_LOG_ALL)) &&
246248
!vhost_log_access_ok(&n->dev)) {
247249
mutex_unlock(&n->dev.mutex);
248250
return -EFAULT;
249251
}
250-
n->dev.acked_features = features;
251-
smp_wmb();
252-
vhost_test_flush(n);
252+
vq = &n->vqs[VHOST_TEST_VQ];
253+
mutex_lock(&vq->mutex);
254+
vq->acked_features = features;
255+
mutex_unlock(&vq->mutex);
253256
mutex_unlock(&n->dev.mutex);
254257
return 0;
255258
}

0 commit comments

Comments
 (0)