virtio, vhost, qemu: bugfixes, cleanups
Fixes in qemu, vhost and virtio. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJaDdyiAAoJECgfDbjSjVRpEekIAMh6WWhjHWSG1PukqSZYiHEN S1GU+wViGLai9zI54o8/VcRcRMuJMcN/HiYXh/28N3v4MzSxtJy12c/oV13zexAZ ypALoQM6Fazm1hPdAMujFAQ4rgAgYFZ98822HU3rXwfS+jW1JY/LV0cLoIL9BStQ aHLr06GGv/Xq3aibECaKvzFcKXi9qCz6Cuw/aKPMmDo89RSvxQyMhneaEW6YyT2L Srt2lke0W4UbozMAe3UT2SwOMTEpSOnmrTDGqvU4gFtfgAm6Z8HkM1HA/i010Dcc FsSfa5N9yLD9WodEyKgU0qh3yvhkLwg/Sfiu/KBbbbSSQzjkuqW+XWWJwOAitWA= =1iSK -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
18c83d2c03
|
@ -10,9 +10,9 @@
|
|||
* and select subsets of aarch64), a Device Tree node (on arm), or using
|
||||
* 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
|
||||
* [fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>]
|
||||
* [qemu_fw_cfg.]mmio=<size>@<base>[:<ctrl_off>:<data_off>]
|
||||
*
|
||||
* where:
|
||||
* <size> := size of ioport or mmio range
|
||||
|
@ -21,9 +21,9 @@
|
|||
* <data_off> := (optional) offset of data register
|
||||
*
|
||||
* 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
|
||||
* 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>
|
||||
|
|
|
@ -519,7 +519,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
|
|||
vs_completion_work);
|
||||
DECLARE_BITMAP(signal, VHOST_SCSI_MAX_VQ);
|
||||
struct virtio_scsi_cmd_resp v_rsp;
|
||||
struct vhost_scsi_cmd *cmd;
|
||||
struct vhost_scsi_cmd *cmd, *t;
|
||||
struct llist_node *llnode;
|
||||
struct se_cmd *se_cmd;
|
||||
struct iov_iter iov_iter;
|
||||
|
@ -527,7 +527,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
|
|||
|
||||
bitmap_zero(signal, VHOST_SCSI_MAX_VQ);
|
||||
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;
|
||||
|
||||
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,
|
|||
{
|
||||
const struct vhost_umem_node *node;
|
||||
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))
|
||||
return true;
|
||||
|
@ -1183,7 +1183,7 @@ static int iotlb_access_ok(struct vhost_virtqueue *vq,
|
|||
while (len > s) {
|
||||
node = vhost_umem_interval_tree_iter_first(&umem->umem_tree,
|
||||
addr,
|
||||
addr + len - 1);
|
||||
last);
|
||||
if (node == NULL || node->start > addr) {
|
||||
vhost_iotlb_miss(vq, addr, access);
|
||||
return false;
|
||||
|
|
|
@ -518,6 +518,8 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
|
|||
goto out;
|
||||
}
|
||||
|
||||
vsock->guest_cid = 0; /* no CID assigned yet */
|
||||
|
||||
atomic_set(&vsock->queued_replies, 0);
|
||||
|
||||
vqs[VSOCK_VQ_TX] = &vsock->vqs[VSOCK_VQ_TX];
|
||||
|
|
|
@ -143,16 +143,17 @@ static void set_page_pfns(struct virtio_balloon *vb,
|
|||
|
||||
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_pfns;
|
||||
struct page *page;
|
||||
LIST_HEAD(pages);
|
||||
|
||||
/* We can only do one array worth at a time. */
|
||||
num = min(num, ARRAY_SIZE(vb->pfns));
|
||||
|
||||
mutex_lock(&vb->balloon_lock);
|
||||
for (vb->num_pfns = 0; vb->num_pfns < num;
|
||||
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
|
||||
struct page *page = balloon_page_enqueue(vb_dev_info);
|
||||
for (num_pfns = 0; num_pfns < num;
|
||||
num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
|
||||
struct page *page = balloon_page_alloc();
|
||||
|
||||
if (!page) {
|
||||
dev_info_ratelimited(&vb->vdev->dev,
|
||||
|
@ -162,6 +163,19 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
|
|||
msleep(200);
|
||||
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);
|
||||
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
|
||||
if (!virtio_has_feature(vb->vdev,
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <linux/gfp.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
/*
|
||||
* Balloon device information descriptor.
|
||||
|
@ -67,7 +68,9 @@ struct balloon_dev_info {
|
|||
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);
|
||||
|
||||
static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
|
||||
|
@ -193,4 +196,34 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
|
|||
}
|
||||
|
||||
#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 */
|
||||
|
|
|
@ -10,23 +10,38 @@
|
|||
#include <linux/export.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
|
||||
* page list.
|
||||
* @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.
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
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
|
||||
|
@ -39,7 +54,6 @@ struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
|
|||
__count_vm_event(BALLOON_INFLATE);
|
||||
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
|
||||
unlock_page(page);
|
||||
return page;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(balloon_page_enqueue);
|
||||
|
||||
|
|
Loading…
Reference in New Issue