lkml.org 
[lkml]   [1998]   [Nov]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateFri, 06 Nov 1998 19:21:37 +0100
FromBrian 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;
}
\
 
 \ /
  Last update: 2005-03-22 13:45    [from the cache]
©2003-2010