Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost

Pull virtio fixes from Michael Tsirkin:
"Several fixes, some of them for CVEs"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
vhost: scsi: add weight support
vhost: vsock: add weight support
vhost_net: fix possible infinite loop
vhost: introduce vhost_exceeds_weight()
virtio: Fix indentation of VIRTIO_MMIO
virtio: add unlikely() to WARN_ON_ONCE()

+77 -48
+14 -27
drivers/vhost/net.c
··· 604 604 return iov_iter_count(iter); 605 605 } 606 606 607 - static bool vhost_exceeds_weight(int pkts, int total_len) 608 - { 609 - return total_len >= VHOST_NET_WEIGHT || 610 - pkts >= VHOST_NET_PKT_WEIGHT; 611 - } 612 - 613 607 static int get_tx_bufs(struct vhost_net *net, 614 608 struct vhost_net_virtqueue *nvq, 615 609 struct msghdr *msg, ··· 773 779 int sent_pkts = 0; 774 780 bool sock_can_batch = (sock->sk->sk_sndbuf == INT_MAX); 775 781 776 - for (;;) { 782 + do { 777 783 bool busyloop_intr = false; 778 784 779 785 if (nvq->done_idx == VHOST_NET_BATCH) ··· 839 845 vq->heads[nvq->done_idx].id = cpu_to_vhost32(vq, head); 840 846 vq->heads[nvq->done_idx].len = 0; 841 847 ++nvq->done_idx; 842 - if (vhost_exceeds_weight(++sent_pkts, total_len)) { 843 - vhost_poll_queue(&vq->poll); 844 - break; 845 - } 846 - } 848 + } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len))); 847 849 848 850 vhost_tx_batch(net, nvq, sock, &msg); 849 851 } ··· 864 874 bool zcopy_used; 865 875 int sent_pkts = 0; 866 876 867 - for (;;) { 877 + do { 868 878 bool busyloop_intr; 869 879 870 880 /* Release DMAs done buffers first */ ··· 941 951 else 942 952 vhost_zerocopy_signal_used(net, vq); 943 953 vhost_net_tx_packet(net); 944 - if (unlikely(vhost_exceeds_weight(++sent_pkts, total_len))) { 945 - vhost_poll_queue(&vq->poll); 946 - break; 947 - } 948 - } 954 + } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len))); 949 955 } 950 956 951 957 /* Expects to be always run from workqueue - which acts as ··· 1139 1153 vq->log : NULL; 1140 1154 mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF); 1141 1155 1142 - while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk, 1143 - &busyloop_intr))) { 1156 + do { 1157 + sock_len = vhost_net_rx_peek_head_len(net, sock->sk, 1158 + &busyloop_intr); 1159 + if (!sock_len) 1160 + break; 1144 1161 sock_len += sock_hlen; 1145 1162 vhost_len = sock_len + vhost_hlen; 1146 1163 headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx, ··· 1228 1239 vhost_log_write(vq, vq_log, log, vhost_len, 1229 1240 vq->iov, in); 1230 1241 total_len += vhost_len; 1231 - if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) { 1232 - vhost_poll_queue(&vq->poll); 1233 - goto out; 1234 - } 1235 - } 1242 + } while (likely(!vhost_exceeds_weight(vq, ++recv_pkts, total_len))); 1243 + 1236 1244 if (unlikely(busyloop_intr)) 1237 1245 vhost_poll_queue(&vq->poll); 1238 - else 1246 + else if (!sock_len) 1239 1247 vhost_net_enable_vq(net, vq); 1240 1248 out: 1241 1249 vhost_net_signal_used(nvq); ··· 1324 1338 vhost_net_buf_init(&n->vqs[i].rxq); 1325 1339 } 1326 1340 vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX, 1327 - UIO_MAXIOV + VHOST_NET_BATCH); 1341 + UIO_MAXIOV + VHOST_NET_BATCH, 1342 + VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT); 1328 1343 1329 1344 vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev); 1330 1345 vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
+14 -7
drivers/vhost/scsi.c
··· 57 57 #define VHOST_SCSI_PREALLOC_UPAGES 2048 58 58 #define VHOST_SCSI_PREALLOC_PROT_SGLS 2048 59 59 60 + /* Max number of requests before requeueing the job. 61 + * Using this limit prevents one virtqueue from starving others with 62 + * request. 63 + */ 64 + #define VHOST_SCSI_WEIGHT 256 65 + 60 66 struct vhost_scsi_inflight { 61 67 /* Wait for the flush operation to finish */ 62 68 struct completion comp; ··· 918 912 struct iov_iter in_iter, prot_iter, data_iter; 919 913 u64 tag; 920 914 u32 exp_data_len, data_direction; 921 - int ret, prot_bytes; 915 + int ret, prot_bytes, c = 0; 922 916 u16 lun; 923 917 u8 task_attr; 924 918 bool t10_pi = vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI); ··· 938 932 939 933 vhost_disable_notify(&vs->dev, vq); 940 934 941 - for (;;) { 935 + do { 942 936 ret = vhost_scsi_get_desc(vs, vq, &vc); 943 937 if (ret) 944 938 goto err; ··· 1118 1112 break; 1119 1113 else if (ret == -EIO) 1120 1114 vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out); 1121 - } 1115 + } while (likely(!vhost_exceeds_weight(vq, ++c, 0))); 1122 1116 out: 1123 1117 mutex_unlock(&vq->mutex); 1124 1118 } ··· 1177 1171 } v_req; 1178 1172 struct vhost_scsi_ctx vc; 1179 1173 size_t typ_size; 1180 - int ret; 1174 + int ret, c = 0; 1181 1175 1182 1176 mutex_lock(&vq->mutex); 1183 1177 /* ··· 1191 1185 1192 1186 vhost_disable_notify(&vs->dev, vq); 1193 1187 1194 - for (;;) { 1188 + do { 1195 1189 ret = vhost_scsi_get_desc(vs, vq, &vc); 1196 1190 if (ret) 1197 1191 goto err; ··· 1270 1264 break; 1271 1265 else if (ret == -EIO) 1272 1266 vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out); 1273 - } 1267 + } while (likely(!vhost_exceeds_weight(vq, ++c, 0))); 1274 1268 out: 1275 1269 mutex_unlock(&vq->mutex); 1276 1270 } ··· 1627 1621 vqs[i] = &vs->vqs[i].vq; 1628 1622 vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick; 1629 1623 } 1630 - vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV); 1624 + vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV, 1625 + VHOST_SCSI_WEIGHT, 0); 1631 1626 1632 1627 vhost_scsi_init_inflight(vs, NULL); 1633 1628
+19 -1
drivers/vhost/vhost.c
··· 413 413 vhost_vq_free_iovecs(dev->vqs[i]); 414 414 } 415 415 416 + bool vhost_exceeds_weight(struct vhost_virtqueue *vq, 417 + int pkts, int total_len) 418 + { 419 + struct vhost_dev *dev = vq->dev; 420 + 421 + if ((dev->byte_weight && total_len >= dev->byte_weight) || 422 + pkts >= dev->weight) { 423 + vhost_poll_queue(&vq->poll); 424 + return true; 425 + } 426 + 427 + return false; 428 + } 429 + EXPORT_SYMBOL_GPL(vhost_exceeds_weight); 430 + 416 431 void vhost_dev_init(struct vhost_dev *dev, 417 - struct vhost_virtqueue **vqs, int nvqs, int iov_limit) 432 + struct vhost_virtqueue **vqs, int nvqs, 433 + int iov_limit, int weight, int byte_weight) 418 434 { 419 435 struct vhost_virtqueue *vq; 420 436 int i; ··· 444 428 dev->mm = NULL; 445 429 dev->worker = NULL; 446 430 dev->iov_limit = iov_limit; 431 + dev->weight = weight; 432 + dev->byte_weight = byte_weight; 447 433 init_llist_head(&dev->work_list); 448 434 init_waitqueue_head(&dev->wait); 449 435 INIT_LIST_HEAD(&dev->read_list);
+4 -1
drivers/vhost/vhost.h
··· 171 171 struct list_head pending_list; 172 172 wait_queue_head_t wait; 173 173 int iov_limit; 174 + int weight; 175 + int byte_weight; 174 176 }; 175 177 178 + bool vhost_exceeds_weight(struct vhost_virtqueue *vq, int pkts, int total_len); 176 179 void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, 177 - int nvqs, int iov_limit); 180 + int nvqs, int iov_limit, int weight, int byte_weight); 178 181 long vhost_dev_set_owner(struct vhost_dev *dev); 179 182 bool vhost_dev_has_owner(struct vhost_dev *dev); 180 183 long vhost_dev_check_owner(struct vhost_dev *);
+21 -7
drivers/vhost/vsock.c
··· 21 21 #include "vhost.h" 22 22 23 23 #define VHOST_VSOCK_DEFAULT_HOST_CID 2 24 + /* Max number of bytes transferred before requeueing the job. 25 + * Using this limit prevents one virtqueue from starving others. */ 26 + #define VHOST_VSOCK_WEIGHT 0x80000 27 + /* Max number of packets transferred before requeueing the job. 28 + * Using this limit prevents one virtqueue from starving others with 29 + * small pkts. 30 + */ 31 + #define VHOST_VSOCK_PKT_WEIGHT 256 24 32 25 33 enum { 26 34 VHOST_VSOCK_FEATURES = VHOST_FEATURES, ··· 86 78 struct vhost_virtqueue *vq) 87 79 { 88 80 struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX]; 81 + int pkts = 0, total_len = 0; 89 82 bool added = false; 90 83 bool restart_tx = false; 91 84 ··· 98 89 /* Avoid further vmexits, we're already processing the virtqueue */ 99 90 vhost_disable_notify(&vsock->dev, vq); 100 91 101 - for (;;) { 92 + do { 102 93 struct virtio_vsock_pkt *pkt; 103 94 struct iov_iter iov_iter; 104 95 unsigned out, in; ··· 183 174 */ 184 175 virtio_transport_deliver_tap_pkt(pkt); 185 176 177 + total_len += pkt->len; 186 178 virtio_transport_free_pkt(pkt); 187 - } 179 + } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); 188 180 if (added) 189 181 vhost_signal(&vsock->dev, vq); 190 182 ··· 360 350 struct vhost_vsock *vsock = container_of(vq->dev, struct vhost_vsock, 361 351 dev); 362 352 struct virtio_vsock_pkt *pkt; 363 - int head; 353 + int head, pkts = 0, total_len = 0; 364 354 unsigned int out, in; 365 355 bool added = false; 366 356 ··· 370 360 goto out; 371 361 372 362 vhost_disable_notify(&vsock->dev, vq); 373 - for (;;) { 363 + do { 374 364 u32 len; 375 365 376 366 if (!vhost_vsock_more_replies(vsock)) { ··· 411 401 else 412 402 virtio_transport_free_pkt(pkt); 413 403 414 - vhost_add_used(vq, head, sizeof(pkt->hdr) + len); 404 + len += sizeof(pkt->hdr); 405 + vhost_add_used(vq, head, len); 406 + total_len += len; 415 407 added = true; 416 - } 408 + } while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len))); 417 409 418 410 no_more_replies: 419 411 if (added) ··· 543 531 vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick; 544 532 vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick; 545 533 546 - vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV); 534 + vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), 535 + UIO_MAXIOV, VHOST_VSOCK_PKT_WEIGHT, 536 + VHOST_VSOCK_WEIGHT); 547 537 548 538 file->private_data = vsock; 549 539 spin_lock_init(&vsock->send_pkt_list_lock);
+4 -4
drivers/virtio/Kconfig
··· 63 63 64 64 If unsure, say M. 65 65 66 - config VIRTIO_MMIO 66 + config VIRTIO_MMIO 67 67 tristate "Platform bus driver for memory mapped virtio devices" 68 68 depends on HAS_IOMEM && HAS_DMA 69 - select VIRTIO 70 - ---help--- 71 - This drivers provides support for memory mapped virtio 69 + select VIRTIO 70 + ---help--- 71 + This drivers provides support for memory mapped virtio 72 72 platform device driver. 73 73 74 74 If unsure, say N.
+1 -1
tools/virtio/linux/kernel.h
··· 127 127 #define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) 128 128 #define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) 129 129 130 - #define WARN_ON_ONCE(cond) ((cond) ? fprintf (stderr, "WARNING\n") : 0) 130 + #define WARN_ON_ONCE(cond) (unlikely(cond) ? fprintf (stderr, "WARNING\n") : 0) 131 131 132 132 #define min(x, y) ({ \ 133 133 typeof(x) _min1 = (x); \