aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/virtio/virtio_balloon.c52
-rw-r--r--include/uapi/linux/virtio_balloon.h1
2 files changed, 53 insertions, 0 deletions
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index ff71fdcf3345..50c5f42d7a9f 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -28,6 +28,7 @@
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/balloon_compaction.h> 30#include <linux/balloon_compaction.h>
31#include <linux/oom.h>
31 32
32/* 33/*
33 * Balloon device works in 4K page units. So each page is pointed to by 34 * Balloon device works in 4K page units. So each page is pointed to by
@@ -36,6 +37,12 @@
36 */ 37 */
37#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) 38#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
38#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256 39#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
40#define OOM_VBALLOON_DEFAULT_PAGES 256
41#define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80
42
43static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES;
44module_param(oom_pages, int, S_IRUSR | S_IWUSR);
45MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
39 46
40struct virtio_balloon 47struct virtio_balloon
41{ 48{
@@ -71,6 +78,9 @@ struct virtio_balloon
71 /* Memory statistics */ 78 /* Memory statistics */
72 int need_stats_update; 79 int need_stats_update;
73 struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; 80 struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
81
82 /* To register callback in oom notifier call chain */
83 struct notifier_block nb;
74}; 84};
75 85
76static struct virtio_device_id id_table[] = { 86static struct virtio_device_id id_table[] = {
@@ -290,6 +300,38 @@ static void update_balloon_size(struct virtio_balloon *vb)
290 &actual); 300 &actual);
291} 301}
292 302
303/*
304 * virtballoon_oom_notify - release pages when system is under severe
305 * memory pressure (called from out_of_memory())
306 * @self : notifier block struct
307 * @dummy: not used
308 * @parm : returned - number of freed pages
309 *
310 * The balancing of memory by use of the virtio balloon should not cause
311 * the termination of processes while there are pages in the balloon.
312 * If virtio balloon manages to release some memory, it will make the
313 * system return and retry the allocation that forced the OOM killer
314 * to run.
315 */
316static int virtballoon_oom_notify(struct notifier_block *self,
317 unsigned long dummy, void *parm)
318{
319 struct virtio_balloon *vb;
320 unsigned long *freed;
321 unsigned num_freed_pages;
322
323 vb = container_of(self, struct virtio_balloon, nb);
324 if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
325 return NOTIFY_OK;
326
327 freed = parm;
328 num_freed_pages = leak_balloon(vb, oom_pages);
329 update_balloon_size(vb);
330 *freed += num_freed_pages;
331
332 return NOTIFY_OK;
333}
334
293static int balloon(void *_vballoon) 335static int balloon(void *_vballoon)
294{ 336{
295 struct virtio_balloon *vb = _vballoon; 337 struct virtio_balloon *vb = _vballoon;
@@ -446,6 +488,12 @@ static int virtballoon_probe(struct virtio_device *vdev)
446 if (err) 488 if (err)
447 goto out_free_vb; 489 goto out_free_vb;
448 490
491 vb->nb.notifier_call = virtballoon_oom_notify;
492 vb->nb.priority = VIRTBALLOON_OOM_NOTIFY_PRIORITY;
493 err = register_oom_notifier(&vb->nb);
494 if (err < 0)
495 goto out_oom_notify;
496
449 vb->thread = kthread_run(balloon, vb, "vballoon"); 497 vb->thread = kthread_run(balloon, vb, "vballoon");
450 if (IS_ERR(vb->thread)) { 498 if (IS_ERR(vb->thread)) {
451 err = PTR_ERR(vb->thread); 499 err = PTR_ERR(vb->thread);
@@ -455,6 +503,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
455 return 0; 503 return 0;
456 504
457out_del_vqs: 505out_del_vqs:
506 unregister_oom_notifier(&vb->nb);
507out_oom_notify:
458 vdev->config->del_vqs(vdev); 508 vdev->config->del_vqs(vdev);
459out_free_vb: 509out_free_vb:
460 kfree(vb); 510 kfree(vb);
@@ -479,6 +529,7 @@ static void virtballoon_remove(struct virtio_device *vdev)
479{ 529{
480 struct virtio_balloon *vb = vdev->priv; 530 struct virtio_balloon *vb = vdev->priv;
481 531
532 unregister_oom_notifier(&vb->nb);
482 kthread_stop(vb->thread); 533 kthread_stop(vb->thread);
483 remove_common(vb); 534 remove_common(vb);
484 kfree(vb); 535 kfree(vb);
@@ -518,6 +569,7 @@ static int virtballoon_restore(struct virtio_device *vdev)
518static unsigned int features[] = { 569static unsigned int features[] = {
519 VIRTIO_BALLOON_F_MUST_TELL_HOST, 570 VIRTIO_BALLOON_F_MUST_TELL_HOST,
520 VIRTIO_BALLOON_F_STATS_VQ, 571 VIRTIO_BALLOON_F_STATS_VQ,
572 VIRTIO_BALLOON_F_DEFLATE_ON_OOM,
521}; 573};
522 574
523static struct virtio_driver virtio_balloon_driver = { 575static struct virtio_driver virtio_balloon_driver = {
diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h
index 5e26f61b5df5..be40f7059e93 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -31,6 +31,7 @@
31/* The feature bitmap for virtio balloon */ 31/* The feature bitmap for virtio balloon */
32#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */ 32#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */
33#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */ 33#define VIRTIO_BALLOON_F_STATS_VQ 1 /* Memory Stats virtqueue */
34#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */
34 35
35/* Size of a PFN in the balloon interface. */ 36/* Size of a PFN in the balloon interface. */
36#define VIRTIO_BALLOON_PFN_SHIFT 12 37#define VIRTIO_BALLOON_PFN_SHIFT 12