Introduced two garbage collection mode: greedy and reluctant.

The greedy GC mode attempts to erase as many sectors as possible, and
it is therefore a slow operation, since the flash driver must wait
for about a second after erasing one sector. The former behavior was
to always do a greedy GC if file reservations fails due to lack of space.

The new reluctant GC stops after erasing one sector, and therefore
we often do not have to wait if there is no file system operation
in the time while the sector is being erased. We call the garbage collector
using this mode when removing a file that is not a micro log file, since
the remove function is called recursively for micro log files that are
erased because the corresponding ordinary file is erased.

This change increases the coffee test (examples/sky/test-coffee.c) speed
from 9 to 5 seconds.
This commit is contained in:
nvt-se 2009-04-02 11:22:23 +00:00
parent b730fb329d
commit 1425537a13

View file

@ -69,6 +69,11 @@
#define INVALID_PAGE ((coffee_page_t)-1)
#define UNKNOWN_OFFSET ((cfs_offset_t)-1)
/* "Greedy" garbage collection erases as many sectors as possible. */
#define GC_GREEDY 0
/* "Reluctant" garbage collection stops after erasing one sector. */
#define GC_RELUCTANT 1
#define FD_VALID(fd) \
((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
coffee_fd_set[(fd)].flags != COFFEE_FD_FREE)
@ -258,7 +263,7 @@ get_sector_status(uint16_t sector, struct sector_stats *stats) {
}
/*---------------------------------------------------------------------------*/
static void
cfs_garbage_collect(void)
collect_garbage(int mode)
{
uint16_t sector;
struct sector_stats stats;
@ -282,6 +287,9 @@ cfs_garbage_collect(void)
if(first_page < *next_free) {
*next_free = first_page;
}
if(mode == GC_RELUCTANT) {
break;
}
}
}
@ -519,6 +527,10 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds)
}
}
if(!HDR_LOG(hdr)) {
collect_garbage(GC_RELUCTANT);
}
return 0;
}
/*---------------------------------------------------------------------------*/
@ -548,7 +560,7 @@ reserve(const char *name, coffee_page_t pages, int allow_duplicates)
if(*gc_wait) {
return NULL;
}
cfs_garbage_collect();
collect_garbage(GC_GREEDY);
page = find_contiguous_pages(pages);
if(page == INVALID_PAGE) {
watchdog_start();