| From foo@baz Thu Dec 21 09:02:40 CET 2017 |
| From: Ladi Prosek <lprosek@redhat.com> |
| Date: Tue, 28 Mar 2017 18:46:58 +0200 |
| Subject: virtio-balloon: use actual number of stats for stats queue buffers |
| |
| From: Ladi Prosek <lprosek@redhat.com> |
| |
| |
| [ Upstream commit 9646b26e85896ef0256e66649f7937f774dc18a6 ] |
| |
| 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: Arnd Bergmann <arnd@arndb.de> |
| Signed-off-by: Ladi Prosek <lprosek@redhat.com> |
| Signed-off-by: Michael S. Tsirkin <mst@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/virtio/virtio_balloon.c | 17 ++++++++++------- |
| 1 file changed, 10 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/virtio/virtio_balloon.c |
| +++ b/drivers/virtio/virtio_balloon.c |
| @@ -241,11 +241,11 @@ static inline void update_stat(struct vi |
| |
| #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]; |
| struct sysinfo i; |
| - int idx = 0; |
| + unsigned int idx = 0; |
| long available; |
| |
| all_vm_events(events); |
| @@ -265,6 +265,8 @@ static void update_balloon_stats(struct |
| pages_to_bytes(i.totalram)); |
| update_stat(vb, idx++, VIRTIO_BALLOON_S_AVAIL, |
| pages_to_bytes(available)); |
| + |
| + return idx; |
| } |
| |
| /* |
| @@ -290,14 +292,14 @@ static void stats_handle_request(struct |
| { |
| struct virtqueue *vq; |
| 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; |
| if (!virtqueue_get_buf(vq, &len)) |
| 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_kick(vq); |
| } |
| @@ -421,15 +423,16 @@ static int init_vqs(struct virtio_balloo |
| vb->deflate_vq = vqs[1]; |
| if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { |
| struct scatterlist sg; |
| + unsigned int num_stats; |
| vb->stats_vq = vqs[2]; |
| |
| /* |
| * Prime this virtqueue with one buffer so the hypervisor can |
| * 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) |
| < 0) |
| BUG(); |