Changeset 96

Show
Ignore:
Timestamp:
07/03/05 04:58:03 (4 years ago)
Author:
jtv
Message:

Reworked diet mechanism; more debug output; cut deadwood from error diagnosis

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • debian/changelog

    r89 r96  
    11swapspace (1.5) unstable; urgency=low 
    22 
    3   * Redesigned internal state machine, should improve corner-case behaviour 
     3  * Redesigned internal state machine; improved corner-case behaviour 
    44  * Custom signal handlers are now reusable 
    55  * Signal-triggered stats dump now goes to log if appropriate 
    66  * New -v|--verbose option logs state transitions and other debug info 
     7  * Updated documentation 
    78 
    8  -- Jeroen T. Vermeulen <jtv@sipa.or.th>  Wed, 29 June 2005 14:10:00 +0700 
     9 -- Jeroen T. Vermeulen <jtv@sipa.or.th>  Sat, 02 July 2005 15:30:00 +0700 
    910 
    1011swapspace (1.4) unstable; urgency=low 
  • src/state.c

    r89 r96  
    7878 
    7979static enum State the_state = st_hungry; 
     80static bool need_diet = false; 
     81 
     82void request_diet(void) { need_diet = true; } 
    8083 
    8184static void state_to(enum State s) 
     
    9396void handle_requirements(void) 
    9497{ 
     98  if (unlikely(need_diet)) 
     99  { 
     100    need_diet = false; 
     101    state_to(st_diet); 
     102    return; 
     103  } 
     104 
    95105  const memsize_t reqbytes = memory_target(); 
    96  
    97106  timer_tick(); 
    98107 
     
    102111     * memory means we forget what state we're in and jump straight to "hungry" 
    103112     * 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
    105114     */ 
    106115    if (likely(alloc_swapfile(reqbytes))) state_to(st_hungry); 
    107     else state_to(st_diet); 
    108116  } 
    109117  else if (unlikely(timer_timeout())) 
  • src/state.h

    r82 r96  
    1919#define SWAPSPACE_STATE_H 
    2020 
     21/// Perform one iteration of the allocation algorithm.  Clobbers localbuf. 
    2122void handle_requirements(void); 
     23 
     24/// Log state information.  Clubbers localbuf. 
    2225void dump_state(void); 
     26 
     27/// Request a transition to "diet" state 
     28void request_diet(void); 
    2329 
    2430#endif 
  • src/swaps.c

    r87 r96  
    8686{ 
    8787  CHECK_CONFIG_ERR(min_swapsize > max_swapsize); 
     88  CHECK_CONFIG_ERR(min_swapsize < 10*PAGE_SIZE); 
    8889 
    8990  if (chdir(swappath) == -1) 
     
    185186/// Populate swapfile by writing data to it 
    186187/** 
    187  * @return Real size of created file 
     188 * @return Real size of created file, or zero on failure 
    188189 */ 
    189190static memsize_t fill_swapfile(const char file[], int fd, memsize_t size) 
    190191{ 
    191192  memsize_t bytes = 0; 
    192   static const ssize_t chunk = sizeof(localbuf); 
    193   ssize_t block = chunk
     193  ssize_t block = sizeof(localbuf); 
     194  int err = 0
    194195 
    195196  /* Zero buffer before using it to write data to swapfile.  This doesn't do 
     
    203204  do 
    204205  { 
    205     block = write(fd, localbuf, chunk); 
     206    block = write(fd, localbuf, sizeof(localbuf)); 
     207    err = errno; 
    206208    bytes += block; 
    207   } while (block==chunk && bytes < size); 
     209  } while ((block > 0 || errno == EINTR) && bytes < size); 
    208210 
    209211  if (unlikely(block < 0)) 
    210212  { 
    211     const int err = errno; 
    212213    log_perr_str(LOG_ERR, "Error writing swapfile", file); 
    213214    bytes -= block; 
     
    215216    { 
    216217    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
    218219      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      } 
    220228      break; 
    221229    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(); 
    224233      break; 
     234    default: 
     235        log_msg(LOG_WARNING, "Unexpected error writing swap file"); 
    225236    } 
     237    bytes = 0; 
    226238  } 
    227239 
     
    234246 * @param filename File to be created 
    235247 * @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. 
    240250 */ 
    241251static memsize_t make_swapfile(const char file[], memsize_t size) 
     
    246256  assert(size == TRUNC_TO_PAGE(size)); 
    247257 
    248   memsize_t realsize; 
    249  
    250258  if (unlikely(size < min_swapsize)) return 0; 
    251259 
     
    259267    return 0; 
    260268  } 
    261   realsize = fill_swapfile(file, fd, size); 
     269 
     270  if (unlikely(!fill_swapfile(file, fd, size))) 
     271  { 
     272    size = 0; 
     273    unlink(file); 
     274  } 
    262275  close(fd); 
    263   if (unlikely(realsize < size)) 
    264   { 
    265     unlink(file); 
    266     realsize = 0; 
    267   } 
    268276   
    269   return realsize; 
     277  return size; 
    270278} 
    271279 
     
    560568  snprintf(file, sizeof(file), "%d", newswap); 
    561569  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); 
    572580 
    573581  return true;