aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio/virtio_balloon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/virtio/virtio_balloon.c')
-rw-r--r--drivers/virtio/virtio_balloon.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index cd778b1752b5..3db3d242c3ee 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -51,6 +51,7 @@ struct virtio_balloon
51 u32 pfns[256]; 51 u32 pfns[256];
52 52
53 /* Memory statistics */ 53 /* Memory statistics */
54 int need_stats_update;
54 struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; 55 struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
55}; 56};
56 57
@@ -193,20 +194,30 @@ static void update_balloon_stats(struct virtio_balloon *vb)
193 * the stats queue operates in reverse. The driver initializes the virtqueue 194 * the stats queue operates in reverse. The driver initializes the virtqueue
194 * with a single buffer. From that point forward, all conversations consist of 195 * with a single buffer. From that point forward, all conversations consist of
195 * a hypervisor request (a call to this function) which directs us to refill 196 * a hypervisor request (a call to this function) which directs us to refill
196 * the virtqueue with a fresh stats buffer. 197 * the virtqueue with a fresh stats buffer. Since stats collection can sleep,
198 * we notify our kthread which does the actual work via stats_handle_request().
197 */ 199 */
198static void stats_ack(struct virtqueue *vq) 200static void stats_request(struct virtqueue *vq)
199{ 201{
200 struct virtio_balloon *vb; 202 struct virtio_balloon *vb;
201 unsigned int len; 203 unsigned int len;
202 struct scatterlist sg;
203 204
204 vb = vq->vq_ops->get_buf(vq, &len); 205 vb = vq->vq_ops->get_buf(vq, &len);
205 if (!vb) 206 if (!vb)
206 return; 207 return;
208 vb->need_stats_update = 1;
209 wake_up(&vb->config_change);
210}
211
212static void stats_handle_request(struct virtio_balloon *vb)
213{
214 struct virtqueue *vq;
215 struct scatterlist sg;
207 216
217 vb->need_stats_update = 0;
208 update_balloon_stats(vb); 218 update_balloon_stats(vb);
209 219
220 vq = vb->stats_vq;
210 sg_init_one(&sg, vb->stats, sizeof(vb->stats)); 221 sg_init_one(&sg, vb->stats, sizeof(vb->stats));
211 if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) < 0) 222 if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) < 0)
212 BUG(); 223 BUG();
@@ -249,8 +260,11 @@ static int balloon(void *_vballoon)
249 try_to_freeze(); 260 try_to_freeze();
250 wait_event_interruptible(vb->config_change, 261 wait_event_interruptible(vb->config_change,
251 (diff = towards_target(vb)) != 0 262 (diff = towards_target(vb)) != 0
263 || vb->need_stats_update
252 || kthread_should_stop() 264 || kthread_should_stop()
253 || freezing(current)); 265 || freezing(current));
266 if (vb->need_stats_update)
267 stats_handle_request(vb);
254 if (diff > 0) 268 if (diff > 0)
255 fill_balloon(vb, diff); 269 fill_balloon(vb, diff);
256 else if (diff < 0) 270 else if (diff < 0)
@@ -264,7 +278,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
264{ 278{
265 struct virtio_balloon *vb; 279 struct virtio_balloon *vb;
266 struct virtqueue *vqs[3]; 280 struct virtqueue *vqs[3];
267 vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_ack }; 281 vq_callback_t *callbacks[] = { balloon_ack, balloon_ack, stats_request };
268 const char *names[] = { "inflate", "deflate", "stats" }; 282 const char *names[] = { "inflate", "deflate", "stats" };
269 int err, nvqs; 283 int err, nvqs;
270 284