/*---------------------------------------------------------------------------*/ 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(); }
/*---------------------------------------------------------------------------*/ 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; }