Changeset 81
- Timestamp:
- 06/16/05 21:29:30 (4 years ago)
- Files:
-
- Makefile (modified) (2 diffs)
- TODO (modified) (1 diff)
- debian/changelog (modified) (1 diff)
- src/Makefile (modified) (2 diffs)
- src/main.c (modified) (1 diff)
- src/memory.c (modified) (6 diffs)
- src/opts.c (modified) (4 diffs)
- src/swaps.c (modified) (6 diffs)
- src/swaps.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
Makefile
r73 r81 4 4 SWAPDIR=$(SWAPPARENT)/swapspace 5 5 6 all: 7 +$(MAKE) -C src 6 all: VERSION DATE 7 +$(MAKE) -C src VERSION="`cat VERSION`" DATE="`cat DATE`" 8 8 9 9 clean: … … 25 25 $(RM) /usr/share/man/man8/swapspace.8 26 26 27 # Derive version number and last change date from Debian changelog 28 VERSION: debian/changelog 29 head -n 1 $< | sed -e 's/^.*(\([0-9][^)]*\)).*/\1/' >$@ 30 31 DATE: debian/changelog 32 grep '^ -- ' $< | sed -e 's/^.*> \([MTWFS][a-z]\{2\}, \{1,2\}[[:digit:]]\{1,2\} [JFBAMSOND][a-z]* 2[[:digit:]]\{3\}\) .*/\1/' | head -n 1 >$@ 33 27 34 .PHONY: all clean install uninstall 28 35 TODO
r80 r81 2 2 - Print version number with help output; add --version option 3 3 - Ensure minimal repetition of error/warning messages 4 5 6 Bull/Bear Mode7 8 Currently, the program goes into bear mode if swapfile allocation fails and into9 bull mode when swapfiles are allocated. In the steady state we're somewhere10 inbetween. Maybe this isn't the best way to do it.11 12 What if we inhibited deallocations until the percentage of available space13 remained above the deallocation limit for an entire cooldown period? Currently14 deallocation seems to be too aggressive.15 debian/changelog
r77 r81 1 swapspace (1.4) unstable; urgency=low 2 3 * Supports Linux 2.4's /proc/meminfo format; no longer requires 2.6 kernel 4 * Only deallocates if enough memory stays free for entire cooldown period 5 * Failure to parse /proc/meminfo is now fatal 6 * New --version option 7 * Additional sanity checking of memory statistics 8 9 -- Jeroen T. Vermeulen <jtv@sipa.or.th> Thu, 16 June 2005 19:30:00 +0700 10 1 11 swapspace (1.3) unstable; urgency=low 2 12 src/Makefile
r76 r81 1 1 #! /usr/bin/make 2 2 3 # CC=gcc-3.43 # Assumes we're using gcc 4 4 CFLAGS=--std=c99 -Wall --pedantic -Wshadow -O2 -g 5 CPPFLAGS=-DSUPPORT_LARGE_FILES 5 CPPFLAGS=-DSUPPORT_LARGE_FILES -DVERSION="\"$(VERSION)\"" -DDATE="\"$(DATE)\"" 6 6 RM=rm -f 7 7 … … 22 22 memory.o : memory.c config.h env.h log.h main.h memory.h support.h 23 23 24 opts.o : opts.c opts.h main.h 24 opts.o : opts.c opts.h main.h ../VERSION ../DATE 25 25 26 26 support.o : support.c config.h env.h support.h src/main.c
r76 r81 205 205 if (req > 0) alloc_swapfile(req); 206 206 else if (req < 0) free_swapfile(-req); 207 else steady_state(); 207 208 } 208 209 src/memory.c
r78 r81 97 97 /** Attempt to read a line from /proc/meminfo into result. If an error occurs, 98 98 * result will hold errno (which may be zero, e.g. in the case of a parse error) 99 * and a generic error string. If end-of-file has been reached , result will100 * contain zero and the empty string.99 * and a generic error string. If end-of-file has been reached or a meaningless 100 * line has been read, result will contain zero and the empty string. 101 101 * 102 102 * @return success (not EOF and not error) … … 115 115 116 116 char fact[20]; 117 const int x = sscanf(localbuf,"%s %lld %s",result->entry,&result->value,fact); 117 const int x = sscanf(localbuf, 118 "%s %lld %19s", 119 result->entry, 120 &result->value, 121 fact); 122 118 123 if (unlikely(x < 3)) 119 124 { 120 125 result->value = 0; 126 127 // In Linux 2.4, /proc/meminfo starts with a header line with leading 128 // whitespace. We accept that as a special case. 129 if (likely(isspace(localbuf[0]))) 130 { 131 result->entry[0] = '\0'; 132 return true; 133 } 134 135 // All other parse failures are fatal. 121 136 snprintf(result->entry, 122 sizeof(result->entry), 123 "Parse error in /proc/meminfo: '%150s'", 124 localbuf); 125 return false; 126 } 127 137 sizeof(result->entry), 138 "Parse error in /proc/meminfo: '%150s'", 139 localbuf); 140 141 return false; 142 } 143 144 // Another special case for Linux 2.4: two extra lines summarize the various 145 // pools of physical memory and swap space. We'd fail to parse these lines 146 // (which we're not interested in anyway) because there's a number where we 147 // expect a scale factor. Detect this and skip those lines. 148 if (isdigit(fact[0])) 149 { 150 result->entry[0] = '\0'; 151 result->value = 0; 152 return true; 153 } 154 155 // Parse scale factor at end of line. I've never seen it be anything other 156 // than "kB", but who knows what can happen... 128 157 memsize_t scale = 0; 129 158 const size_t factlen = strlen(fact); … … 214 243 215 244 216 static bool read_proc_meminfo(struct memstate * result)245 static bool read_proc_meminfo(struct memstate *s) 217 246 { 218 247 FILE *fp = fopen("/proc/meminfo", "r"); … … 224 253 225 254 struct meminfo_item inf; 226 while (read_meminfo_item(fp, &inf)) imbibe_meminfo_entry(&inf, result);255 while (read_meminfo_item(fp, &inf)) imbibe_meminfo_entry(&inf, s); 227 256 fclose(fp); 228 if (unlikely(inf.entry[0])) log_perrno(LOG_ERR, inf.entry, inf.value); 229 257 if (unlikely(inf.entry[0])) 258 { 259 log_perrno(LOG_ERR, inf.entry, inf.value); 260 return false; 261 } 262 263 if (unlikely(!s->MemTotal)) 264 { 265 log_msg(LOG_ERR, 266 "No memory detected! Perhaps /proc/meminfo is in an unexpected format"); 267 return false; 268 } 269 if (unlikely(s->MemTotal < s->MemFree+s->Buffers+s->Cached+s->SwapCached)) 270 { 271 log_msg(LOG_ERR, "Memory statistics read from /proc/meminfo don't add up"); 272 return false; 273 } 274 230 275 return true; 231 276 } … … 235 280 { 236 281 const memsize_t init_req = memory_target(); 282 if (init_req == MEMSIZE_ERROR) return false; 237 283 if (init_req && !quiet) 238 284 { … … 241 287 else if (init_req < 0) printf("%lld bytes to spare\n", -init_req); 242 288 } 243 return init_req != MEMSIZE_ERROR;289 return true; 244 290 } 245 291 src/opts.c
r77 r81 41 41 42 42 static char *set_help(long long dummy); 43 static char *set_version(long long dummy); 43 44 44 45 … … 88 89 "Create swapfiles in secure directory s" }, 89 90 { "upper_freelimit", 'u', at_num, 0, 100, set_upper_freelimit, 90 "Reduce swapspace if more than n% is free" } 91 "Reduce swapspace if more than n% is free" }, 92 { "version", 'V', at_none, 0, 0, set_version, 93 "Print version number and exit" } 91 94 }; 92 95 … … 149 152 return result; 150 153 } 154 155 const char copyright[] = "\n" 156 "Copyright (c) 2004-2005 Software Industry Promotion Agency of Thailand\n" 157 "Written by Jeroen T. Vermeulen <jtv@sipa.or.th>\n" 158 "This program is free software, and is available for use under the GNU\n" 159 "General Public License (GPL).\n"; 151 160 152 161 static char *set_help(long long dummy) … … 183 192 } 184 193 185 puts("\n\n" 186 "Copyright (c) 2004-2005 Software Industry Promotion Agency of Thailand\n" 187 "Written by Jeroen T. Vermeulen <jtv@sipa.or.th>\n" 188 "This program is free software, and is available for use under the GNU\n" 189 "General Public License (GPL).\n" 190 ); 194 puts(copyright); 195 exit(EXIT_SUCCESS); 196 } 197 198 199 char *set_version(long long dummy) 200 { 201 puts("swapspace " VERSION ", " DATE); 202 puts(copyright); 191 203 exit(EXIT_SUCCESS); 192 204 } src/swaps.c
r79 r81 72 72 /// Minimum cooldown time between Bull/Bear policy reversals 73 73 /** The program's disposition to allocate or deallocate wavers between two 74 * extremes: Bull and Bear, though normal operation will take place in the 75 * grey area between them. This is done to avoid unstable behaviour where swap 74 * extremes: Bull and Bear. This is done to avoid unstable behaviour where swap 76 75 * files are repeatedly created, deleted again, and then re-allocated. 77 76 * … … 80 79 * left unused. While this phase lasts, the program will assume that any drop 81 80 * in swap space usage may be temporary and the allocated swap files may be 82 * needed again soon. 81 * needed again soon. Bull phases can end only if the disk fills up with swap 82 * files, or the amount of free memory remains above the deallocation threshold 83 * for an entire cooldown period. 83 84 * 84 85 * On the other extreme, Bear phases occur when swapfile allocation fails due … … 86 87 * space is not likely to satisfy whatever software is using up so much memory 87 88 * or disk space. In a Bear phase we assume that the spike in memory usage is a 88 * fluke: no more allocations are attempted-- probably starving the offending89 * fluke: no more allocations are attempted--hopefully starving the offending 89 90 * software--and unneeded swap space is freed up more aggressively. 90 91 * 91 * The program's steady state lies between these phases. Any attempt to 92 * allocate a swapfile marks the beginning of either a Bull phase or a Bear 93 * phase; the allocation attempt will be given the configured amount of 94 * "cooldown time" before the program is allowed to go into the opposite phase. 95 * Deallocation does not trigger a transition, though may conceivably provide 92 * Deallocation does not trigger a transition, though it may conceivably provide 96 93 * useful information about optimal phase duration. 97 94 */ … … 158 155 { 159 156 return (clock < cooldown_start + cooldown_time); 157 } 158 159 160 void steady_state(void) 161 { 162 if (!cooldown_bear) cooldown_start = clock; 160 163 } 161 164 … … 248 251 static const ssize_t chunk = sizeof(localbuf); 249 252 ssize_t block = chunk; 253 250 254 /* Zero buffer before using it to write data to swapfile. This doesn't do 251 255 * much for security (if an attacker can get to your swapfiles you don't have … … 316 320 size = MIN(size, max_swapsize); 317 321 318 // TODO: Think about reuse of existing swapfiles319 322 unlink(file); 320 323 const int fd=open(file, O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, S_IRUSR|S_IWUSR); src/swaps.h
r76 r81 63 63 void free_swapfile(memsize_t maxsize); 64 64 65 /// Mark an iteration where we don't want to allocate/deallocate swap files 66 void steady_state(void); 67 65 68 char *set_min_swapsize(long long size); 66 69 char *set_max_swapsize(long long size);
