Commit 3d6357de authored by Arun KS's avatar Arun KS Committed by Linus Torvalds

mm: reference totalram_pages and managed_pages once per function

Patch series "mm: convert totalram_pages, totalhigh_pages and managed
pages to atomic", v5.

This series converts totalram_pages, totalhigh_pages and
zone->managed_pages to atomic variables.

totalram_pages, zone->managed_pages and totalhigh_pages updates are
protected by managed_page_count_lock, but readers never care about it.
Convert these variables to atomic to avoid readers potentially seeing a
store tear.

Main motivation was that managed_page_count_lock handling was complicating
things.  It was discussed in length here,
https://lore.kernel.org/patchwork/patch/995739/#1181785 It seemes better
to remove the lock and convert variables to atomic.  With the change,
preventing poteintial store-to-read tearing comes as a bonus.

This patch (of 4):

This is in preparation to a later patch which converts totalram_pages and
zone->managed_pages to atomic variables.  Please note that re-reading the
value might lead to a different value and as such it could lead to
unexpected behavior.  There are no known bugs as a result of the current
code but it is better to prevent from them in principle.

Link: http://lkml.kernel.org/r/1542090790-21750-2-git-send-email-arunks@codeaurora.orgSigned-off-by: default avatarArun KS <arunks@codeaurora.org>
Reviewed-by: default avatarKonstantin Khlebnikov <khlebnikov@yandex-team.ru>
Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
Acked-by: default avatarMichal Hocko <mhocko@suse.com>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Reviewed-by: default avatarPavel Tatashin <pasha.tatashin@soleen.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent fecd4a50
...@@ -52,7 +52,7 @@ void __init mem_init(void) ...@@ -52,7 +52,7 @@ void __init mem_init(void)
/* this will put all low memory onto the freelists */ /* this will put all low memory onto the freelists */
memblock_free_all(); memblock_free_all();
max_low_pfn = totalram_pages; max_low_pfn = totalram_pages;
max_pfn = totalram_pages; max_pfn = max_low_pfn;
mem_init_print_info(NULL); mem_init_print_info(NULL);
kmalloc_ok = 1; kmalloc_ok = 1;
} }
......
...@@ -434,9 +434,10 @@ static ssize_t microcode_write(struct file *file, const char __user *buf, ...@@ -434,9 +434,10 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
size_t len, loff_t *ppos) size_t len, loff_t *ppos)
{ {
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
unsigned long nr_pages = totalram_pages;
if ((len >> PAGE_SHIFT) > totalram_pages) { if ((len >> PAGE_SHIFT) > nr_pages) {
pr_err("too much data (max %ld pages)\n", totalram_pages); pr_err("too much data (max %ld pages)\n", nr_pages);
return ret; return ret;
} }
......
...@@ -1090,6 +1090,7 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) ...@@ -1090,6 +1090,7 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
static unsigned long compute_balloon_floor(void) static unsigned long compute_balloon_floor(void)
{ {
unsigned long min_pages; unsigned long min_pages;
unsigned long nr_pages = totalram_pages;
#define MB2PAGES(mb) ((mb) << (20 - PAGE_SHIFT)) #define MB2PAGES(mb) ((mb) << (20 - PAGE_SHIFT))
/* Simple continuous piecewiese linear function: /* Simple continuous piecewiese linear function:
* max MiB -> min MiB gradient * max MiB -> min MiB gradient
...@@ -1102,16 +1103,16 @@ static unsigned long compute_balloon_floor(void) ...@@ -1102,16 +1103,16 @@ static unsigned long compute_balloon_floor(void)
* 8192 744 (1/16) * 8192 744 (1/16)
* 32768 1512 (1/32) * 32768 1512 (1/32)
*/ */
if (totalram_pages < MB2PAGES(128)) if (nr_pages < MB2PAGES(128))
min_pages = MB2PAGES(8) + (totalram_pages >> 1); min_pages = MB2PAGES(8) + (nr_pages >> 1);
else if (totalram_pages < MB2PAGES(512)) else if (nr_pages < MB2PAGES(512))
min_pages = MB2PAGES(40) + (totalram_pages >> 2); min_pages = MB2PAGES(40) + (nr_pages >> 2);
else if (totalram_pages < MB2PAGES(2048)) else if (nr_pages < MB2PAGES(2048))
min_pages = MB2PAGES(104) + (totalram_pages >> 3); min_pages = MB2PAGES(104) + (nr_pages >> 3);
else if (totalram_pages < MB2PAGES(8192)) else if (nr_pages < MB2PAGES(8192))
min_pages = MB2PAGES(232) + (totalram_pages >> 4); min_pages = MB2PAGES(232) + (nr_pages >> 4);
else else
min_pages = MB2PAGES(488) + (totalram_pages >> 5); min_pages = MB2PAGES(488) + (nr_pages >> 5);
#undef MB2PAGES #undef MB2PAGES
return min_pages; return min_pages;
} }
......
...@@ -380,10 +380,11 @@ void __init files_init(void) ...@@ -380,10 +380,11 @@ void __init files_init(void)
void __init files_maxfiles_init(void) void __init files_maxfiles_init(void)
{ {
unsigned long n; unsigned long n;
unsigned long memreserve = (totalram_pages - nr_free_pages()) * 3/2; unsigned long nr_pages = totalram_pages;
unsigned long memreserve = (nr_pages - nr_free_pages()) * 3/2;
memreserve = min(memreserve, totalram_pages - 1); memreserve = min(memreserve, nr_pages - 1);
n = ((totalram_pages - memreserve) * (PAGE_SIZE / 1024)) / 10; n = ((nr_pages - memreserve) * (PAGE_SIZE / 1024)) / 10;
files_stat.max_files = max_t(unsigned long, n, NR_FILE); files_stat.max_files = max_t(unsigned long, n, NR_FILE);
} }
...@@ -744,15 +744,16 @@ void __init __weak arch_task_cache_init(void) { } ...@@ -744,15 +744,16 @@ void __init __weak arch_task_cache_init(void) { }
static void set_max_threads(unsigned int max_threads_suggested) static void set_max_threads(unsigned int max_threads_suggested)
{ {
u64 threads; u64 threads;
unsigned long nr_pages = totalram_pages;
/* /*
* The number of threads shall be limited such that the thread * The number of threads shall be limited such that the thread
* structures may only consume a small part of the available memory. * structures may only consume a small part of the available memory.
*/ */
if (fls64(totalram_pages) + fls64(PAGE_SIZE) > 64) if (fls64(nr_pages) + fls64(PAGE_SIZE) > 64)
threads = MAX_THREADS; threads = MAX_THREADS;
else else
threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, threads = div64_u64((u64) nr_pages * (u64) PAGE_SIZE,
(u64) THREAD_SIZE * 8UL); (u64) THREAD_SIZE * 8UL);
if (threads > max_threads_suggested) if (threads > max_threads_suggested)
......
...@@ -152,6 +152,7 @@ int sanity_check_segment_list(struct kimage *image) ...@@ -152,6 +152,7 @@ int sanity_check_segment_list(struct kimage *image)
int i; int i;
unsigned long nr_segments = image->nr_segments; unsigned long nr_segments = image->nr_segments;
unsigned long total_pages = 0; unsigned long total_pages = 0;
unsigned long nr_pages = totalram_pages;
/* /*
* Verify we have good destination addresses. The caller is * Verify we have good destination addresses. The caller is
...@@ -217,13 +218,13 @@ int sanity_check_segment_list(struct kimage *image) ...@@ -217,13 +218,13 @@ int sanity_check_segment_list(struct kimage *image)
* wasted allocating pages, which can cause a soft lockup. * wasted allocating pages, which can cause a soft lockup.
*/ */
for (i = 0; i < nr_segments; i++) { for (i = 0; i < nr_segments; i++) {
if (PAGE_COUNT(image->segment[i].memsz) > totalram_pages / 2) if (PAGE_COUNT(image->segment[i].memsz) > nr_pages / 2)
return -EINVAL; return -EINVAL;
total_pages += PAGE_COUNT(image->segment[i].memsz); total_pages += PAGE_COUNT(image->segment[i].memsz);
} }
if (total_pages > totalram_pages / 2) if (total_pages > nr_pages / 2)
return -EINVAL; return -EINVAL;
/* /*
......
...@@ -7257,6 +7257,7 @@ static void calculate_totalreserve_pages(void) ...@@ -7257,6 +7257,7 @@ static void calculate_totalreserve_pages(void)
for (i = 0; i < MAX_NR_ZONES; i++) { for (i = 0; i < MAX_NR_ZONES; i++) {
struct zone *zone = pgdat->node_zones + i; struct zone *zone = pgdat->node_zones + i;
long max = 0; long max = 0;
unsigned long managed_pages = zone->managed_pages;
/* Find valid and maximum lowmem_reserve in the zone */ /* Find valid and maximum lowmem_reserve in the zone */
for (j = i; j < MAX_NR_ZONES; j++) { for (j = i; j < MAX_NR_ZONES; j++) {
...@@ -7267,8 +7268,8 @@ static void calculate_totalreserve_pages(void) ...@@ -7267,8 +7268,8 @@ static void calculate_totalreserve_pages(void)
/* we treat the high watermark as reserved pages. */ /* we treat the high watermark as reserved pages. */
max += high_wmark_pages(zone); max += high_wmark_pages(zone);
if (max > zone->managed_pages) if (max > managed_pages)
max = zone->managed_pages; max = managed_pages;
pgdat->totalreserve_pages += max; pgdat->totalreserve_pages += max;
......
...@@ -114,7 +114,8 @@ static unsigned long shmem_default_max_blocks(void) ...@@ -114,7 +114,8 @@ static unsigned long shmem_default_max_blocks(void)
static unsigned long shmem_default_max_inodes(void) static unsigned long shmem_default_max_inodes(void)
{ {
return min(totalram_pages - totalhigh_pages, totalram_pages / 2); unsigned long nr_pages = totalram_pages;
return min(nr_pages - totalhigh_pages, nr_pages / 2);
} }
#endif #endif
......
...@@ -1131,6 +1131,7 @@ EXPORT_SYMBOL_GPL(dccp_debug); ...@@ -1131,6 +1131,7 @@ EXPORT_SYMBOL_GPL(dccp_debug);
static int __init dccp_init(void) static int __init dccp_init(void)
{ {
unsigned long goal; unsigned long goal;
unsigned long nr_pages = totalram_pages;
int ehash_order, bhash_order, i; int ehash_order, bhash_order, i;
int rc; int rc;
...@@ -1157,10 +1158,10 @@ static int __init dccp_init(void) ...@@ -1157,10 +1158,10 @@ static int __init dccp_init(void)
* *
* The methodology is similar to that of the buffer cache. * The methodology is similar to that of the buffer cache.
*/ */
if (totalram_pages >= (128 * 1024)) if (nr_pages >= (128 * 1024))
goal = totalram_pages >> (21 - PAGE_SHIFT); goal = nr_pages >> (21 - PAGE_SHIFT);
else else
goal = totalram_pages >> (23 - PAGE_SHIFT); goal = nr_pages >> (23 - PAGE_SHIFT);
if (thash_entries) if (thash_entries)
goal = (thash_entries * goal = (thash_entries *
......
...@@ -2248,6 +2248,7 @@ static __always_inline unsigned int total_extension_size(void) ...@@ -2248,6 +2248,7 @@ static __always_inline unsigned int total_extension_size(void)
int nf_conntrack_init_start(void) int nf_conntrack_init_start(void)
{ {
unsigned long nr_pages = totalram_pages;
int max_factor = 8; int max_factor = 8;
int ret = -ENOMEM; int ret = -ENOMEM;
int i; int i;
...@@ -2267,11 +2268,11 @@ int nf_conntrack_init_start(void) ...@@ -2267,11 +2268,11 @@ int nf_conntrack_init_start(void)
* >= 4GB machines have 65536 buckets. * >= 4GB machines have 65536 buckets.
*/ */
nf_conntrack_htable_size nf_conntrack_htable_size
= (((totalram_pages << PAGE_SHIFT) / 16384) = (((nr_pages << PAGE_SHIFT) / 16384)
/ sizeof(struct hlist_head)); / sizeof(struct hlist_head));
if (totalram_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE))) if (nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
nf_conntrack_htable_size = 65536; nf_conntrack_htable_size = 65536;
else if (totalram_pages > (1024 * 1024 * 1024 / PAGE_SIZE)) else if (nr_pages > (1024 * 1024 * 1024 / PAGE_SIZE))
nf_conntrack_htable_size = 16384; nf_conntrack_htable_size = 16384;
if (nf_conntrack_htable_size < 32) if (nf_conntrack_htable_size < 32)
nf_conntrack_htable_size = 32; nf_conntrack_htable_size = 32;
......
...@@ -274,14 +274,15 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg, ...@@ -274,14 +274,15 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
struct xt_hashlimit_htable *hinfo; struct xt_hashlimit_htable *hinfo;
const struct seq_operations *ops; const struct seq_operations *ops;
unsigned int size, i; unsigned int size, i;
unsigned long nr_pages = totalram_pages;
int ret; int ret;
if (cfg->size) { if (cfg->size) {
size = cfg->size; size = cfg->size;
} else { } else {
size = (totalram_pages << PAGE_SHIFT) / 16384 / size = (nr_pages << PAGE_SHIFT) / 16384 /
sizeof(struct hlist_head); sizeof(struct hlist_head);
if (totalram_pages > 1024 * 1024 * 1024 / PAGE_SIZE) if (nr_pages > 1024 * 1024 * 1024 / PAGE_SIZE)
size = 8192; size = 8192;
if (size < 16) if (size < 16)
size = 16; size = 16;
......
...@@ -1368,6 +1368,7 @@ static __init int sctp_init(void) ...@@ -1368,6 +1368,7 @@ static __init int sctp_init(void)
int status = -EINVAL; int status = -EINVAL;
unsigned long goal; unsigned long goal;
unsigned long limit; unsigned long limit;
unsigned long nr_pages = totalram_pages;
int max_share; int max_share;
int order; int order;
int num_entries; int num_entries;
...@@ -1426,10 +1427,10 @@ static __init int sctp_init(void) ...@@ -1426,10 +1427,10 @@ static __init int sctp_init(void)
* The methodology is similar to that of the tcp hash tables. * The methodology is similar to that of the tcp hash tables.
* Though not identical. Start by getting a goal size * Though not identical. Start by getting a goal size
*/ */
if (totalram_pages >= (128 * 1024)) if (nr_pages >= (128 * 1024))
goal = totalram_pages >> (22 - PAGE_SHIFT); goal = nr_pages >> (22 - PAGE_SHIFT);
else else
goal = totalram_pages >> (24 - PAGE_SHIFT); goal = nr_pages >> (24 - PAGE_SHIFT);
/* Then compute the page order for said goal */ /* Then compute the page order for said goal */
order = get_order(goal); order = get_order(goal);
......
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