Commit 835a6a64 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin

virtio-balloon: Revert "virtio-balloon: Switch back to OOM handler for...

virtio-balloon: Revert "virtio-balloon: Switch back to OOM handler for VIRTIO_BALLOON_F_DEFLATE_ON_OOM"

This reverts commit 5a6b4cc5.

It has been queued properly in the akpm tree, this version is just
creating conflicts.
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent c9b9f5f8
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/balloon_compaction.h> #include <linux/balloon_compaction.h>
#include <linux/oom.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mount.h> #include <linux/mount.h>
...@@ -28,9 +27,7 @@ ...@@ -28,9 +27,7 @@
*/ */
#define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT) #define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
#define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256 #define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
/* Maximum number of (4k) pages to deflate on OOM notifications. */ #define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80
#define VIRTIO_BALLOON_OOM_NR_PAGES 256
#define VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY 80
#define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \ #define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \
__GFP_NOMEMALLOC) __GFP_NOMEMALLOC)
...@@ -115,11 +112,8 @@ struct virtio_balloon { ...@@ -115,11 +112,8 @@ struct virtio_balloon {
/* Memory statistics */ /* Memory statistics */
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
/* Shrinker to return free pages - VIRTIO_BALLOON_F_FREE_PAGE_HINT */ /* To register a shrinker to shrink memory upon memory pressure */
struct shrinker shrinker; struct shrinker shrinker;
/* OOM notifier to deflate on OOM - VIRTIO_BALLOON_F_DEFLATE_ON_OOM */
struct notifier_block oom_nb;
}; };
static struct virtio_device_id id_table[] = { static struct virtio_device_id id_table[] = {
...@@ -794,13 +788,50 @@ static unsigned long shrink_free_pages(struct virtio_balloon *vb, ...@@ -794,13 +788,50 @@ static unsigned long shrink_free_pages(struct virtio_balloon *vb,
return blocks_freed * VIRTIO_BALLOON_HINT_BLOCK_PAGES; return blocks_freed * VIRTIO_BALLOON_HINT_BLOCK_PAGES;
} }
static unsigned long leak_balloon_pages(struct virtio_balloon *vb,
unsigned long pages_to_free)
{
return leak_balloon(vb, pages_to_free * VIRTIO_BALLOON_PAGES_PER_PAGE) /
VIRTIO_BALLOON_PAGES_PER_PAGE;
}
static unsigned long shrink_balloon_pages(struct virtio_balloon *vb,
unsigned long pages_to_free)
{
unsigned long pages_freed = 0;
/*
* One invocation of leak_balloon can deflate at most
* VIRTIO_BALLOON_ARRAY_PFNS_MAX balloon pages, so we call it
* multiple times to deflate pages till reaching pages_to_free.
*/
while (vb->num_pages && pages_freed < pages_to_free)
pages_freed += leak_balloon_pages(vb,
pages_to_free - pages_freed);
update_balloon_size(vb);
return pages_freed;
}
static unsigned long virtio_balloon_shrinker_scan(struct shrinker *shrinker, static unsigned long virtio_balloon_shrinker_scan(struct shrinker *shrinker,
struct shrink_control *sc) struct shrink_control *sc)
{ {
unsigned long pages_to_free, pages_freed = 0;
struct virtio_balloon *vb = container_of(shrinker, struct virtio_balloon *vb = container_of(shrinker,
struct virtio_balloon, shrinker); struct virtio_balloon, shrinker);
return shrink_free_pages(vb, sc->nr_to_scan); pages_to_free = sc->nr_to_scan;
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
pages_freed = shrink_free_pages(vb, pages_to_free);
if (pages_freed >= pages_to_free)
return pages_freed;
pages_freed += shrink_balloon_pages(vb, pages_to_free - pages_freed);
return pages_freed;
} }
static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker, static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker,
...@@ -808,22 +839,26 @@ static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker, ...@@ -808,22 +839,26 @@ static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker,
{ {
struct virtio_balloon *vb = container_of(shrinker, struct virtio_balloon *vb = container_of(shrinker,
struct virtio_balloon, shrinker); struct virtio_balloon, shrinker);
unsigned long count;
count = vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE;
count += vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES;
return vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES; return count;
} }
static int virtio_balloon_oom_notify(struct notifier_block *nb, static void virtio_balloon_unregister_shrinker(struct virtio_balloon *vb)
unsigned long dummy, void *parm)
{ {
struct virtio_balloon *vb = container_of(nb, unregister_shrinker(&vb->shrinker);
struct virtio_balloon, oom_nb); }
unsigned long *freed = parm;
*freed += leak_balloon(vb, VIRTIO_BALLOON_OOM_NR_PAGES) / static int virtio_balloon_register_shrinker(struct virtio_balloon *vb)
VIRTIO_BALLOON_PAGES_PER_PAGE; {
update_balloon_size(vb); vb->shrinker.scan_objects = virtio_balloon_shrinker_scan;
vb->shrinker.count_objects = virtio_balloon_shrinker_count;
vb->shrinker.seeks = DEFAULT_SEEKS;
return NOTIFY_OK; return register_shrinker(&vb->shrinker);
} }
static int virtballoon_probe(struct virtio_device *vdev) static int virtballoon_probe(struct virtio_device *vdev)
...@@ -900,35 +935,22 @@ static int virtballoon_probe(struct virtio_device *vdev) ...@@ -900,35 +935,22 @@ static int virtballoon_probe(struct virtio_device *vdev)
virtio_cwrite(vb->vdev, struct virtio_balloon_config, virtio_cwrite(vb->vdev, struct virtio_balloon_config,
poison_val, &poison_val); poison_val, &poison_val);
} }
}
/* /*
* We're allowed to reuse any free pages, even if they are * We continue to use VIRTIO_BALLOON_F_DEFLATE_ON_OOM to decide if a
* still to be processed by the host. * shrinker needs to be registered to relieve memory pressure.
*/ */
vb->shrinker.scan_objects = virtio_balloon_shrinker_scan; if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) {
vb->shrinker.count_objects = virtio_balloon_shrinker_count; err = virtio_balloon_register_shrinker(vb);
vb->shrinker.seeks = DEFAULT_SEEKS;
err = register_shrinker(&vb->shrinker);
if (err) if (err)
goto out_del_balloon_wq; goto out_del_balloon_wq;
} }
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) {
vb->oom_nb.notifier_call = virtio_balloon_oom_notify;
vb->oom_nb.priority = VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY;
err = register_oom_notifier(&vb->oom_nb);
if (err < 0)
goto out_unregister_shrinker;
}
virtio_device_ready(vdev); virtio_device_ready(vdev);
if (towards_target(vb)) if (towards_target(vb))
virtballoon_changed(vdev); virtballoon_changed(vdev);
return 0; return 0;
out_unregister_shrinker:
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
unregister_shrinker(&vb->shrinker);
out_del_balloon_wq: out_del_balloon_wq:
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
destroy_workqueue(vb->balloon_wq); destroy_workqueue(vb->balloon_wq);
...@@ -967,11 +989,8 @@ static void virtballoon_remove(struct virtio_device *vdev) ...@@ -967,11 +989,8 @@ static void virtballoon_remove(struct virtio_device *vdev)
{ {
struct virtio_balloon *vb = vdev->priv; struct virtio_balloon *vb = vdev->priv;
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
unregister_oom_notifier(&vb->oom_nb); virtio_balloon_unregister_shrinker(vb);
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
unregister_shrinker(&vb->shrinker);
spin_lock_irq(&vb->stop_update_lock); spin_lock_irq(&vb->stop_update_lock);
vb->stop_update = true; vb->stop_update = true;
spin_unlock_irq(&vb->stop_update_lock); spin_unlock_irq(&vb->stop_update_lock);
......
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