Changeset 612:71bf10c32feb

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

Working best_overall(), one sub-case missing.

Also added nx_fs_soft_format() to wipe the flash contents softly. Some
new tests as well in tests/

Location:
nxos
Files:
5 modified

Legend:

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

    r611 r612  
    233233  while (len--) { 
    234234    memcpy((void *) data, 
    235            (void *) &(FLASH_BASE_PTR[(source+len-1)*EFC_PAGE_WORDS]), 
     235           (void *) &(FLASH_BASE_PTR[(source + len)*EFC_PAGE_WORDS]), 
    236236           EFC_PAGE_BYTES); 
    237     if (!nx__efc_write_page(data, dest+len-1)) { 
     237    if (!nx__efc_write_page(data, dest + len)) { 
    238238      return FS_ERR_FLASH_ERROR; 
    239239    } 
    240240 
    241     if (!nx__efc_erase_page(source, 0)) { 
     241    if (!nx__efc_erase_page(source + len, 0)) { 
    242242      return FS_ERR_FLASH_ERROR; 
    243243    } 
     
    685685} 
    686686 
     687fs_err_t nx_fs_soft_format(void) { 
     688  U32 nulldata[EFC_PAGE_WORDS] = {0}; 
     689  U32 i, j; 
     690 
     691  for (i=FS_PAGE_START; i<FS_PAGE_END; i++) { 
     692    if (nx_fs_page_has_magic(i)) { 
     693      volatile U32 *metadata = &(FLASH_BASE_PTR[i*EFC_PAGE_WORDS]); 
     694      size_t size, npages; 
     695 
     696      size = nx_fs_get_file_size_from_metadata(metadata); 
     697      npages = nx_fs_get_file_page_count(size); 
     698      nx_display_string("erasing "); 
     699      nx_display_uint(npages); 
     700      nx_display_end_line(); 
     701 
     702      for (j=i; j<i+npages; j++) { 
     703        nx_display_string("wiping "); 
     704        nx_display_uint(j); 
     705        nx_display_end_line(); 
     706 
     707        nx__efc_write_page(nulldata, j); 
     708      } 
     709 
     710      i += npages - 1; 
     711    } 
     712  } 
     713 
     714  return FS_ERR_NO_ERROR; 
     715} 
     716 
    687717/* Seek to the given position in the file. 
    688718 */ 
     
    920950} 
    921951 
    922 fs_err_t nx_fs_defrag_best_overall(void) { 
    923   U32 hole_start = 0, next_hole = 0, next_origin = 0; 
    924   U32 files, used, free_pages, wasted, mean_space_per_file = 0; 
    925   U32 i; 
     952static fs_err_t nx_fs_defrag_pull_file_to(U32 origin, U32 dest) { 
     953  volatile U32 *metadata; 
     954  size_t size; 
     955 
     956  metadata = &(FLASH_BASE_PTR[origin*EFC_PAGE_WORDS]); 
     957  size = nx_fs_get_file_size_from_metadata(metadata); 
     958 
     959  return nx_fs_move_region(origin, dest, 
     960    nx_fs_get_file_page_count(size)); 
     961} 
     962 
     963static U32 nx_fs_defrag_get_mean_space(void) { 
     964  U32 files, used, free_pages, wasted; 
    926965 
    927966  /* Get the number of files and freepages. */ 
    928967  nx_fs_get_occupation(&files, &used, &free_pages, &wasted); 
     968  if (!files) { 
     969    return 0; 
     970  } 
     971 
     972  return free_pages / files; 
     973} 
     974 
     975fs_err_t nx_fs_defrag_best_overall(void) { 
     976  U32 next_origin = 0, mean_space_per_file = 0, i; 
     977  fs_err_t err; 
     978 
     979  mean_space_per_file = nx_fs_defrag_get_mean_space(); 
    929980 
    930981  /* Nothing to do here, move on */ 
    931   if (!files) { 
    932     return FS_ERR_NO_ERROR; 
    933   } 
    934  
    935   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    */ 
    940   if (mean_space_per_file < 1) { 
     982  if (!mean_space_per_file) { 
    941983    return nx_fs_defrag_simple(); 
    942984  } 
     
    949991  } 
    950992 
    951   if (nx_fs_find_next_hole(next_origin, &hole_start) != FS_ERR_NO_ERROR) { 
    952     hole_start = FS_PAGE_END-1; 
    953   } 
    954  
    955   nx_fs_move_region(next_origin, i, hole_start - next_origin); 
    956  
     993  err = nx_fs_defrag_pull_file_to(next_origin, i); 
     994  if (err != FS_ERR_NO_ERROR) { 
     995    return err; 
     996  } 
     997 
     998  nx_display_uint(mean_space_per_file); 
     999  nx_display_end_line(); 
     1000 
     1001  /* Then, iterate on all files to set a proper space after them. */ 
    9571002  while (i < FS_PAGE_END) { 
    9581003    if (nx_fs_page_has_magic(i)) { 
    959       size_t hole_size; 
    960  
    961       /* Calculate the size of the hole directly after this block. */ 
    962       nx_fs_find_next_hole(i, &hole_start); 
    963       nx_fs_find_next_origin(hole_start, &next_origin); 
    964       hole_size = next_origin - hole_start; 
    965  
    966       /* When the size of the hole following this file is greater than 
    967        * what we want to put after it, move the rest of the current 
    968        * block a bit forward to make room after this file. 
     1004      volatile U32 *metadata; 
     1005      size_t size, npages, hole_size; 
     1006 
     1007      metadata = &(FLASH_BASE_PTR[i*EFC_PAGE_WORDS]); 
     1008      size = nx_fs_get_file_size_from_metadata(metadata); 
     1009      npages = nx_fs_get_file_page_count(size); 
     1010 
     1011      /* No file left after this one, job's done. */ 
     1012      if (nx_fs_find_next_origin(i + npages, &next_origin) != FS_ERR_NO_ERROR) { 
     1013        return FS_ERR_NO_ERROR; 
     1014      } 
     1015 
     1016      hole_size = next_origin - (i + npages); 
     1017 
     1018      nx_display_uint(i); 
     1019      nx_display_string(" "); 
     1020      nx_display_uint(npages); 
     1021      nx_display_end_line(); 
     1022 
     1023      i += npages + mean_space_per_file; 
     1024 
     1025      nx_display_uint(hole_size); 
     1026      nx_display_string(" > "); 
     1027      nx_display_uint(i); 
     1028      nx_display_end_line(); 
     1029 
     1030      /* First, trivial case: the hole size equals mean_space_per_file. 
     1031       * We then have nothing to do and can proceed to the next file. 
    9691032       */ 
    970       if (hole_size > mean_space_per_file) { 
    971         // TODO 
    972         size_t size = nx_fs_get_file_size_from_metadata(metadata); 
    973         nx_fs_move_region(i + size, mean_space_per_file, 
    974                           hole_start - i); 
    975       } 
    976  
    977       /* Otherwise, if the hole is smaller than what we want, move the 
    978        * following block a bit forward, when possible. 
     1033      if (hole_size == mean_space_per_file) { 
     1034        continue; 
     1035      } 
     1036 
     1037      /* Second case: the hole size is greater than what we want: pull 
     1038       * the next file at (beginning of the hole + mean_space_per_file). 
    9791039       */ 
    980       else if (hole_size < mean_space_per_file) { 
    981         if (nx_fs_find_next_hole(next_origin, &next_hole) != FS_ERR_NO_ERROR) { 
    982           /* We can't move the next block :/ */ 
    983           return FS_ERR_NO_SPACE_LEFT_ON_DEVICE; /* TODO: ?? */ 
     1040      else if (hole_size > mean_space_per_file) { 
     1041        err = nx_fs_defrag_pull_file_to(next_origin, i); 
     1042        if (err != FS_ERR_NO_ERROR) { 
     1043          return err; 
    9841044        } 
    985  
    986         nx_fs_move_region(next_origin, hole_start + mean_space_per_file, 
    987                           next_hole - next_origin); 
    988       } 
    989     } 
    990   } 
    991  
    992   return FS_ERR_NO_ERROR; 
    993 } 
    994  
     1045      } 
     1046 
     1047      /* Last case: the hole is smaller than what we need: try to move 
     1048       * what's after this file a bit forward to make room for 
     1049       * mean_space_per_file pages. 
     1050       */ 
     1051      else { 
     1052        U32 next_hole = 0, hole_end = 0; 
     1053        size_t next_hole_size; 
     1054 
     1055        nx_display_string("here\n"); 
     1056 
     1057        if (nx_fs_find_next_hole(next_origin, &next_hole) != 
     1058          FS_ERR_NO_ERROR) { 
     1059          /* The block goes all the way to the end of the flash: we 
     1060           * can't do anything anymore, just leave. 
     1061           */ 
     1062          return FS_ERR_NO_ERROR; 
     1063        } 
     1064 
     1065        if (nx_fs_find_next_origin(next_hole, &hole_end) != FS_ERR_NO_ERROR) { 
     1066          hole_end = FS_PAGE_END-1; 
     1067        } 
     1068 
     1069        next_hole_size = hole_end - next_hole; 
     1070 
     1071        nx_display_uint(next_origin); 
     1072        nx_display_string("-"); 
     1073        nx_display_uint(next_hole); 
     1074        nx_display_end_line(); 
     1075 
     1076        /* First sub-case: we have enough space after this block to 
     1077         * extend our hole up to mean_space_per_file pages. 
     1078         */ 
     1079        if (next_hole_size >= mean_space_per_file - hole_size) { 
     1080          /* Move the block [next_origin ; next_hole] 
     1081           * (mean_space_per_file - hole_size) pages to the right. 
     1082           */ 
     1083          err = nx_fs_move_region(next_origin, 
     1084            next_origin + mean_space_per_file, 
     1085            next_hole - next_origin); 
     1086          if (err != FS_ERR_NO_ERROR) { 
     1087            return err; 
     1088          } 
     1089        } 
     1090 
     1091        else { 
     1092          /* TODO: find a way to accomodate this situation. */ 
     1093          return FS_ERR_NO_SPACE_LEFT_ON_DEVICE; 
     1094        } 
     1095      } 
     1096    } 
     1097  } 
     1098 
     1099  return FS_ERR_NO_ERROR; 
     1100} 
     1101 
  • nxos/base/lib/fs/fs.h

    r608 r612  
    183183fs_err_t nx_fs_unlink(fs_fd_t fd); 
    184184 
     185/** Soft format the flash by wiping all present files. 
     186 */ 
     187fs_err_t nx_fs_soft_format(void); 
     188 
    185189/** Seek to a given position in a file. 
    186190 * 
  • nxos/systems/tests/fs.c

    r609 r612  
    88 
    99#include "base/display.h" 
     10#include "base/util.h" 
    1011#include "base/drivers/avr.h" 
    1112#include "base/drivers/_efc.h" 
     
    1617#define TEST_ZONE_START 128 
    1718#define TEST_ZONE_END 256 
     19 
     20union U32tochar { 
     21  U32 integers[8]; 
     22  char chars[32]; 
     23}; 
    1824 
    1925static bool spawn_file(char *filename, size_t bytes) { 
     
    4753 
    4854static void cleanup(void) { 
    49   U32 nulldata[EFC_PAGE_WORDS] = {0}; 
    50   int i; 
    51  
    52   for (i=TEST_ZONE_START; i<TEST_ZONE_END; i++) { 
    53     nx__efc_write_page(nulldata, i); 
    54   } 
     55  nx_fs_soft_format(); 
    5556} 
    5657 
     
    144145  nx_systick_wait_ms(500); 
    145146 
     147  destroy(); 
     148} 
     149 
     150void fs_test_defrag_best_overall(void) { 
     151  U32 data[256] = {0}; 
     152  union U32tochar nameconv; 
     153 
     154  setup(); 
     155 
     156  nx_display_string("Starting...\n"); 
     157 
     158  data[0] = (0x42 << 24); 
     159  memcpy(nameconv.chars, (void *)"test42", 6); 
     160  memcpy(data+2, nameconv.integers, 32); 
     161 
     162  spawn_file("test1", 300); 
     163  spawn_file("test2", 350); 
     164  spawn_file("test3", 10); 
     165  spawn_file("test4", 10); 
     166  remove_file("test3"); 
     167 
     168  nx_fs_dump(); 
     169  while (nx_avr_get_button() != BUTTON_OK); 
     170  nx_systick_wait_ms(500); 
     171 
     172  nx_display_clear(); 
     173  nx_display_string("Defrag: "); 
     174  nx_display_uint(nx_fs_defrag_best_overall()); 
     175  nx_display_string(" done.\n"); 
     176  while (nx_avr_get_button() != BUTTON_OK); 
     177  nx_systick_wait_ms(500); 
     178 
     179  nx_display_clear(); 
     180  nx_fs_dump(); 
     181  while (nx_avr_get_button() != BUTTON_OK); 
     182  nx_systick_wait_ms(500); 
    146183 
    147184  destroy(); 
  • nxos/systems/tests/fs.h

    r609 r612  
    1414void fs_test_defrag_empty(void); 
    1515void fs_test_defrag_simple(void); 
     16void fs_test_defrag_best_overall(void); 
    1617 
    1718#endif /* __NXOS_TESTS_FS_H__ */ 
  • nxos/systems/tests/tests.c

    r609 r612  
    867867void tests_defrag(void) { 
    868868  hello(); 
    869   fs_test_defrag_simple(); 
     869  //fs_test_defrag_simple(); 
    870870  //fs_test_defrag_empty(); 
     871  fs_test_defrag_best_overall(); 
    871872  goodbye(); 
    872873}