Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/page_alloc.c: calculate 'available' memory in a separate function

Add a new field, VIRTIO_BALLOON_S_AVAIL, to virtio_balloon memory
statistics protocol, corresponding to 'Available' in /proc/meminfo.

It indicates to the hypervisor how big the balloon can be inflated
without pushing the guest system to swap. This metric would be very
useful in VM orchestration software to improve memory management of
different VMs under overcommit.

This patch (of 2):

Factor out calculation of the available memory counter into a separate
exportable function, in order to be able to use it in other parts of the
kernel.

In particular, it appears a relevant metric to report to the hypervisor
via virtio-balloon statistics interface (in a followup patch).

Signed-off-by: Igor Redko <redkoi@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Igor Redko and committed by
Linus Torvalds
d02bd27b 7eb50292

+45 -30
+1 -30
fs/proc/meminfo.c
··· 29 29 unsigned long committed; 30 30 long cached; 31 31 long available; 32 - unsigned long pagecache; 33 - unsigned long wmark_low = 0; 34 32 unsigned long pages[NR_LRU_LISTS]; 35 - struct zone *zone; 36 33 int lru; 37 34 38 35 /* ··· 48 51 for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++) 49 52 pages[lru] = global_page_state(NR_LRU_BASE + lru); 50 53 51 - for_each_zone(zone) 52 - wmark_low += zone->watermark[WMARK_LOW]; 53 - 54 - /* 55 - * Estimate the amount of memory available for userspace allocations, 56 - * without causing swapping. 57 - */ 58 - available = i.freeram - totalreserve_pages; 59 - 60 - /* 61 - * Not all the page cache can be freed, otherwise the system will 62 - * start swapping. Assume at least half of the page cache, or the 63 - * low watermark worth of cache, needs to stay. 64 - */ 65 - pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE]; 66 - pagecache -= min(pagecache / 2, wmark_low); 67 - available += pagecache; 68 - 69 - /* 70 - * Part of the reclaimable slab consists of items that are in use, 71 - * and cannot be freed. Cap this estimate at the low watermark. 72 - */ 73 - available += global_page_state(NR_SLAB_RECLAIMABLE) - 74 - min(global_page_state(NR_SLAB_RECLAIMABLE) / 2, wmark_low); 75 - 76 - if (available < 0) 77 - available = 0; 54 + available = si_mem_available(); 78 55 79 56 /* 80 57 * Tagged format, for easy grepping and expansion.
+1
include/linux/mm.h
··· 1875 1875 extern void mem_init(void); 1876 1876 extern void __init mmap_init(void); 1877 1877 extern void show_mem(unsigned int flags); 1878 + extern long si_mem_available(void); 1878 1879 extern void si_meminfo(struct sysinfo * val); 1879 1880 extern void si_meminfo_node(struct sysinfo *val, int nid); 1880 1881
+43
mm/page_alloc.c
··· 3713 3713 printk("Node %d ", zone_to_nid(zone)); 3714 3714 } 3715 3715 3716 + long si_mem_available(void) 3717 + { 3718 + long available; 3719 + unsigned long pagecache; 3720 + unsigned long wmark_low = 0; 3721 + unsigned long pages[NR_LRU_LISTS]; 3722 + struct zone *zone; 3723 + int lru; 3724 + 3725 + for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++) 3726 + pages[lru] = global_page_state(NR_LRU_BASE + lru); 3727 + 3728 + for_each_zone(zone) 3729 + wmark_low += zone->watermark[WMARK_LOW]; 3730 + 3731 + /* 3732 + * Estimate the amount of memory available for userspace allocations, 3733 + * without causing swapping. 3734 + */ 3735 + available = global_page_state(NR_FREE_PAGES) - totalreserve_pages; 3736 + 3737 + /* 3738 + * Not all the page cache can be freed, otherwise the system will 3739 + * start swapping. Assume at least half of the page cache, or the 3740 + * low watermark worth of cache, needs to stay. 3741 + */ 3742 + pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE]; 3743 + pagecache -= min(pagecache / 2, wmark_low); 3744 + available += pagecache; 3745 + 3746 + /* 3747 + * Part of the reclaimable slab consists of items that are in use, 3748 + * and cannot be freed. Cap this estimate at the low watermark. 3749 + */ 3750 + available += global_page_state(NR_SLAB_RECLAIMABLE) - 3751 + min(global_page_state(NR_SLAB_RECLAIMABLE) / 2, wmark_low); 3752 + 3753 + if (available < 0) 3754 + available = 0; 3755 + return available; 3756 + } 3757 + EXPORT_SYMBOL_GPL(si_mem_available); 3758 + 3716 3759 void si_meminfo(struct sysinfo *val) 3717 3760 { 3718 3761 val->totalram = totalram_pages;