From d546ca36039427d6c804bc817636939022db6d05 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Wed, 14 May 2014 12:58:37 +0200 Subject: [PATCH] UBUNTU: SAUCE: fs/stat: Reduce memory requirements for stat_open When reading /proc/stat the stat_open function currently uses 1024 + 128 * num_possible_cpus() + 2 * num_irqs This is to optimize the buffer given to show_stat to be big enough to handle the output in one go. However, the output actually grows for each online cpu. Since the number of possible CPUs is 256 we end up at least 33kB which translates into an order-4 allocation (64kB). This was seen to be a problem on some systems where reading /proc/stat would often fail due to an allocation failure. So we change the formula to only add 128 bytes per online CPU. Also, the upper bound for the buffer is set to the maximum memory kmalloc can handle. Since /proc/stat is a seq_file, not being able to fit all output in one go is not a problem (just a bit more overhead). So there is no need to set the upper bound that high. Insetead this change limits it to order-3 allocations (32kB). BugLink: http://bugs.launchpad.net/bugs/1319244 Signed-off-by: Stefan Bader --- fs/proc/stat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 1cf86c0..986ca75 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -184,7 +184,7 @@ static int show_stat(struct seq_file *p, void *v) static int stat_open(struct inode *inode, struct file *file) { - size_t size = 1024 + 128 * num_possible_cpus(); + size_t size = 1024 + 128 * num_online_cpus(); char *buf; struct seq_file *m; int res; @@ -193,8 +193,8 @@ static int stat_open(struct inode *inode, struct file *file) size += 2 * nr_irqs; /* don't ask for more than the kmalloc() max size */ - if (size > KMALLOC_MAX_SIZE) - size = KMALLOC_MAX_SIZE; + if (size > (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) + size = PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER; buf = kmalloc(size, GFP_KERNEL); if (!buf) return -ENOMEM; -- 1.7.9.5