From patchwork Mon Nov 9 16:32:06 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adam Litke X-Patchwork-Id: 37979 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 A7097B7B65 for ; Tue, 10 Nov 2009 03:57:36 +1100 (EST) Received: from localhost ([127.0.0.1]:59710 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N7XYb-0004OH-T8 for incoming@patchwork.ozlabs.org; Mon, 09 Nov 2009 11:57:33 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1N7XAN-00039U-DQ for qemu-devel@nongnu.org; Mon, 09 Nov 2009 11:32:31 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1N7XAH-00037D-8T for qemu-devel@nongnu.org; Mon, 09 Nov 2009 11:32:30 -0500 Received: from [199.232.76.173] (port=55030 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N7XAG-00036o-Nv for qemu-devel@nongnu.org; Mon, 09 Nov 2009 11:32:24 -0500 Received: from e37.co.us.ibm.com ([32.97.110.158]:53793) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1N7XAG-0004Ty-6A for qemu-devel@nongnu.org; Mon, 09 Nov 2009 11:32:24 -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 nA9GVCm1013153 for ; Mon, 9 Nov 2009 09:31:12 -0700 Received: from d03av04.boulder.ibm.com (d03av04.boulder.ibm.com [9.17.195.170]) by d03relay01.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id nA9GWA8P043590 for ; Mon, 9 Nov 2009 09:32:12 -0700 Received: from d03av04.boulder.ibm.com (loopback [127.0.0.1]) by d03av04.boulder.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id nA9ASFNQ029623 for ; Mon, 9 Nov 2009 03:28:16 -0700 Received: from [9.10.86.161] (aglitke.rchland.ibm.com [9.10.86.161]) by d03av04.boulder.ibm.com (8.14.3/8.13.1/NCO v10.0 AVin) with ESMTP id nA9ASEZF029528; Mon, 9 Nov 2009 03:28:14 -0700 From: Adam Litke To: qemu-devel@nongnu.org In-Reply-To: <1257782838.2835.5.camel@aglitke> References: <1257782838.2835.5.camel@aglitke> Organization: IBM Date: Mon, 09 Nov 2009 10:32:06 -0600 Message-ID: <1257784326.2835.16.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: linux-kernel@vger.kernel.org, "virtualization@lists.linux-foundation.orgAnthony Liguori" , Rusty Russell , Avi Kivity , virtualization@lists.linux-foundation.org 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 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. Comments? Signed-off-by: Adam Litke Cc: Rusty Russell Cc: Anthony Liguori Cc: Avi Kivity Cc: virtualization@lists.linux-foundation.org Cc: linux-kernel@vger.kernel.org diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 200c22f..0c9a9a1 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -180,6 +180,41 @@ 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) +{ + __le32 __v = cpu_to_le32(value); + if (virtio_has_feature(vdev, feature)) + vdev->config->set(vdev, offset, &__v, sizeof(__v)); +} + +#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 +224,17 @@ 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); 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; } @@ -265,7 +302,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 */