Commit 18c83d2c authored by Linus Torvalds's avatar Linus Torvalds

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

Pull virtio updates from Michael Tsirkin:
 "Fixes in qemu, vhost and virtio"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
  fw_cfg: fix the command line module name
  vhost/vsock: fix uninitialized vhost_vsock->guest_cid
  vhost: fix end of range for access_ok
  vhost/scsi: Use safe iteration in vhost_scsi_complete_cmd_work()
  virtio_balloon: fix deadlock on OOM
parents 051089a2 c1d0c3f6
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
* and select subsets of aarch64), a Device Tree node (on arm), or using * and select subsets of aarch64), a Device Tree node (on arm), or using
* a kernel module (or command line) parameter with the following syntax: * a kernel module (or command line) parameter with the following syntax:
* *
* [fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>] * [qemu_fw_cfg.]ioport=<size>@<base>[:<ctrl_off>:<data_off>]
* or * or
* [fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>] * [qemu_fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>]
* *
* where: * where:
* <size> := size of ioport or mmio range * <size> := size of ioport or mmio range
...@@ -21,9 +21,9 @@ ...@@ -21,9 +21,9 @@
* <data_off> := (optional) offset of data register * <data_off> := (optional) offset of data register
* *
* e.g.: * e.g.:
* fw_cfg.ioport=2@0x510:0:1 (the default on x86) * qemu_fw_cfg.ioport=2@0x510:0:1 (the default on x86)
* or * or
* fw_cfg.mmio=0xA@0x9020000:8:0 (the default on arm) * qemu_fw_cfg.mmio=0xA@0x9020000:8:0 (the default on arm)
*/ */
#include <linux/module.h> #include <linux/module.h>
......
...@@ -519,7 +519,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) ...@@ -519,7 +519,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
vs_completion_work); vs_completion_work);
DECLARE_BITMAP(signal, VHOST_SCSI_MAX_VQ); DECLARE_BITMAP(signal, VHOST_SCSI_MAX_VQ);
struct virtio_scsi_cmd_resp v_rsp; struct virtio_scsi_cmd_resp v_rsp;
struct vhost_scsi_cmd *cmd; struct vhost_scsi_cmd *cmd, *t;
struct llist_node *llnode; struct llist_node *llnode;
struct se_cmd *se_cmd; struct se_cmd *se_cmd;
struct iov_iter iov_iter; struct iov_iter iov_iter;
...@@ -527,7 +527,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) ...@@ -527,7 +527,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
bitmap_zero(signal, VHOST_SCSI_MAX_VQ); bitmap_zero(signal, VHOST_SCSI_MAX_VQ);
llnode = llist_del_all(&vs->vs_completion_list); llnode = llist_del_all(&vs->vs_completion_list);
llist_for_each_entry(cmd, llnode, tvc_completion_list) { llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) {
se_cmd = &cmd->tvc_se_cmd; se_cmd = &cmd->tvc_se_cmd;
pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__, pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__,
......
...@@ -1175,7 +1175,7 @@ static int iotlb_access_ok(struct vhost_virtqueue *vq, ...@@ -1175,7 +1175,7 @@ static int iotlb_access_ok(struct vhost_virtqueue *vq,
{ {
const struct vhost_umem_node *node; const struct vhost_umem_node *node;
struct vhost_umem *umem = vq->iotlb; struct vhost_umem *umem = vq->iotlb;
u64 s = 0, size, orig_addr = addr; u64 s = 0, size, orig_addr = addr, last = addr + len - 1;
if (vhost_vq_meta_fetch(vq, addr, len, type)) if (vhost_vq_meta_fetch(vq, addr, len, type))
return true; return true;
...@@ -1183,7 +1183,7 @@ static int iotlb_access_ok(struct vhost_virtqueue *vq, ...@@ -1183,7 +1183,7 @@ static int iotlb_access_ok(struct vhost_virtqueue *vq,
while (len > s) { while (len > s) {
node = vhost_umem_interval_tree_iter_first(&umem->umem_tree, node = vhost_umem_interval_tree_iter_first(&umem->umem_tree,
addr, addr,
addr + len - 1); last);
if (node == NULL || node->start > addr) { if (node == NULL || node->start > addr) {
vhost_iotlb_miss(vq, addr, access); vhost_iotlb_miss(vq, addr, access);
return false; return false;
......
...@@ -518,6 +518,8 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file) ...@@ -518,6 +518,8 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
goto out; goto out;
} }
vsock->guest_cid = 0; /* no CID assigned yet */
atomic_set(&vsock->queued_replies, 0); atomic_set(&vsock->queued_replies, 0);
vqs[VSOCK_VQ_TX] = &vsock->vqs[VSOCK_VQ_TX]; vqs[VSOCK_VQ_TX] = &vsock->vqs[VSOCK_VQ_TX];
......
...@@ -143,16 +143,17 @@ static void set_page_pfns(struct virtio_balloon *vb, ...@@ -143,16 +143,17 @@ static void set_page_pfns(struct virtio_balloon *vb,
static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
{ {
struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;
unsigned num_allocated_pages; unsigned num_allocated_pages;
unsigned num_pfns;
struct page *page;
LIST_HEAD(pages);
/* We can only do one array worth at a time. */ /* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns)); num = min(num, ARRAY_SIZE(vb->pfns));
mutex_lock(&vb->balloon_lock); for (num_pfns = 0; num_pfns < num;
for (vb->num_pfns = 0; vb->num_pfns < num; num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) { struct page *page = balloon_page_alloc();
struct page *page = balloon_page_enqueue(vb_dev_info);
if (!page) { if (!page) {
dev_info_ratelimited(&vb->vdev->dev, dev_info_ratelimited(&vb->vdev->dev,
...@@ -162,6 +163,19 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num) ...@@ -162,6 +163,19 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
msleep(200); msleep(200);
break; break;
} }
balloon_page_push(&pages, page);
}
mutex_lock(&vb->balloon_lock);
vb->num_pfns = 0;
while ((page = balloon_page_pop(&pages))) {
balloon_page_enqueue(&vb->vb_dev_info, page);
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE;
set_page_pfns(vb, vb->pfns + vb->num_pfns, page); set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE; vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
if (!virtio_has_feature(vb->vdev, if (!virtio_has_feature(vb->vdev,
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/list.h>
/* /*
* Balloon device information descriptor. * Balloon device information descriptor.
...@@ -67,7 +68,9 @@ struct balloon_dev_info { ...@@ -67,7 +68,9 @@ struct balloon_dev_info {
struct inode *inode; struct inode *inode;
}; };
extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info); extern struct page *balloon_page_alloc(void);
extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
struct page *page);
extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info); extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
...@@ -193,4 +196,34 @@ static inline gfp_t balloon_mapping_gfp_mask(void) ...@@ -193,4 +196,34 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
} }
#endif /* CONFIG_BALLOON_COMPACTION */ #endif /* CONFIG_BALLOON_COMPACTION */
/*
* balloon_page_push - insert a page into a page list.
* @head : pointer to list
* @page : page to be added
*
* Caller must ensure the page is private and protect the list.
*/
static inline void balloon_page_push(struct list_head *pages, struct page *page)
{
list_add(&page->lru, pages);
}
/*
* balloon_page_pop - remove a page from a page list.
* @head : pointer to list
* @page : page to be added
*
* Caller must ensure the page is private and protect the list.
*/
static inline struct page *balloon_page_pop(struct list_head *pages)
{
struct page *page = list_first_entry_or_null(pages, struct page, lru);
if (!page)
return NULL;
list_del(&page->lru);
return page;
}
#endif /* _LINUX_BALLOON_COMPACTION_H */ #endif /* _LINUX_BALLOON_COMPACTION_H */
...@@ -10,23 +10,38 @@ ...@@ -10,23 +10,38 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/balloon_compaction.h> #include <linux/balloon_compaction.h>
/*
* balloon_page_alloc - allocates a new page for insertion into the balloon
* page list.
*
* Driver must call it to properly allocate a new enlisted balloon page.
* Driver must call balloon_page_enqueue before definitively removing it from
* the guest system. This function returns the page address for the recently
* allocated page or NULL in the case we fail to allocate a new page this turn.
*/
struct page *balloon_page_alloc(void)
{
struct page *page = alloc_page(balloon_mapping_gfp_mask() |
__GFP_NOMEMALLOC | __GFP_NORETRY);
return page;
}
EXPORT_SYMBOL_GPL(balloon_page_alloc);
/* /*
* balloon_page_enqueue - allocates a new page and inserts it into the balloon * balloon_page_enqueue - allocates a new page and inserts it into the balloon
* page list. * page list.
* @b_dev_info: balloon device descriptor where we will insert a new page to * @b_dev_info: balloon device descriptor where we will insert a new page to
* @page: new page to enqueue - allocated using balloon_page_alloc.
* *
* Driver must call it to properly allocate a new enlisted balloon page * Driver must call it to properly enqueue a new allocated balloon page
* before definitively removing it from the guest system. * before definitively removing it from the guest system.
* This function returns the page address for the recently enqueued page or * This function returns the page address for the recently enqueued page or
* NULL in the case we fail to allocate a new page this turn. * NULL in the case we fail to allocate a new page this turn.
*/ */
struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info) void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
struct page *page)
{ {
unsigned long flags; unsigned long flags;
struct page *page = alloc_page(balloon_mapping_gfp_mask() |
__GFP_NOMEMALLOC | __GFP_NORETRY);
if (!page)
return NULL;
/* /*
* Block others from accessing the 'page' when we get around to * Block others from accessing the 'page' when we get around to
...@@ -39,7 +54,6 @@ struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info) ...@@ -39,7 +54,6 @@ struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
__count_vm_event(BALLOON_INFLATE); __count_vm_event(BALLOON_INFLATE);
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
unlock_page(page); unlock_page(page);
return page;
} }
EXPORT_SYMBOL_GPL(balloon_page_enqueue); EXPORT_SYMBOL_GPL(balloon_page_enqueue);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment