/*---------------------------------------------------------------------------*/
static void
collect_garbage(int mode)
{
    uint16_t sector;
    struct sector_status stats;
    coffee_page_t first_page, isolation_count;

    COFFEE_WATCHDOG_STOP();

    PRINTF("Coffee: Running the file system garbage collector in %s mode\n",
           mode == GC_RELUCTANT ? "reluctant" : "greedy");
    /*
     * The garbage collector erases as many sectors as possible. A sector is
     * erasable if there are only free or obsolete pages in it.
     */
    for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
        isolation_count = get_sector_status(sector, &stats);
        PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n",
               sector, (unsigned)stats.active,
               (unsigned)stats.obsolete, (unsigned)stats.free);

        if(stats.active > 0) {
            continue;
        }

        if((mode == GC_RELUCTANT && stats.free == 0) ||
                (mode == GC_GREEDY && stats.obsolete > 0)) {
            first_page = sector * COFFEE_PAGES_PER_SECTOR;
            if(first_page < *next_free) {
                *next_free = first_page;
            }

            if(isolation_count > 0) {
                isolate_pages(first_page + COFFEE_PAGES_PER_SECTOR, isolation_count);
            }

            COFFEE_ERASE(sector);
            PRINTF("Coffee: Erased sector %d!\n", sector);

            if(mode == GC_RELUCTANT && isolation_count > 0) {
                break;
            }
        }
    }

    COFFEE_WATCHDOG_START();
}
Exemplo n.º 2
0
/*---------------------------------------------------------------------------*/
static int
cfs_garbage_collect(void)
{
  uint16_t sector;
  uint16_t active_pages, free_pages, obsolete_pages;
  uint8_t sectors_in_row, longest_row;
  
  watchdog_stop();
  
  PRINTF("Coffee: Running the file system garbage collector...\n");
  
  sectors_in_row = longest_row = 0;
  /* 
   * The garbage collector erases as many sectors as possible. A sector is
   * erasable if there are only free or obsolete pages in it.
   */
  for(sector = 0; sector < COFFEE_SIZE / COFFEE_SECTOR_SIZE; sector++) {
    get_sector_status(sector, &active_pages, &free_pages, &obsolete_pages);
    PRINTF("Coffee: Sector %u has %u active, %u free, and %u obsolete pages.\n",
	sector, active_pages, free_pages, obsolete_pages);
    if(active_pages == 0 && obsolete_pages > 0) {
      COFFEE_ERASE(sector);
      PRINTF("Coffee: Erased sector %d!\n", sector);
      ++sectors_in_row;
      if(sectors_in_row > longest_row) {
	longest_row = sectors_in_row;
      }
    } else {
      sectors_in_row = 0;
    }
  }

  watchdog_start();
  
  return longest_row * COFFEE_PAGES_PER_SECTOR;
}