qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] virtio: Add memory statistics reporting to the balloon driv


From: Adam Litke
Subject: [Qemu-devel] virtio: Add memory statistics reporting to the balloon driver
Date: Thu, 05 Nov 2009 17:02:35 -0600

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 <address@hidden>

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 */



-- 
Thanks,
Adam





reply via email to

[Prev in Thread] Current Thread [Next in Thread]