From patchwork Thu Nov 5 23:02:35 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Litke X-Patchwork-Id: 37801 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C2EB8B7BA4 for ; Fri, 6 Nov 2009 10:04:07 +1100 (EST) Received: from localhost ([127.0.0.1]:35627 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N6BN5-0005LI-Tm for incoming@patchwork.ozlabs.org; Thu, 05 Nov 2009 18:04:04 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1N6BM3-0004xt-J1 for qemu-devel@nongnu.org; Thu, 05 Nov 2009 18:02:59 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1N6BLy-0004uj-Kp for qemu-devel@nongnu.org; Thu, 05 Nov 2009 18:02:59 -0500 Received: from [199.232.76.173] (port=33780 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N6BLy-0004ud-8x for qemu-devel@nongnu.org; Thu, 05 Nov 2009 18:02:54 -0500 Received: from e37.co.us.ibm.com ([32.97.110.158]:35280) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1N6BLx-00069E-IZ for qemu-devel@nongnu.org; Thu, 05 Nov 2009 18:02:53 -0500 Received: from d03relay01.boulder.ibm.com (d03relay01.boulder.ibm.com [9.17.195.226]) by e37.co.us.ibm.com (8.14.3/8.13.1) with ESMTP id nA5N1hdM030078 for ; Thu, 5 Nov 2009 16:01:43 -0700 Received: from d03av06.boulder.ibm.com (d03av06.boulder.ibm.com [9.17.195.245]) by d03relay01.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id nA5N2bUR131720 for ; Thu, 5 Nov 2009 16:02:38 -0700 Received: from d03av06.boulder.ibm.com (loopback [127.0.0.1]) by d03av06.boulder.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id nA5N4C5h021161 for ; Thu, 5 Nov 2009 16:04:12 -0700 Received: from [9.10.86.161] (aglitke.rchland.ibm.com [9.10.86.161]) by d03av06.boulder.ibm.com (8.14.3/8.13.1/NCO v10.0 AVin) with ESMTP id nA5N4CmK021108; Thu, 5 Nov 2009 16:04:12 -0700 From: Adam Litke To: qemu-devel@nongnu.org In-Reply-To: <1257461425.3121.22.camel@aglitke> References: <1257461425.3121.22.camel@aglitke> Organization: IBM Date: Thu, 05 Nov 2009 17:02:35 -0600 Message-ID: <1257462155.3121.25.camel@aglitke> Mime-Version: 1.0 X-Mailer: Evolution 2.28.1 X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: aliguori@us.ibm.com Subject: [Qemu-devel] virtio: Add memory statistics reporting to the balloon driver X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Here are the corresponding changes to the Linux virtio driver... virtio: Add memory statistics reporting to the balloon driver When using ballooning to manage overcommitted memory on a host, a system for guests to communicate their memory usage to the host can provide information that will minimize the impact of ballooning on the guests. The current method employs a daemon running in each guest that communicates memory statistics to a host daemon at a specified time interval. The host daemon aggregates this information and inflates and/or deflates balloons according to the level of host memory pressure. This approach is effective but overly complex since a daemon must be installed inside each guest and coordinated to communicate with the host. A simpler approach is to collect memory statistics in the virtio balloon driver and communicate them to the host via the device config space. This patch enables the guest-side support by adding stats collection and reporting to the virtio balloon driver. Signed-off-by: Adam Litke diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 3a43ebf..1029363 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -135,6 +135,7 @@ static int virtio_dev_probe(struct device *_d) set_bit(i, dev->features); dev->config->finalize_features(dev); + printk("virtio_dev_probe: final features = %lx\n", dev->features[0]); err = drv->probe(dev); if (err) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 200c22f..77cb953 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -180,6 +180,45 @@ static void update_balloon_size(struct virtio_balloon *vb) &actual, sizeof(actual)); } +static inline void update_stat(struct virtio_device *vdev, int feature, + unsigned long value, unsigned offset) +{ + if (virtio_has_feature(vdev, feature)) { + vdev->config->set(vdev, offset, &value, sizeof(value)); + printk("update_stat: Set field %i to %lu\n", + offset / 4, value); + } else + printk("Feature %i not supported, leaving field %i alone\n", + feature, offset / 4); +} + +#define K(x) ((x) << (PAGE_SHIFT - 10)) +static void update_balloon_stats(struct virtio_balloon *vb) +{ + unsigned long events[NR_VM_EVENT_ITEMS]; + struct sysinfo i; + unsigned off = offsetof(struct virtio_balloon_config, stats); + + all_vm_events(events); + + update_stat(vb->vdev, VIRTIO_BALLOON_F_RPT_SWAP_IN, events[PSWPIN], + off + offsetof(struct virtio_balloon_stats, pswapin)); + update_stat(vb->vdev, VIRTIO_BALLOON_F_RPT_SWAP_OUT, events[PSWPOUT], + off + offsetof(struct virtio_balloon_stats, pswapout)); + update_stat(vb->vdev, VIRTIO_BALLOON_F_RPT_MAJFLT, events[PGMAJFAULT], + off + offsetof(struct virtio_balloon_stats, pgmajfault)); + update_stat(vb->vdev, VIRTIO_BALLOON_F_RPT_MINFLT, events[PGFAULT], + off + offsetof(struct virtio_balloon_stats, pgminfault)); + update_stat(vb->vdev, VIRTIO_BALLOON_F_RPT_ANON, + K(global_page_state(NR_ANON_PAGES)), + off + offsetof(struct virtio_balloon_stats, panon)); + si_meminfo(&i); + update_stat(vb->vdev, VIRTIO_BALLOON_F_RPT_MEMFREE, K(i.freeram), + off + offsetof(struct virtio_balloon_stats, memfree)); + update_stat(vb->vdev, VIRTIO_BALLOON_F_RPT_MEMTOT, K(i.totalram), + off + offsetof(struct virtio_balloon_stats, memtot)); +} + static int balloon(void *_vballoon) { struct virtio_balloon *vb = _vballoon; @@ -189,15 +228,18 @@ static int balloon(void *_vballoon) s64 diff; try_to_freeze(); - wait_event_interruptible(vb->config_change, + wait_event_interruptible_timeout(vb->config_change, (diff = towards_target(vb)) != 0 || kthread_should_stop() - || freezing(current)); + || freezing(current), + VIRTIO_BALLOON_TIMEOUT); + printk("Awake!\n"); if (diff > 0) fill_balloon(vb, diff); else if (diff < 0) leak_balloon(vb, -diff); update_balloon_size(vb); + update_balloon_stats(vb); } return 0; } @@ -237,6 +279,7 @@ static int virtballoon_probe(struct virtio_device *vdev) vb->tell_host_first = virtio_has_feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST); + dev_printk(KERN_INFO, &vb->vdev->dev, "virtballoon_probe: features = %lx\n", vdev->features[0]); return 0; @@ -265,7 +308,12 @@ static void virtballoon_remove(struct virtio_device *vdev) kfree(vb); } -static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST }; +static unsigned int features[] = { + VIRTIO_BALLOON_F_MUST_TELL_HOST, VIRTIO_BALLOON_F_RPT_SWAP_IN, + VIRTIO_BALLOON_F_RPT_SWAP_OUT, VIRTIO_BALLOON_F_RPT_ANON, + VIRTIO_BALLOON_F_RPT_MAJFLT, VIRTIO_BALLOON_F_RPT_MINFLT, + VIRTIO_BALLOON_F_RPT_MEMFREE, VIRTIO_BALLOON_F_RPT_MEMTOT, +}; static struct virtio_driver virtio_balloon = { .feature_table = features, diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h index 09d7300..0bff4b8 100644 --- a/include/linux/virtio_balloon.h +++ b/include/linux/virtio_balloon.h @@ -6,15 +6,39 @@ /* The feature bitmap for virtio balloon */ #define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ + /* Guest memory statistic reporting */ +#define VIRTIO_BALLOON_F_RPT_SWAP_IN 1 /* Number of pages swapped in */ +#define VIRTIO_BALLOON_F_RPT_SWAP_OUT 2 /* Number of pages swapped out */ +#define VIRTIO_BALLOON_F_RPT_ANON 3 /* Number of anonymous pages in use */ +#define VIRTIO_BALLOON_F_RPT_MAJFLT 4 /* Number of major faults */ +#define VIRTIO_BALLOON_F_RPT_MINFLT 5 /* Number of minor faults */ +#define VIRTIO_BALLOON_F_RPT_MEMFREE 6 /* Total amount of free memory */ +#define VIRTIO_BALLOON_F_RPT_MEMTOT 7 /* Total amount of memory */ /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 +struct virtio_balloon_stats +{ + __le32 pswapin; /* pages swapped in */ + __le32 pswapout; /* pages swapped out */ + __le32 panon; /* anonymous pages in use (in kb) */ + __le32 pgmajfault; /* Major page faults */ + __le32 pgminfault; /* Minor page faults */ + __le32 memfree; /* Total amount of free memory (in kb) */ + __le32 memtot; /* Total amount of memory (in kb) */ +}; + struct virtio_balloon_config { /* Number of pages host wants Guest to give up. */ __le32 num_pages; /* Number of pages we've actually got in balloon. */ __le32 actual; + /* Memory statistics */ + struct virtio_balloon_stats stats; }; + +#define VIRTIO_BALLOON_TIMEOUT (30 * HZ) + #endif /* _LINUX_VIRTIO_BALLOON_H */