Changeset 610:db2bef9ee1c8

Show
Ignore:
Timestamp:
06/12/08 13:28:47 (7 months ago)
Author:
Maxime Petazzoni <maxime.petazzoni@…>
Branch:
default
Message:

Work on the best_overall defrag.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • nxos/base/lib/fs/fs.c

    r608 r610  
    204204  /* File name. */ 
    205205  memcpy(metadata + FS_FILENAME_OFFSET, nameconv.integers, FS_FILENAME_LENGTH); 
     206} 
     207 
     208static fs_err_t nx_fs_move_region_backwards(U32 source, U32 dest, U32 len) { 
     209  U32 data[EFC_PAGE_WORDS]; 
     210 
     211  while (len--) { 
     212    memcpy((void *) data, 
     213           (void *) &(FLASH_BASE_PTR[source*EFC_PAGE_WORDS]), 
     214           EFC_PAGE_BYTES); 
     215    if (!nx__efc_write_page(data, dest)) { 
     216      return FS_ERR_FLASH_ERROR; 
     217    } 
     218 
     219    if (!nx__efc_erase_page(source, 0)) { 
     220      return FS_ERR_FLASH_ERROR; 
     221    } 
     222 
     223    source++; 
     224    dest++; 
     225  } 
     226 
     227  return FS_ERR_NO_ERROR; 
     228} 
     229 
     230static fs_err_t nx_fs_move_region_forwards(U32 source, U32 dest, U32 len) { 
     231  U32 data[EFC_PAGE_WORDS]; 
     232 
     233  while (len--) { 
     234    memcpy((void *) data, 
     235           (void *) &(FLASH_BASE_PTR[(source+len-1)*EFC_PAGE_WORDS]), 
     236           EFC_PAGE_BYTES); 
     237    if (!nx__efc_write_page(data, dest+len-1)) { 
     238      return FS_ERR_FLASH_ERROR; 
     239    } 
     240 
     241    if (!nx__efc_erase_page(source, 0)) { 
     242      return FS_ERR_FLASH_ERROR; 
     243    } 
     244  } 
     245 
     246  return FS_ERR_NO_ERROR; 
    206247} 
    207248 
     
    219260 */ 
    220261static fs_err_t nx_fs_move_region(U32 source, U32 dest, U32 len) { 
    221   U32 data[EFC_PAGE_WORDS]; 
    222  
    223262  NX_ASSERT(source < EFC_PAGES); 
    224263  NX_ASSERT(dest < EFC_PAGES); 
    225264  NX_ASSERT(len < EFC_PAGES); 
    226265 
    227   /* TODO: allow forward moves ? */ 
    228   NX_ASSERT(dest < source || (dest > source && dest > source + len)); 
    229  
    230   while (len--) { 
    231     memcpy((void *) data, 
    232            (void *) &(FLASH_BASE_PTR[source*EFC_PAGE_WORDS]), 
    233            EFC_PAGE_BYTES); 
    234     if (!nx__efc_write_page(data, dest)) { 
    235       return FS_ERR_FLASH_ERROR; 
    236     } 
    237  
    238     if (!nx__efc_erase_page(source, 0)) { 
    239       return FS_ERR_FLASH_ERROR; 
    240     } 
    241  
    242     source++; 
    243     dest++; 
    244   } 
    245  
    246   return FS_ERR_NO_ERROR; 
     266  if (source == dest) { 
     267    return FS_ERR_NO_ERROR; 
     268  } else if (dest < source) { 
     269    return nx_fs_move_region_backwards(source, dest, len); 
     270  } else { 
     271    return nx_fs_move_region_forwards(source, dest, len); 
     272  } 
    247273} 
    248274 
     
    896922fs_err_t nx_fs_defrag_best_overall(void) { 
    897923  U32 hole_start = 0, next_hole = 0, freeblock_size = 0, next_origin = 0; 
    898   U32 files, used, free_pages, wasted; 
    899   U32 mean_space_per_file = 0; 
    900   U32 size = 0; 
    901   U32 current_location = FS_PAGE_START; 
     924  U32 files, used, free_pages, wasted, mean_space_per_file = 0; 
     925  U32 i; 
     926 
    902927  /* Get the number of files and freepages. */ 
    903928  nx_fs_get_occupation(&files, &used, &free_pages, &wasted); 
     929 
    904930  /* Nothing to do here, move on */ 
    905   if (files == 0) { 
     931  if (!files) { 
    906932    return FS_ERR_NO_ERROR; 
    907933  } 
    908934 
    909935  mean_space_per_file = free_pages / files; 
     936 
     937  /* If we have less than one page per file, it's no use doing a best 
     938   * overall defrag. Fall back to simple mode. 
     939   */ 
    910940  if (mean_space_per_file < 1) { 
    911     /*Fallback to simple defrag*/ 
    912     nx_fs_defrag_simple(); 
    913   } else { 
    914     while (current_location < FS_PAGE_END) { 
    915       if (nx_fs_page_has_magic(current_location)) { 
    916         /* calculate free space after file */ 
    917         volatile U32 *metadata = &(FLASH_BASE_PTR[current_location*EFC_PAGE_WORDS]); 
    918         hole_start = current_location + nx_fs_get_file_page_count(nx_fs_get_file_size_from_metadata(metadata)); 
    919         nx_fs_find_next_origin(hole_start, &next_origin); 
    920         freeblock_size = next_origin - hole_start; 
    921  
    922         /* frag operations*/ 
    923         if (freeblock_size > mean_space_per_file) { 
    924           size = nx_fs_get_file_size_from_metadata(metadata); 
    925           nx_fs_move_region(current_location , hole_start + mean_space_per_file, nx_fs_get_file_page_count(size)); 
    926         } else if (freeblock_size < mean_space_per_file) { 
    927           nx_fs_find_next_hole(next_origin, & next_hole); 
    928           /* TODO: fix overlapping on move */ 
    929           nx_fs_move_region(next_origin, hole_start + mean_space_per_file, next_hole -1); 
    930         } 
    931       } 
    932     } 
    933   } 
    934   return FS_ERR_NO_ERROR; 
    935 } 
    936  
     941    return nx_fs_defrag_simple(); 
     942  } 
     943 
     944  i = FS_PAGE_START; 
     945  while (i < FS_PAGE_END) { 
     946    if (nx_fs_page_has_magic(i)) { 
     947      /* Calculate free space after file */ 
     948      nx_fs_find_next_hole(i, &hole_start); 
     949      nx_fs_find_next_origin(hole_start, &next_origin); 
     950      freeblock_size = next_origin - hole_start; 
     951 
     952      /* frag operations */ 
     953      if (freeblock_size > mean_space_per_file) { 
     954        size_t size = nx_fs_get_file_size_from_metadata(metadata); 
     955        nx_fs_move_region(i, hole_start + mean_space_per_file, 
     956                          nx_fs_get_file_page_count(size)); 
     957      } else if (freeblock_size < mean_space_per_file) { 
     958        nx_fs_find_next_hole(next_origin, &next_hole); 
     959        nx_fs_move_region(next_origin, hole_start + mean_space_per_file, 
     960                          next_hole - next_origin); 
     961      } 
     962    } 
     963  } 
     964 
     965  return FS_ERR_NO_ERROR; 
     966} 
     967