Message ID | 1465405088-595-1-git-send-email-tim.gardner@canonical.com |
---|---|
State | New |
Headers | show |
Ack for both patches. Backport looks correct and cherry-pick seems reasonable. I think this feature addition is minimal enough in just reporting additional information which can be very useful when trying to allocate vms on a system. --chris On Wed, Jun 08, 2016 at 10:58:07AM -0600, Tim Gardner wrote: > From: Igor Redko <redkoi@virtuozzo.com> > > BugLink: http://bugs.launchpad.net/bugs/1587091 > > 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> > (back ported from commit d02bd27bd33dd7e8d22594cd568b81be0cb584cd) > Signed-off-by: Tim Gardner <tim.gardner@canonical.com> > > Conflicts: > fs/proc/meminfo.c > --- > fs/proc/meminfo.c | 34 +--------------------------------- > include/linux/mm.h | 1 + > mm/page_alloc.c | 43 +++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 45 insertions(+), 33 deletions(-) > > diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c > index 9155a5a..8372046 100644 > --- a/fs/proc/meminfo.c > +++ b/fs/proc/meminfo.c > @@ -29,10 +29,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v) > unsigned long committed; > long cached; > long available; > - unsigned long pagecache; > - unsigned long wmark_low = 0; > unsigned long pages[NR_LRU_LISTS]; > - struct zone *zone; > int lru; > > /* > @@ -51,36 +48,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v) > for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++) > pages[lru] = global_page_state(NR_LRU_BASE + lru); > > - for_each_zone(zone) > - wmark_low += zone->watermark[WMARK_LOW]; > - > - /* > - * Estimate the amount of memory available for userspace allocations, > - * without causing swapping. > - * > - * Free memory cannot be taken below the low watermark, before the > - * system starts swapping. > - */ > - available = i.freeram - wmark_low; > - > - /* > - * Not all the page cache can be freed, otherwise the system will > - * start swapping. Assume at least half of the page cache, or the > - * low watermark worth of cache, needs to stay. > - */ > - pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE]; > - pagecache -= min(pagecache / 2, wmark_low); > - available += pagecache; > - > - /* > - * Part of the reclaimable slab consists of items that are in use, > - * and cannot be freed. Cap this estimate at the low watermark. > - */ > - available += global_page_state(NR_SLAB_RECLAIMABLE) - > - min(global_page_state(NR_SLAB_RECLAIMABLE) / 2, wmark_low); > - > - if (available < 0) > - available = 0; > + available = si_mem_available(); > > /* > * Tagged format, for easy grepping and expansion. > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 70cbf8c..3b13fd3 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -1829,6 +1829,7 @@ extern int __meminit init_per_zone_wmark_min(void); > extern void mem_init(void); > extern void __init mmap_init(void); > extern void show_mem(unsigned int flags); > +extern long si_mem_available(void); > extern void si_meminfo(struct sysinfo * val); > extern void si_meminfo_node(struct sysinfo *val, int nid); > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 6cf5cad..2f4e66a 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -3604,6 +3604,49 @@ static inline void show_node(struct zone *zone) > printk("Node %d ", zone_to_nid(zone)); > } > > +long si_mem_available(void) > +{ > + long available; > + unsigned long pagecache; > + unsigned long wmark_low = 0; > + unsigned long pages[NR_LRU_LISTS]; > + struct zone *zone; > + int lru; > + > + for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++) > + pages[lru] = global_page_state(NR_LRU_BASE + lru); > + > + for_each_zone(zone) > + wmark_low += zone->watermark[WMARK_LOW]; > + > + /* > + * Estimate the amount of memory available for userspace allocations, > + * without causing swapping. > + */ > + available = global_page_state(NR_FREE_PAGES) - totalreserve_pages; > + > + /* > + * Not all the page cache can be freed, otherwise the system will > + * start swapping. Assume at least half of the page cache, or the > + * low watermark worth of cache, needs to stay. > + */ > + pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE]; > + pagecache -= min(pagecache / 2, wmark_low); > + available += pagecache; > + > + /* > + * Part of the reclaimable slab consists of items that are in use, > + * and cannot be freed. Cap this estimate at the low watermark. > + */ > + available += global_page_state(NR_SLAB_RECLAIMABLE) - > + min(global_page_state(NR_SLAB_RECLAIMABLE) / 2, wmark_low); > + > + if (available < 0) > + available = 0; > + return available; > +} > +EXPORT_SYMBOL_GPL(si_mem_available); > + > void si_meminfo(struct sysinfo *val) > { > val->totalram = totalram_pages; > -- > 1.9.1 > > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team
Applied to X. -Kamal
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 9155a5a..8372046 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -29,10 +29,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v) unsigned long committed; long cached; long available; - unsigned long pagecache; - unsigned long wmark_low = 0; unsigned long pages[NR_LRU_LISTS]; - struct zone *zone; int lru; /* @@ -51,36 +48,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v) for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++) pages[lru] = global_page_state(NR_LRU_BASE + lru); - for_each_zone(zone) - wmark_low += zone->watermark[WMARK_LOW]; - - /* - * Estimate the amount of memory available for userspace allocations, - * without causing swapping. - * - * Free memory cannot be taken below the low watermark, before the - * system starts swapping. - */ - available = i.freeram - wmark_low; - - /* - * Not all the page cache can be freed, otherwise the system will - * start swapping. Assume at least half of the page cache, or the - * low watermark worth of cache, needs to stay. - */ - pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE]; - pagecache -= min(pagecache / 2, wmark_low); - available += pagecache; - - /* - * Part of the reclaimable slab consists of items that are in use, - * and cannot be freed. Cap this estimate at the low watermark. - */ - available += global_page_state(NR_SLAB_RECLAIMABLE) - - min(global_page_state(NR_SLAB_RECLAIMABLE) / 2, wmark_low); - - if (available < 0) - available = 0; + available = si_mem_available(); /* * Tagged format, for easy grepping and expansion. diff --git a/include/linux/mm.h b/include/linux/mm.h index 70cbf8c..3b13fd3 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1829,6 +1829,7 @@ extern int __meminit init_per_zone_wmark_min(void); extern void mem_init(void); extern void __init mmap_init(void); extern void show_mem(unsigned int flags); +extern long si_mem_available(void); extern void si_meminfo(struct sysinfo * val); extern void si_meminfo_node(struct sysinfo *val, int nid); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6cf5cad..2f4e66a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3604,6 +3604,49 @@ static inline void show_node(struct zone *zone) printk("Node %d ", zone_to_nid(zone)); } +long si_mem_available(void) +{ + long available; + unsigned long pagecache; + unsigned long wmark_low = 0; + unsigned long pages[NR_LRU_LISTS]; + struct zone *zone; + int lru; + + for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++) + pages[lru] = global_page_state(NR_LRU_BASE + lru); + + for_each_zone(zone) + wmark_low += zone->watermark[WMARK_LOW]; + + /* + * Estimate the amount of memory available for userspace allocations, + * without causing swapping. + */ + available = global_page_state(NR_FREE_PAGES) - totalreserve_pages; + + /* + * Not all the page cache can be freed, otherwise the system will + * start swapping. Assume at least half of the page cache, or the + * low watermark worth of cache, needs to stay. + */ + pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE]; + pagecache -= min(pagecache / 2, wmark_low); + available += pagecache; + + /* + * Part of the reclaimable slab consists of items that are in use, + * and cannot be freed. Cap this estimate at the low watermark. + */ + available += global_page_state(NR_SLAB_RECLAIMABLE) - + min(global_page_state(NR_SLAB_RECLAIMABLE) / 2, wmark_low); + + if (available < 0) + available = 0; + return available; +} +EXPORT_SYMBOL_GPL(si_mem_available); + void si_meminfo(struct sysinfo *val) { val->totalram = totalram_pages;