Re: swap space: an idea. Please comment.

Marc MERLIN (marc_merlin@magic.metawire.com)
3 Mar 1997 22:01:33 GMT


On Sun, 2 Mar 1997 21:12:31 +0100, Herve R.-P. <regad@micronet.fr> wrote:
>Digging further more, the dream would be to have *all* of the unused
>local disk space available for swap. Then, no need to do anything
>manually, except, maybe, adding a disk :-)

I already have something similar on my machine:
I used swapd from Nick Holloway <Nick.Holloway@alfie.demon.co.uk>

It's rather old (at least 2 years) and basically it watches /proc/meminfo
every x seconds and creates swap files on the fly. It's not perfect, but it
works :-) (On my system, I have it look every second).

I submitted a patch to Nick for the new /proc/meminfo setup, but I don't
think he ever made a new release.

Swapd 1.3 should be available easily. ftpsearch tells me:
tsx-11.mit.edu /pub/linux/sources/sbin/swapd-1.3.tar.gz

For the patch, since I can't garantee that my ftp server will be up forever,
and since it's not too big, here it is:
(The patch is not great either, but it also works :-D)

diff -urN swapd-1.3/Makefile swapd-1.4/Makefile
--- swapd-1.3/Makefile Sun Jul 9 01:42:11 1995
+++ swapd-1.4/Makefile Sat Apr 27 11:52:55 1996
@@ -7,12 +7,11 @@
# Compiled defaults to override swapd.h -- add to CFLAGS to taste
# -DTMPDIR=\"/var/tmp\" Directory to create swap files in
# -DPRIORITY=-4 Nice level for daemon to run at
-# -DINTERVAL=30 Interval to check free VM
+# -DINTERVAL=1 Interval to check free VM
# -DNUMCHUNKS=8 Maximum number of swap files
-# -DCHUNKSZ=2*1024*1024 Size of each swap file
-# -DLOWER=CHUNKSZ/2 Lower limit for VM
-# -DUPPER=CHUNKSZ Upper limit for VM
-# -DBROKEN_SYSLOG If your syslog ignores setlogmask()
+# -DCHUNKSZ=8*1048576 Size of each swap file
+# -DLOWER=10*1048576 Lower limit for VM
+# -DUPPER=18*1048576 Upper limit for VM

CFLAGS = -O2 -Wall
LDFLAGS = -s
diff -urN swapd-1.3/swapd.c swapd-1.4/swapd.c
--- swapd-1.3/swapd.c Sun May 21 22:33:27 1995
+++ swapd-1.4/swapd.c Sat Apr 27 11:09:22 1996
@@ -4,7 +4,13 @@
* swapd - dynamically add and remove swap
*
* Nick Holloway <Nick.Holloway@alfie.demon.co.uk>
- */
+ *
+ * Patched so that it works on the newer versions of the kernel (28/03/96)
+ * I messed with syslog to make it work as initially intended (I think)
+ * and I added a debug toggle when SIGUSR1 is received
+ *
+ * Marc Merlin <Marc.Merlin@efrei.fr> [MM]
+ */

# include <stdio.h>
# include <syslog.h>
@@ -31,9 +37,7 @@
char *tmpdir = TMPDIR; /* -d */

/*
- * The intention was that `debug' would control the amount of logging that
- * occurred. However, setlogmask is currently broke (fixed in future
- * release of libc). So, if you want the extra logging, define DEBUG.
+ * Set debug if you want memory info (can be toggled with SIGUSR1) [MM]
*/
int debug = 0; /* -D */

@@ -77,6 +81,15 @@
}

/*
+ * On SIGUSR1 toggle debug
+ */
+void toggledebug ( int dummy )
+{
+ debug=1-debug;
+}
+
+
+/*
* On signals, tidy up, and vanish.
*/
void sighandler ( int signal )
@@ -245,7 +258,6 @@
}

openlog ( "swapd", LOG_DAEMON | LOG_CONS | (debug ? LOG_PERROR : 0), 0 );
- setlogmask ( debug ? LOG_UPTO ( LOG_DEBUG ) : LOG_UPTO ( LOG_NOTICE ) );

/* allocate memory needed at start, rather than leaving to later */
swapfile = malloc ( sizeof(char*) * numchunks );
@@ -269,11 +281,14 @@
(void) sigaction ( SIGQUIT, &act, (struct sigaction*)NULL );
(void) sigaction ( SIGTERM, &act, (struct sigaction*)NULL );

+/* this should be handy [MM] */
+ act.sa_handler = toggledebug;
+ (void) sigaction ( SIGUSR1, &act, (struct sigaction*)NULL );
+
for ( ; ; ) {
swap = getswap();
-#ifndef BROKEN_SYSLOG
- syslog ( LOG_DEBUG, "%dk available swap", swap / 1024 );
-#endif
+ if ( debug )
+ syslog ( LOG_DEBUG, "%dk available swap", swap / 1024 );
if ( swap < lower && chunks < numchunks ) {
if ( addswap ( chunks ) )
chunks++;
@@ -292,13 +307,34 @@
* Mem: 7417856 5074944 2342912 880640 3563520
* Swap: 8441856 0 8441856
*/
+
+/*
+ * After Linux 1.3.5x, it looks more like this [MM]:
+ * total: used: free: shared: buffers: cached:
+ * Mem: 32038912 27721728 4317184 21188608 630784 7942144
+ * Swap: 2093056 1167360 925696
+ * MemTotal: 31288 kB
+ * MemFree: 4216 kB
+ * MemShared: 20692 kB
+ * Buffers: 616 kB
+ * Cached: 7756 kB
+ * SwapTotal: 2044 kB
+ * SwapFree: 904 kB
+ *
+ * According to the kernel source, the two first lines will eventually
+ * disappear, but since the procps-0.99a still uses them, I guess that I can
+ * also, at least for now. [MM]
+ * The following is generic, so it should work on all versions of the kernel
+ */
+
long getswap ()
{
static int fd = -1; /* fd to read meminfo from */
- char buffer [ 512 ]; /* enough to slurp meminfo in */
+ char buffer [ 1024 ]; /* increase the buffer size, just in case [MM] */
char *cp;
- long freemem, cache, freeswap;
+ long freemem, buf, cache=0, freeswap;
int n;
+ char newproc=0;

if ( fd < 0 ) {
fd = open ( "/proc/meminfo", O_RDONLY );
@@ -318,13 +354,31 @@
}
buffer[n] = '\0'; /* null terminate */
cp = buffer;
+
+ if (strstr(cp,"cached:")!=NULL)
+ {
+ newproc=1; /* Check if we have a newer kernel */
+ }
+
while ( *cp != '\n' ) /* skip to memory usage line */
cp++;
while ( *cp != ' ' ) /* skip past 'Mem:' */
cp++;
- if ( 2 != sscanf ( cp, "%*d %*d %ld %*d %ld", &freemem, &cache ) ) {
- syslog ( LOG_ERR, "sscanf failed on memory info" );
- exit ( 1 );
+ if (newproc)
+ {
+ if (3 != sscanf (cp, "%*d %*d %ld %*d %ld %ld", &freemem, &buf, &cache))
+ {
+ syslog ( LOG_ERR, "sscanf failed on memory info" );
+ exit ( 1 );
+ }
+ }
+ else
+ {
+ if ( 2 != sscanf ( cp, "%*d %*d %ld %*d %ld", &freemem, &buf ) )
+ {
+ syslog ( LOG_ERR, "sscanf failed on memory info" );
+ exit ( 1 );
+ }
}
while ( *cp != '\n' ) /* skip to swap usage line */
cp++;
@@ -335,7 +389,7 @@
exit ( 1 );
}

- return ( freemem + cache + freeswap );
+ return ( freemem + cache + buf + freeswap );
}

/*
@@ -356,7 +410,7 @@
exit ( 1 );
}
if ( fsstat.f_bsize * fsstat.f_bavail < chunksz ) {
- syslog ( LOG_NOTICE, "no space for swapfile on \"%s\"", tmpdir );
+ syslog ( LOG_ERR, "no space for swapfile on \"%s\"", tmpdir );
return 0;
}

@@ -380,7 +434,7 @@
/* stick the pages for swapping onto disk */
while ( pages-- > 0 ) {
if ( write ( fd, page, sizeof(page) ) != sizeof(page) ) {
- syslog ( LOG_NOTICE, "write failed on \"%s\": %m", swapfile[i] );
+ syslog ( LOG_ERR, "write failed on \"%s\": %m", swapfile[i] );
(void) close ( fd );
(void) unlink ( swapfile[i] );
return 0;
diff -urN swapd-1.3/swapd.h swapd-1.4/swapd.h
--- swapd-1.3/swapd.h Sun Jul 9 16:06:48 1995
+++ swapd-1.4/swapd.h Sat Apr 27 11:17:57 1996
@@ -3,7 +3,7 @@
*
*/

-# define VERSION "1.3"
+# define VERSION "1.4"

/* The directory in which the extra swap files will be created */
# ifndef TMPDIR
@@ -22,7 +22,7 @@

/* The interval (in seconds) between checks */
# ifndef INTERVAL
- # define INTERVAL 15
+ # define INTERVAL 1
# endif

/* The maximum number of extra swap files that will be created */
@@ -32,20 +32,15 @@

/* The size of each extra swapfile */
# ifndef CHUNKSZ
- # define CHUNKSZ 4 * 1024 * 1024
+ # define CHUNKSZ 8 * 1048576
# endif

/* If the free swap falls below this level, an extra swap file is added */
# ifndef LOWER
- # define LOWER CHUNKSZ / 2
+ # define LOWER 10 * 1048576
# endif

/* An extra swap file is only removed if it will leave at least much free */
# ifndef UPPER
- # define UPPER CHUNKSZ
-# endif
-
-/* I have no idea if my syslog is broken but I don't want all that logging */
-# ifndef BROKEN_SYSLOG
- # define BROKEN_SYSLOG
+ # define UPPER 18 * 1048576
# endif

Enjoy,
Marc

-- 
Home page: http://www.efrei.fr/~merlin/ (browser friendly)