diff mbox

[RFC] virtio_balloon: disable oom killer when fill balloon

Message ID 20100928131954.GA2939@darkstar (mailing list archive)
State New, archived
Headers show

Commit Message

Dave Young Sept. 28, 2010, 1:19 p.m. UTC
None
diff mbox

Patch

--- linux-2.6.orig/drivers/virtio/virtio_balloon.c	2010-09-25 20:58:14.190000001 +0800
+++ linux-2.6/drivers/virtio/virtio_balloon.c	2010-09-28 21:05:42.203333675 +0800
@@ -25,6 +25,7 @@ 
 #include <linux/freezer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/oom.h>
 
 struct virtio_balloon
 {
@@ -97,8 +98,22 @@  static void tell_host(struct virtio_ball
 	wait_for_completion(&vb->acked);
 }
 
-static void fill_balloon(struct virtio_balloon *vb, size_t num)
+static int cblimit(int times)
 {
+	static int t;
+
+	if (t < times)
+		t++;
+	else
+		t = 0;
+
+	return !t;
+}
+
+static int fill_balloon(struct virtio_balloon *vb, size_t num)
+{
+	int ret = 0;
+
 	/* We can only do one array worth at a time. */
 	num = min(num, ARRAY_SIZE(vb->pfns));
 
@@ -106,10 +121,13 @@  static void fill_balloon(struct virtio_b
 		struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
 					__GFP_NOMEMALLOC | __GFP_NOWARN);
 		if (!page) {
-			if (printk_ratelimit())
+			if (cblimit(5)) {
 				dev_printk(KERN_INFO, &vb->vdev->dev,
 					   "Out of puff! Can't get %zu pages\n",
 					   num);
+				ret = -ENOMEM;
+				goto out;
+			}
 			/* Sleep for at least 1/5 of a second before retry. */
 			msleep(200);
 			break;
@@ -120,11 +138,11 @@  static void fill_balloon(struct virtio_b
 		list_add(&page->lru, &vb->pages);
 	}
 
-	/* Didn't get any?  Oh well. */
-	if (vb->num_pfns == 0)
-		return;
+out:
+	if (vb->num_pfns)
+		tell_host(vb, vb->inflate_vq);
 
-	tell_host(vb, vb->inflate_vq);
+	return ret;
 }
 
 static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
@@ -251,6 +269,14 @@  static void update_balloon_size(struct v
 			      &actual, sizeof(actual));
 }
 
+static void update_balloon_target(struct virtio_balloon *vb)
+{
+	__le32 num_pages = cpu_to_le32(vb->num_pages);
+	vb->vdev->config->set(vb->vdev,
+			      offsetof(struct virtio_balloon_config, num_pages),
+			      &num_pages, sizeof(num_pages));
+}
+
 static int balloon(void *_vballoon)
 {
 	struct virtio_balloon *vb = _vballoon;
@@ -267,9 +293,14 @@  static int balloon(void *_vballoon)
 					 || freezing(current));
 		if (vb->need_stats_update)
 			stats_handle_request(vb);
-		if (diff > 0)
-			fill_balloon(vb, diff);
-		else if (diff < 0)
+		if (diff > 0) {
+			int oom;
+			oom_killer_disable();
+			oom = fill_balloon(vb, diff);
+			oom_killer_enable();
+			if (oom)
+				update_balloon_target(vb);
+		} else if (diff < 0)
 			leak_balloon(vb, -diff);
 		update_balloon_size(vb);
 	}