Skip to contentSkip to conversation

kvm balloon guest driver (v2)

PATCH In review Marcelo Tosatti 3 participants 5 messages Jan 9, 2008 – Jan 10, 2008 2 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 kvm balloon guest driver (v2)

Updated balloon driver.

Changes from last version:
- Get rid of global variables/structure
- Use page->lru to link ballooned pages
- Use dev_dbg/dev_printk
- Proper kthread_should_stop handling
- Move shared definitions to separate header
- Use ->config_changed method for notification

This depends on Rusty's config_changed patch.

drivers/virtio/Kconfig +9 -0
Index: linux-2.6-nv/drivers/virtio/Kconfig
===================================================================
@@ -23,3 +23,12 @@ config VIRTIO_PCI
 
 	  If unsure, say M.
 
+config KVM_BALLOON
+	tristate "KVM balloon driver (EXPERIMENTAL)"
+	depends on VIRTIO_PCI
+	---help---
+	 This driver provides support for ballooning memory in/out of a
+	 KVM paravirt guest.	
+
+	 If unsure, say M.
+
drivers/virtio/Makefile +1 -0
Index: linux-2.6-nv/drivers/virtio/Makefile
===================================================================
@@ -1,3 +1,4 @@
 obj-$(CONFIG_VIRTIO) += virtio.o
 obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
+obj-$(CONFIG_KVM_BALLOON) += kvm_balloon.o
drivers/virtio/kvm_balloon.c new file +537 -0

537 lines not on this page · raw message

drivers/virtio/virtio_pci.c +1 -0
Index: linux-2.6-nv/drivers/virtio/virtio_pci.c
===================================================================
@@ -67,6 +67,7 @@ static struct pci_device_id virtio_pci_i
 	{ 0x1AF4, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Dummy entry */
 	{ 0x1AF4, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Dummy entry */
 	{ 0x1AF4, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Dummy entry */
+	{ 0x1AF4, 0x1003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Balloon */
 	{ 0 },
 };
 
include/linux/virtio_balloon.h new file +20 -0
Index: linux-2.6-nv/include/linux/virtio_balloon.h
===================================================================
@@ -0,0 +1,20 @@
+#ifndef _LINUX_VIRTIO_BALLOON_H
+#define _LINUX_VIRTIO_BALLOON_H
+#include <linux/virtio_config.h>
+
+#define VIRTIO_ID_BALLOON 3
+
+#define CMD_BALLOON_INFLATE 0x1
+#define CMD_BALLOON_DEFLATE 0x2
+
+struct virtio_balloon_hdr {
+	uint8_t cmd;
+	uint8_t status;
+};
+
+struct virtio_balloon_config
+{
+	uint32_t target_nrpages;
+};
+
+#endif /* _LINUX_VIRTIO_BALLOON_H */

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

#1 lore raw

Hi, Marcelo

Quoted 12 lines

+struct balloon_buf *alloc_balloon_buf(struct virtio_device *vdev, gfp_t flags)

drivers/virtio/kvm_balloon.c new file +10 -0
+{
+	struct balloon_buf *buf;
+
+	buf = kzalloc(sizeof(struct balloon_buf), flags);
+	if (!buf)
+		dev_printk(KERN_ERR, &vdev->dev, "%s: alloc fail\n", __func__);
+
+	return buf;
+}
+

[snip..]

drivers/virtio/kvm_balloon.c line 118

Quoted 10 lines
drivers/virtio/kvm_balloon.c new file +10 -0
+static int kvm_balloon_inflate(struct virtballoon *v, int32_t npages)
+{
+	LIST_HEAD(tmp_list);
+	struct page *page, *tmp;
+	struct balloon_buf *buf;
+	u32 *pfn;
+	int allocated = 0;
+	int i, r = -ENOMEM;
+
+	buf = alloc_balloon_buf(v->vdev, GFP_KERNEL);

When does balloon driver free the buf?

Quoted 37 lines
drivers/virtio/kvm_balloon.c new file +37 -0
+	if (!buf)
+		return r;
+
+	pfn = (u32 *)&buf->data;
+	*pfn++ = (u32)npages;
+
+	for (i = 0; i < npages; i++) {
+		page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY);
+		if (!page)
+			goto out_free;
+		list_add(&page->lru, &tmp_list);
+		allocated++;
+		*pfn = page_to_pfn(page);
+		pfn++;
+	}
+
+	r = send_balloon_buf(v, CMD_BALLOON_INFLATE, buf);
+	if (r)
+		goto out_free;
+
+	spin_lock(&v->plist_lock);
+	list_splice(&tmp_list, &v->balloon_plist);
+	v->balloon_size += allocated;
+	totalram_pages -= allocated;
+	dprintk(&v->vdev->dev, "%s: current balloon size=%d\n", __func__,
+		v->balloon_size);
+	spin_unlock(&v->plist_lock);
+	return allocated;
+
+out_free:
+	list_for_each_entry_safe(page, tmp, &tmp_list, lru) {
+		list_del(&page->lru);
+		__free_page(page);
+	}
+	return r;
+}
+

drivers/virtio/kvm_balloon.c line 165

Quoted 10 lines
drivers/virtio/kvm_balloon.c new file +10 -0
+static int kvm_balloon_deflate(struct virtballoon *v, int32_t npages)
+{
+	LIST_HEAD(tmp_list);
+	struct page *page, *tmp;
+	struct balloon_buf *buf;
+	u32 *pfn;
+	int deallocated = 0;
+	int r = 0;
+
+	buf = alloc_balloon_buf(v->vdev, GFP_KERNEL);

ditto.

Quoted 39 lines
drivers/virtio/kvm_balloon.c new file +39 -0
+	if (!buf)
+		return r;
+
+	spin_lock(&v->plist_lock);
+
+	if (v->balloon_size < npages) {
+		dev_printk(KERN_INFO, &v->vdev->dev,
+			   "%s: balloon=%d with deflate rq=%d\n",
+			   __func__, v->balloon_size, npages);
+		npages = v->balloon_size;
+		if (!npages)
+			goto out;
+	}
+
+	pfn = (u32 *)&buf->data;
+	*pfn++ = (u32)-npages;
+
+	/*
+	 * Move the balloon pages to tmp list before issuing 
+	 * the virtio buffer
+	 */
+	list_for_each_entry_safe(page, tmp, &v->balloon_plist, lru) {
+		*pfn++ = page_to_pfn(page);
+		list_move(&page->lru, &tmp_list);
+		if (++deallocated == npages)
+			break;
+	}
+
+	r = send_balloon_buf(v, CMD_BALLOON_DEFLATE, buf);
+	if (r)
+		goto out;
+
+	list_for_each_entry_safe(page, tmp, &tmp_list, lru)
+		list_del_init(&page->lru);
+
+	v->balloon_size -= npages;
+	totalram_pages += npages;
+	dprintk(&v->vdev->dev, "%s: current balloon size=%d\n", __func__,
+	       v->balloon_size);

drivers/virtio/kvm_balloon.c line 214

Quoted 10 lines
drivers/virtio/kvm_balloon.c new file +10 -0
+
+	spin_unlock(&v->plist_lock);
+	return deallocated;
+
+out:
+	list_splice(&tmp_list, &v->balloon_plist);
+	spin_unlock(&v->plist_lock);
+	return r;
+}
+

Best Regards,

Akio Takebe

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

A message that is not in the archive (sent off-list or not yet received): F1C85358126773takebe_akio-+CUm20s59erQFUHtdCDX3A@public.gmane.org

#3 lore raw
Quoted 15 lines · Akio Takebe

Hi, Marcelo

Quoted 12 lines

+struct balloon_buf *alloc_balloon_buf(struct virtio_device *vdev, gfp_t flags)

drivers/virtio/kvm_balloon.c new file +10 -0
+{
+	struct balloon_buf *buf;
+
+	buf = kzalloc(sizeof(struct balloon_buf), flags);
+	if (!buf)
+		dev_printk(KERN_ERR, &vdev->dev, "%s: alloc fail\n", __func__);
+
+	return buf;
+}
+

[snip..]

Quoted 11 lines

drivers/virtio/kvm_balloon.c line 118

Quoted 10 lines
drivers/virtio/kvm_balloon.c new file +10 -0
+static int kvm_balloon_inflate(struct virtballoon *v, int32_t npages)
+{
+	LIST_HEAD(tmp_list);
+	struct page *page, *tmp;
+	struct balloon_buf *buf;
+	u32 *pfn;
+	int allocated = 0;
+	int i, r = -ENOMEM;
+
+	buf = alloc_balloon_buf(v->vdev, GFP_KERNEL);

When does balloon driver free the buf?

Hi Akio,

The buffers are passed from the virtio handling routine to the balloon_thread through the balloon_work list, and then freed here:

+ spin_lock_irq(&v->queue_lock);
+ while (!list_empty(&v->balloon_work)) {
+ struct balloon_work *work;
+ struct balloon_buf *buf;
+
+ work = list_entry(v->balloon_work.next,
+ struct balloon_work, list);

+                       list_del(&work->list);
+                       spin_unlock_irq(&v->queue_lock);
+                       buf = work->buf;
+                       kfree(work);

+
+ switch(buf->hdr.cmd) {
+ case CMD_BALLOON_DEFLATE:
+ deflate_done(v, buf);
+ break;
+ case CMD_BALLOON_INFLATE:
+ inflate_done(v, buf);
+ break;
+ default:
+ printk("%s: unknown cmd 0x%x\n", __func__,
+ buf->hdr.cmd);
+ }
+ kfree(buf);

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

#4 lore raw

Hi, Marcelo

Quoted 31 lines
Quoted 11 lines

drivers/virtio/kvm_balloon.c line 118

Quoted 10 lines
drivers/virtio/kvm_balloon.c new file +10 -0
+static int kvm_balloon_inflate(struct virtballoon *v, int32_t npages)
+{
+	LIST_HEAD(tmp_list);
+	struct page *page, *tmp;
+	struct balloon_buf *buf;
+	u32 *pfn;
+	int allocated = 0;
+	int i, r = -ENOMEM;
+
+	buf = alloc_balloon_buf(v->vdev, GFP_KERNEL);

When does balloon driver free the buf?

Hi Akio,

The buffers are passed from the virtio handling routine to the balloon_thread through the balloon_work list, and then freed here:

drivers/virtio/kvm_balloon.c new file +14 -0
+               spin_lock_irq(&v->queue_lock);
+               while (!list_empty(&v->balloon_work)) {
+                       struct balloon_work *work;
+                       struct balloon_buf *buf;
+
+                       work = list_entry(v->balloon_work.next,
+                                        struct balloon_work, list);
+                       list_del(&work->list);
+                       spin_unlock_irq(&v->queue_lock);
+                       buf = work->buf;
+                       kfree(work);
+
+                       switch(buf->hdr.cmd) {
+                       case CMD_BALLOON_DEFLATE:

drivers/virtio/kvm_balloon.c line 380

Quoted 10 lines
drivers/virtio/kvm_balloon.c new file +10 -0
+                               deflate_done(v, buf);
+                               break;
+                       case CMD_BALLOON_INFLATE:
+                               inflate_done(v, buf);
+                               break;
+                       default:
+                               printk("%s: unknown cmd 0x%x\n", __func__,
+                                       buf->hdr.cmd);
+                       }
+                       kfree(buf);

Thank you for your exlanation.
Does balloon free the buf when kvm_balloon_xflate() retrun -ENOMEM?

Best Regards,

Akio Takebe

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

A message that is not in the archive (sent off-list or not yet received): F7C853842F97FDtakebe_akio-+CUm20s59erQFUHtdCDX3A@public.gmane.org

#6 lore raw
Quoted 37 lines · Akio Takebe

Hi, Marcelo

Quoted 35 lines
Quoted 11 lines

drivers/virtio/kvm_balloon.c line 118

Quoted 10 lines
drivers/virtio/kvm_balloon.c new file +10 -0
+static int kvm_balloon_inflate(struct virtballoon *v, int32_t npages)
+{
+	LIST_HEAD(tmp_list);
+	struct page *page, *tmp;
+	struct balloon_buf *buf;
+	u32 *pfn;
+	int allocated = 0;
+	int i, r = -ENOMEM;
+
+	buf = alloc_balloon_buf(v->vdev, GFP_KERNEL);

When does balloon driver free the buf?

Hi Akio,

The buffers are passed from the virtio handling routine to the balloon_thread through the balloon_work list, and then freed here:

drivers/virtio/kvm_balloon.c new file +18 -0
+               spin_lock_irq(&v->queue_lock);
+               while (!list_empty(&v->balloon_work)) {
+                       struct balloon_work *work;
+                       struct balloon_buf *buf;
+
+                       work = list_entry(v->balloon_work.next,
+                                        struct balloon_work, list);
+                       list_del(&work->list);
+                       spin_unlock_irq(&v->queue_lock);
+                       buf = work->buf;
+                       kfree(work);
+
+                       switch(buf->hdr.cmd) {
+                       case CMD_BALLOON_DEFLATE:
+                               deflate_done(v, buf);
+                               break;
+                       case CMD_BALLOON_INFLATE:
+                               inflate_done(v, buf);
Quoted 8 lines

drivers/virtio/kvm_balloon.c line 380

Quoted 6 lines
drivers/virtio/kvm_balloon.c new file +6 -0
+                               break;
+                       default:
+                               printk("%s: unknown cmd 0x%x\n", __func__,
+                                       buf->hdr.cmd);
+                       }
+                       kfree(buf);

Thank you for your exlanation.
Does balloon free the buf when kvm_balloon_xflate() retrun -ENOMEM?

It return -ENOMEM only when kvm_balloon_inflate fails.
We just need to handle this case a little better - there is no leak but the xflate function or the balloon thread need to check the value and update the host that it failed to reach the requested balloon size.

Quoted 12 lines

Akio Takebe

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
kvm-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace