|
14 | 14 | #include <linux/slab.h>
|
15 | 15 | #include <linux/module.h>
|
16 | 16 | #include <linux/balloon_compaction.h>
|
17 |
| -#include <linux/oom.h> |
18 | 17 | #include <linux/wait.h>
|
19 | 18 | #include <linux/mm.h>
|
20 | 19 | #include <linux/mount.h>
|
|
28 | 27 | */
|
29 | 28 | #define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
|
30 | 29 | #define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
|
31 |
| -/* Maximum number of (4k) pages to deflate on OOM notifications. */ |
32 |
| -#define VIRTIO_BALLOON_OOM_NR_PAGES 256 |
33 |
| -#define VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY 80 |
| 30 | +#define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80 |
34 | 31 |
|
35 | 32 | #define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \
|
36 | 33 | __GFP_NOMEMALLOC)
|
@@ -115,11 +112,8 @@ struct virtio_balloon {
|
115 | 112 | /* Memory statistics */
|
116 | 113 | struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
|
117 | 114 |
|
118 |
| - /* Shrinker to return free pages - VIRTIO_BALLOON_F_FREE_PAGE_HINT */ |
| 115 | + /* To register a shrinker to shrink memory upon memory pressure */ |
119 | 116 | struct shrinker shrinker;
|
120 |
| - |
121 |
| - /* OOM notifier to deflate on OOM - VIRTIO_BALLOON_F_DEFLATE_ON_OOM */ |
122 |
| - struct notifier_block oom_nb; |
123 | 117 | };
|
124 | 118 |
|
125 | 119 | static struct virtio_device_id id_table[] = {
|
@@ -794,36 +788,77 @@ static unsigned long shrink_free_pages(struct virtio_balloon *vb,
|
794 | 788 | return blocks_freed * VIRTIO_BALLOON_HINT_BLOCK_PAGES;
|
795 | 789 | }
|
796 | 790 |
|
| 791 | +static unsigned long leak_balloon_pages(struct virtio_balloon *vb, |
| 792 | + unsigned long pages_to_free) |
| 793 | +{ |
| 794 | + return leak_balloon(vb, pages_to_free * VIRTIO_BALLOON_PAGES_PER_PAGE) / |
| 795 | + VIRTIO_BALLOON_PAGES_PER_PAGE; |
| 796 | +} |
| 797 | + |
| 798 | +static unsigned long shrink_balloon_pages(struct virtio_balloon *vb, |
| 799 | + unsigned long pages_to_free) |
| 800 | +{ |
| 801 | + unsigned long pages_freed = 0; |
| 802 | + |
| 803 | + /* |
| 804 | + * One invocation of leak_balloon can deflate at most |
| 805 | + * VIRTIO_BALLOON_ARRAY_PFNS_MAX balloon pages, so we call it |
| 806 | + * multiple times to deflate pages till reaching pages_to_free. |
| 807 | + */ |
| 808 | + while (vb->num_pages && pages_freed < pages_to_free) |
| 809 | + pages_freed += leak_balloon_pages(vb, |
| 810 | + pages_to_free - pages_freed); |
| 811 | + |
| 812 | + update_balloon_size(vb); |
| 813 | + |
| 814 | + return pages_freed; |
| 815 | +} |
| 816 | + |
797 | 817 | static unsigned long virtio_balloon_shrinker_scan(struct shrinker *shrinker,
|
798 | 818 | struct shrink_control *sc)
|
799 | 819 | {
|
| 820 | + unsigned long pages_to_free, pages_freed = 0; |
800 | 821 | struct virtio_balloon *vb = container_of(shrinker,
|
801 | 822 | struct virtio_balloon, shrinker);
|
802 | 823 |
|
803 |
| - return shrink_free_pages(vb, sc->nr_to_scan); |
| 824 | + pages_to_free = sc->nr_to_scan; |
| 825 | + |
| 826 | + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) |
| 827 | + pages_freed = shrink_free_pages(vb, pages_to_free); |
| 828 | + |
| 829 | + if (pages_freed >= pages_to_free) |
| 830 | + return pages_freed; |
| 831 | + |
| 832 | + pages_freed += shrink_balloon_pages(vb, pages_to_free - pages_freed); |
| 833 | + |
| 834 | + return pages_freed; |
804 | 835 | }
|
805 | 836 |
|
806 | 837 | static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker,
|
807 | 838 | struct shrink_control *sc)
|
808 | 839 | {
|
809 | 840 | struct virtio_balloon *vb = container_of(shrinker,
|
810 | 841 | struct virtio_balloon, shrinker);
|
| 842 | + unsigned long count; |
| 843 | + |
| 844 | + count = vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE; |
| 845 | + count += vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES; |
811 | 846 |
|
812 |
| - return vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES; |
| 847 | + return count; |
813 | 848 | }
|
814 | 849 |
|
815 |
| -static int virtio_balloon_oom_notify(struct notifier_block *nb, |
816 |
| - unsigned long dummy, void *parm) |
| 850 | +static void virtio_balloon_unregister_shrinker(struct virtio_balloon *vb) |
817 | 851 | {
|
818 |
| - struct virtio_balloon *vb = container_of(nb, |
819 |
| - struct virtio_balloon, oom_nb); |
820 |
| - unsigned long *freed = parm; |
| 852 | + unregister_shrinker(&vb->shrinker); |
| 853 | +} |
821 | 854 |
|
822 |
| - *freed += leak_balloon(vb, VIRTIO_BALLOON_OOM_NR_PAGES) / |
823 |
| - VIRTIO_BALLOON_PAGES_PER_PAGE; |
824 |
| - update_balloon_size(vb); |
| 855 | +static int virtio_balloon_register_shrinker(struct virtio_balloon *vb) |
| 856 | +{ |
| 857 | + vb->shrinker.scan_objects = virtio_balloon_shrinker_scan; |
| 858 | + vb->shrinker.count_objects = virtio_balloon_shrinker_count; |
| 859 | + vb->shrinker.seeks = DEFAULT_SEEKS; |
825 | 860 |
|
826 |
| - return NOTIFY_OK; |
| 861 | + return register_shrinker(&vb->shrinker); |
827 | 862 | }
|
828 | 863 |
|
829 | 864 | static int virtballoon_probe(struct virtio_device *vdev)
|
@@ -900,35 +935,22 @@ static int virtballoon_probe(struct virtio_device *vdev)
|
900 | 935 | virtio_cwrite(vb->vdev, struct virtio_balloon_config,
|
901 | 936 | poison_val, &poison_val);
|
902 | 937 | }
|
903 |
| - |
904 |
| - /* |
905 |
| - * We're allowed to reuse any free pages, even if they are |
906 |
| - * still to be processed by the host. |
907 |
| - */ |
908 |
| - vb->shrinker.scan_objects = virtio_balloon_shrinker_scan; |
909 |
| - vb->shrinker.count_objects = virtio_balloon_shrinker_count; |
910 |
| - vb->shrinker.seeks = DEFAULT_SEEKS; |
911 |
| - err = register_shrinker(&vb->shrinker); |
| 938 | + } |
| 939 | + /* |
| 940 | + * We continue to use VIRTIO_BALLOON_F_DEFLATE_ON_OOM to decide if a |
| 941 | + * shrinker needs to be registered to relieve memory pressure. |
| 942 | + */ |
| 943 | + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) { |
| 944 | + err = virtio_balloon_register_shrinker(vb); |
912 | 945 | if (err)
|
913 | 946 | goto out_del_balloon_wq;
|
914 | 947 | }
|
915 |
| - if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) { |
916 |
| - vb->oom_nb.notifier_call = virtio_balloon_oom_notify; |
917 |
| - vb->oom_nb.priority = VIRTIO_BALLOON_OOM_NOTIFY_PRIORITY; |
918 |
| - err = register_oom_notifier(&vb->oom_nb); |
919 |
| - if (err < 0) |
920 |
| - goto out_unregister_shrinker; |
921 |
| - } |
922 |
| - |
923 | 948 | virtio_device_ready(vdev);
|
924 | 949 |
|
925 | 950 | if (towards_target(vb))
|
926 | 951 | virtballoon_changed(vdev);
|
927 | 952 | return 0;
|
928 | 953 |
|
929 |
| -out_unregister_shrinker: |
930 |
| - if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) |
931 |
| - unregister_shrinker(&vb->shrinker); |
932 | 954 | out_del_balloon_wq:
|
933 | 955 | if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
|
934 | 956 | destroy_workqueue(vb->balloon_wq);
|
@@ -967,11 +989,8 @@ static void virtballoon_remove(struct virtio_device *vdev)
|
967 | 989 | {
|
968 | 990 | struct virtio_balloon *vb = vdev->priv;
|
969 | 991 |
|
970 |
| - if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) |
971 |
| - unregister_oom_notifier(&vb->oom_nb); |
972 |
| - if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) |
973 |
| - unregister_shrinker(&vb->shrinker); |
974 |
| - |
| 992 | + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) |
| 993 | + virtio_balloon_unregister_shrinker(vb); |
975 | 994 | spin_lock_irq(&vb->stop_update_lock);
|
976 | 995 | vb->stop_update = true;
|
977 | 996 | spin_unlock_irq(&vb->stop_update_lock);
|
|
0 commit comments