Messages in this thread Patch in this message |  | | | Date | Fri, 06 Nov 1998 19:21:37 +0100 | | From | Brian Schau <> | | Subject | [PATCH] Patch to Memory Subsystem ... (Needed?) |
| |
Hello,
(This is long ...)
Find attached three files - one a patch to the memory-subsystem, one a shell-script and one a simple c-program.
Motivation. Today one of my servers had to be 'hard'-rebooted due to lack of memory. One user-space program ate all available memory - resulting in a lot of 'Unable to load interpreter' and the like. Even root couldn't get a login at the console.
Solution. Some way to specify an amount of free pages which is only accessible by root-processes so that root can get a login and kill the offending memory-eater ...
Description. The attached patch patches against a clean 2.1.126. It touches the following files:
mm/mmap.c include/linux/sysctl.h kernel/sysctl.c
It adds an entry to /proc/sys/vm/ called rootpages. Reading 'rootpages' returns the no. of pages reserved exclusively for root (defaults to 0). Writing to 'rootpages' sets the no. of pages to reserve exclusively for root. A shell script ('rootpages') is attached for your convenience:
cryo:/home/bsc # /home/bsc/rootpages Rootpages fixed at 0 pages. cryo:/home/bsc # /home/bsc/rootpages 1024 Setting new rootpages value to 1024 pages.
Test. To test, compile the third file 'eat.c':
gcc -Wall -o eat eat.c
... it compiles without warnings/errors on my 2.1.117. On tty1, run:
free -mtos 1
On tty2, run 'eat' as a normal user and with /proc/sys/vm/rootpages set to 0. 'eat' should eat all available memory (it does on my machine). Watch 'free' on tty1 report loses of memory. Press ctrl-c on tty2 thus aborting 'eat'. The amount of free memory should rise. Now set the no. of freepages to say, 1024 (4 Mb on Intel-platforms) and run 'eat' again as normal user. Watch the amount of free memory. It should drop down to ~ 4Mb - not below! You're then able to login as root and do your stuff ... ;o) (Running 'eat' as root eats all available memory - so take care!)
Notes. The patch has been developed on a 2.1.117 kernel. It runs with no errors on a 2.1.117. It patches cleanly against a 2.1.126 kernel - but I haven't tried it on a 2.1.126 kernel (due to compilation errors in the sound sub-system). But with my un-trained eye (and some help from 'diff'), it seems like there has been no fundamental changes to the files touched between .117 and .126 ... There is no check to see if the number of rootpages exceed some ??strange?? value (like 10000000). So, 'roots' beware! Conclusion. I don't know if this patch is needed in the kernel at all (haven't checked to see if somebody have done this already) - but it was a simple 1 hour hack which, if the facility existed in the kernel I use at work (2.1.107 - soon to be upgraded ;o), would have saved me from a hard-reboot, a lot of fsck'ing and loosing lots of precious time better spent at work (14 people total ...). I would like, though, that somebody validates the patch - is it safe?
Kind regards,
Brisse#include <stdlib.h> #include <stdio.h>
#define CHUNKSIZE 10240 #define STEP 1024
int main(int argc, char* argv[]) { char* ptr=NULL; int cnt=0; int c;
while (1) { cnt++; if ((ptr=(char*)calloc(CHUNKSIZE, 1))) { for (c=0; c<CHUNKSIZE; c+=STEP) *(ptr+c)=1; printf("(%06i) Ate %i bytes ...\n", cnt, CHUNKSIZE); } else printf("(%06i) Couldn't eat %i bytes ...\n", cnt, CHUNKSIZE); } exit(0); }#!/bin/sh ROOTPAGES=/proc/sys/vm/rootpages if test "$(whoami)" = "root"; then if test -f $ROOTPAGES; then if test $# -gt 0; then echo "Setting new rootpages value to $1 pages." echo $1 > $ROOTPAGES else rp="$(cat $ROOTPAGES)" echo "Rootpages fixed at $rp pages." fi else echo "Can't find $ROOTPAGES ..." fi else echo "You must be root to use this program!" fi exit 0diff -ur linux-2.1.117/include/linux/sysctl.h linux/include/linux/sysctl.h --- linux-2.1.117/include/linux/sysctl.h Fri Nov 6 16:45:44 1998 +++ linux/include/linux/sysctl.h Fri Nov 6 16:50:59 1998 @@ -99,7 +99,8 @@ VM_BUFFERMEM, /* struct: Set buffer memory thresholds */ VM_PAGECACHE, /* struct: Set cache memory thresholds */ VM_PAGERDAEMON, /* struct: Control kswapd behaviour */ -/*9*/ VM_PGT_CACHE /* struct: Set page table cache parameters */ +/*9*/ VM_PGT_CACHE, /* struct: Set page table cache parameters */ + VM_ROOTPAGES /* int: No. of free pages reserved for UID 0 */ }; diff -ur linux-2.1.117/kernel/sysctl.c linux/kernel/sysctl.c --- linux-2.1.117/kernel/sysctl.c Fri Nov 6 16:42:17 1998 +++ linux/kernel/sysctl.c Fri Nov 6 16:48:32 1998 @@ -42,6 +42,7 @@ extern int bdf_prm[], bdflush_min[], bdflush_max[]; extern char binfmt_java_interpreter[], binfmt_java_appletviewer[]; extern int sysctl_overcommit_memory; +extern int rootpages; #ifdef CONFIG_KMOD extern char modprobe_path[]; #endif @@ -211,6 +212,8 @@ &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec}, {VM_PGT_CACHE, "pagetable_cache", &pgt_cache_water, 2*sizeof(int), 0600, NULL, &proc_dointvec}, + {VM_ROOTPAGES, "rootpages", + &rootpages, sizeof(int), 0600, NULL, &proc_dointvec}, {0} }; diff -ur linux-2.1.117/mm/mmap.c linux/mm/mmap.c --- linux-2.1.117/mm/mmap.c Fri Nov 6 16:40:49 1998 +++ linux/mm/mmap.c Fri Nov 6 17:21:26 1998 @@ -47,6 +47,7 @@ kmem_cache_t *vm_area_cachep; int sysctl_overcommit_memory; +int rootpages=0; /* Check that a process has enough memory to allocate a * new virtual mapping. @@ -58,7 +59,7 @@ * fool it, but this should catch most mistakes. */ long free; - + /* Sometimes we want to use more memory than we have. */ if (sysctl_overcommit_memory) return 1; @@ -68,6 +69,7 @@ free >>= 1; free += nr_free_pages; free += nr_swap_pages; + if (current->uid) free -= rootpages; free -= num_physpages >> 4; return free > pages; } |  |