Commit 9646b26e authored by Ladi Prosek's avatar Ladi Prosek Committed by Michael S. Tsirkin

virtio-balloon: use actual number of stats for stats queue buffers

The virtio balloon driver contained a not-so-obvious invariant that
update_balloon_stats has to update exactly VIRTIO_BALLOON_S_NR counters
in order to send valid stats to the host. This commit fixes it by having
update_balloon_stats return the actual number of counters, and its
callers use it when pushing buffers to the stats virtqueue.

Note that it is still out of spec to change the number of counters
at run-time. "Driver MUST supply the same subset of statistics in all
buffers submitted to the statsq."
Suggested-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarLadi Prosek <lprosek@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent fc865322
...@@ -242,11 +242,11 @@ static inline void update_stat(struct virtio_balloon *vb, int idx, ...@@ -242,11 +242,11 @@ static inline void update_stat(struct virtio_balloon *vb, int idx,
#define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT) #define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT)
static void update_balloon_stats(struct virtio_balloon *vb) static unsigned int update_balloon_stats(struct virtio_balloon *vb)
{ {
unsigned long events[NR_VM_EVENT_ITEMS]; unsigned long events[NR_VM_EVENT_ITEMS];
struct sysinfo i; struct sysinfo i;
int idx = 0; unsigned int idx = 0;
long available; long available;
all_vm_events(events); all_vm_events(events);
...@@ -266,6 +266,8 @@ static void update_balloon_stats(struct virtio_balloon *vb) ...@@ -266,6 +266,8 @@ static void update_balloon_stats(struct virtio_balloon *vb)
pages_to_bytes(i.totalram)); pages_to_bytes(i.totalram));
update_stat(vb, idx++, VIRTIO_BALLOON_S_AVAIL, update_stat(vb, idx++, VIRTIO_BALLOON_S_AVAIL,
pages_to_bytes(available)); pages_to_bytes(available));
return idx;
} }
/* /*
...@@ -291,14 +293,14 @@ static void stats_handle_request(struct virtio_balloon *vb) ...@@ -291,14 +293,14 @@ static void stats_handle_request(struct virtio_balloon *vb)
{ {
struct virtqueue *vq; struct virtqueue *vq;
struct scatterlist sg; struct scatterlist sg;
unsigned int len; unsigned int len, num_stats;
update_balloon_stats(vb); num_stats = update_balloon_stats(vb);
vq = vb->stats_vq; vq = vb->stats_vq;
if (!virtqueue_get_buf(vq, &len)) if (!virtqueue_get_buf(vq, &len))
return; return;
sg_init_one(&sg, vb->stats, sizeof(vb->stats)); sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL); virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
virtqueue_kick(vq); virtqueue_kick(vq);
} }
...@@ -423,15 +425,16 @@ static int init_vqs(struct virtio_balloon *vb) ...@@ -423,15 +425,16 @@ static int init_vqs(struct virtio_balloon *vb)
vb->deflate_vq = vqs[1]; vb->deflate_vq = vqs[1];
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) {
struct scatterlist sg; struct scatterlist sg;
unsigned int num_stats;
vb->stats_vq = vqs[2]; vb->stats_vq = vqs[2];
/* /*
* Prime this virtqueue with one buffer so the hypervisor can * Prime this virtqueue with one buffer so the hypervisor can
* use it to signal us later (it can't be broken yet!). * use it to signal us later (it can't be broken yet!).
*/ */
update_balloon_stats(vb); num_stats = update_balloon_stats(vb);
sg_init_one(&sg, vb->stats, sizeof vb->stats); sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL)
< 0) < 0)
BUG(); BUG();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment