--- x/drivers/vhost/vhost.c +++ y/drivers/vhost/vhost.c @@ -353,14 +353,16 @@ static int vhost_worker(void *data) /* mb paired w/ kthread_stop */ set_current_state(TASK_INTERRUPTIBLE); - if (kthread_should_stop()) { - __set_current_state(TASK_RUNNING); - break; - } - node = llist_del_all(&dev->work_list); - if (!node) + if (!node) { + if (kthread_should_stop()) { + __set_current_state(TASK_RUNNING); + break; + } + schedule(); + continue; + } node = llist_reverse_order(node); /* make sure flag is seen after deletion */ @@ -712,12 +714,12 @@ void vhost_dev_cleanup(struct vhost_dev dev->iotlb = NULL; vhost_clear_msg(dev); wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); - WARN_ON(!llist_empty(&dev->work_list)); if (dev->worker) { kthread_stop(dev->worker); dev->worker = NULL; dev->kcov_handle = 0; } + WARN_ON(!llist_empty(&dev->work_list)); vhost_detach_mm(dev); } EXPORT_SYMBOL_GPL(vhost_dev_cleanup); @@ -2207,7 +2209,10 @@ int vhost_get_vq_desc(struct vhost_virtq __virtio16 avail_idx; __virtio16 ring_head; int ret, access; + bool was_set = !!(vq->used_flags & VRING_USED_F_NO_NOTIFY); + if (!was_set) + return -EINVAL; /* Check it isn't doing very strange things with descriptor numbers. */ last_avail_idx = vq->last_avail_idx; @@ -2327,12 +2332,14 @@ int vhost_get_vq_desc(struct vhost_virtq } } while ((i = next_desc(vq, &desc)) != -1); + /* Assume notifications from guest are disabled at this point, + * if they aren't we would need to update avail_event index. */ + if (!!(vq->used_flags & VRING_USED_F_NO_NOTIFY) != was_set) + return -EINVAL; + /* On success, increment avail index. */ vq->last_avail_idx++; - /* Assume notifications from guest are disabled at this point, - * if they aren't we would need to update avail_event index. */ - BUG_ON(!(vq->used_flags & VRING_USED_F_NO_NOTIFY)); return head; } EXPORT_SYMBOL_GPL(vhost_get_vq_desc);