Changeset 96
- Timestamp:
- 07/03/05 04:58:03 (4 years ago)
- Files:
-
- debian/changelog (modified) (1 diff)
- src/state.c (modified) (3 diffs)
- src/state.h (modified) (1 diff)
- src/swaps.c (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
debian/changelog
r89 r96 1 1 swapspace (1.5) unstable; urgency=low 2 2 3 * Redesigned internal state machine , should improvecorner-case behaviour3 * Redesigned internal state machine; improved corner-case behaviour 4 4 * Custom signal handlers are now reusable 5 5 * Signal-triggered stats dump now goes to log if appropriate 6 6 * New -v|--verbose option logs state transitions and other debug info 7 * Updated documentation 7 8 8 -- Jeroen T. Vermeulen <jtv@sipa.or.th> Wed, 29 June 2005 14:10:00 +07009 -- Jeroen T. Vermeulen <jtv@sipa.or.th> Sat, 02 July 2005 15:30:00 +0700 9 10 10 11 swapspace (1.4) unstable; urgency=low src/state.c
r89 r96 78 78 79 79 static enum State the_state = st_hungry; 80 static bool need_diet = false; 81 82 void request_diet(void) { need_diet = true; } 80 83 81 84 static void state_to(enum State s) … … 93 96 void handle_requirements(void) 94 97 { 98 if (unlikely(need_diet)) 99 { 100 need_diet = false; 101 state_to(st_diet); 102 return; 103 } 104 95 105 const memsize_t reqbytes = memory_target(); 96 97 106 timer_tick(); 98 107 … … 102 111 * memory means we forget what state we're in and jump straight to "hungry" 103 112 * mode, allocating a new swapfile along the way. If the allocation fails, 104 * we bail out into "diet" mode .113 * we bail out into "diet" mode next time, on alloc_swapfile()'s request. 105 114 */ 106 115 if (likely(alloc_swapfile(reqbytes))) state_to(st_hungry); 107 else state_to(st_diet);108 116 } 109 117 else if (unlikely(timer_timeout())) src/state.h
r82 r96 19 19 #define SWAPSPACE_STATE_H 20 20 21 /// Perform one iteration of the allocation algorithm. Clobbers localbuf. 21 22 void handle_requirements(void); 23 24 /// Log state information. Clubbers localbuf. 22 25 void dump_state(void); 26 27 /// Request a transition to "diet" state 28 void request_diet(void); 23 29 24 30 #endif src/swaps.c
r87 r96 86 86 { 87 87 CHECK_CONFIG_ERR(min_swapsize > max_swapsize); 88 CHECK_CONFIG_ERR(min_swapsize < 10*PAGE_SIZE); 88 89 89 90 if (chdir(swappath) == -1) … … 185 186 /// Populate swapfile by writing data to it 186 187 /** 187 * @return Real size of created file 188 * @return Real size of created file, or zero on failure 188 189 */ 189 190 static memsize_t fill_swapfile(const char file[], int fd, memsize_t size) 190 191 { 191 192 memsize_t bytes = 0; 192 s tatic const ssize_t chunk = sizeof(localbuf);193 ssize_t block = chunk;193 ssize_t block = sizeof(localbuf); 194 int err = 0; 194 195 195 196 /* Zero buffer before using it to write data to swapfile. This doesn't do … … 203 204 do 204 205 { 205 block = write(fd, localbuf, chunk); 206 block = write(fd, localbuf, sizeof(localbuf)); 207 err = errno; 206 208 bytes += block; 207 } while ( block==chunk&& bytes < size);209 } while ((block > 0 || errno == EINTR) && bytes < size); 208 210 209 211 if (unlikely(block < 0)) 210 212 { 211 const int err = errno;212 213 log_perr_str(LOG_ERR, "Error writing swapfile", file); 213 214 bytes -= block; … … 215 216 { 216 217 case EFBIG: 217 // File is too large. Remember how much we were allowed to write.218 // File too big. Don't try creating files this large again. 218 219 if (likely(bytes > 0 && max_swapsize > bytes)) 219 max_swapsize = TRUNC_TO_PAGE(bytes); 220 { 221 max_swapsize = TRUNC_TO_PAGE(bytes); 222 if (verbose) 223 { 224 sprintf(localbuf, "Restricting swapfile size to %lld", bytes); 225 log_msg(LOG_INFO, localbuf); 226 } 227 } 220 228 break; 221 229 case ENOSPC: 222 // Disk full. Don't create swapfiles for a while. 223 bytes = 0; 230 case EIO: 231 // Disk full, or low-level I/O error. Go into "diet" state. 232 request_diet(); 224 233 break; 234 default: 235 log_msg(LOG_WARNING, "Unexpected error writing swap file"); 225 236 } 237 bytes = 0; 226 238 } 227 239 … … 234 246 * @param filename File to be created 235 247 * @param size Desired size in bytes (but already rounded to page size) 236 * @return Size of new swapfile, which may differ from requested size. Zero or 237 * less indicates failure, in which case the file is deleted. Negative result 238 * means any further attempts at allocating swapfile in the near future are not 239 * likely to be appreciated. 248 * @return Size of new swapfile, which may differ from requested size. Zero 249 * indicates failure, in which case the file is deleted. 240 250 */ 241 251 static memsize_t make_swapfile(const char file[], memsize_t size) … … 246 256 assert(size == TRUNC_TO_PAGE(size)); 247 257 248 memsize_t realsize;249 250 258 if (unlikely(size < min_swapsize)) return 0; 251 259 … … 259 267 return 0; 260 268 } 261 realsize = fill_swapfile(file, fd, size); 269 270 if (unlikely(!fill_swapfile(file, fd, size))) 271 { 272 size = 0; 273 unlink(file); 274 } 262 275 close(fd); 263 if (unlikely(realsize < size))264 {265 unlink(file);266 realsize = 0;267 }268 276 269 return realsize;277 return size; 270 278 } 271 279 … … 560 568 snprintf(file, sizeof(file), "%d", newswap); 561 569 swapfiles[newswap].size = make_swapfile(file, size); 562 563 if (swapfiles[newswap].size) 564 {565 if (!enable_swapfile(file))566 {567 unlink(file);568 return false;569 }570 sequence_number = inc_swapno(sequence_number); 571 }570 if (!swapfiles[newswap].size) return false; 571 572 if (!enable_swapfile(file)) 573 { 574 unlink(file); 575 request_diet(); 576 return false; 577 } 578 579 sequence_number = inc_swapno(sequence_number); 572 580 573 581 return true;
