in libs/settings/RAFFS.cpp [395:499]
bool FS::tryGC(int spaceNeeded, filename_filter filter) {
int spaceLeft = (intptr_t)metaPtr - (intptr_t)freeDataPtr;
#ifdef RAFFS_TEST
for (auto p = (uint32_t *)freeDataPtr; p < (uint32_t *)metaPtr; p++) {
if (*p != M1) {
LOG("value at %x = %x", OFF(p), *p);
oopsAndClear();
}
}
#endif
if (spaceLeft > spaceNeeded + 32)
return true;
int now = (int)system_timer_current_time();
if (minGCSpacing) {
gcHorizon += minGCSpacing;
int nextGC = now - minGCSpacing * 2;
// LOG("now=%d n=%d gch=%d", now, nextGC, gcHorizon);
if (nextGC > gcHorizon)
gcHorizon = nextGC;
if (gcHorizon > now)
target_panic(921);
}
LOG("running flash FS GC; needed %d, left %d", spaceNeeded, spaceLeft);
readDirPtr = NULL;
cachedMeta = NULL;
auto newBase = (uintptr_t)altBasePtr();
flushFlash();
erasePages(newBase, bytes / 2);
auto metaDst = (MetaEntry *)(newBase + bytes / 2);
auto newBaseP = (uint8_t *)newBase;
freeDataPtr = newBaseP + sizeof(FSHeader);
for (int iter = 0; iter < 2; ++iter) {
clearBlocked();
auto offset = sizeof(FSHeader);
for (auto p = metaPtr; p < endPtr; p++) {
MetaEntry m = *p;
const char *fn = fnptr(&m);
if (filter && !filter(fn))
continue;
if (checkBlocked(&m) || m.dataptr == 0)
continue;
LOGV("GC %s sz=%d @%x", fn, m.datasize(), m.dataptr);
auto fnlen = strlen(fn) + 1;
auto sz = fnlen + m.datasize();
if (iter == 0) {
auto fd = freeDataPtr;
writeData(fn, fnlen);
writeData(basePtr + m.dataptr, m.datasize());
if (freeDataPtr - fd != (int)sz)
oops();
} else {
m.fnptr = offset;
m.dataptr = offset + fnlen;
m._datasize &= ~RAFFS_FOLLOWING_MASK;
writeBytes(--metaDst, &m, sizeof(m));
}
offset += sz;
}
if (iter == 0)
finishWrite();
}
clearBlocked();
flushFlash();
LOG("GC done: %d free", (int)((intptr_t)metaDst - (intptr_t)freeDataPtr));
FSHeader hd;
hd.magic = RAFFS_MAGIC;
hd.bytes = bytes;
hd.numgc = ((FSHeader*)basePtr)->numgc + 1;
hd.reserved = M1;
writeBytes(newBaseP, &hd, sizeof(hd));
flushFlash();
basePtr = newBaseP;
endPtr = (MetaEntry *)(newBase + bytes / 2);
metaPtr = metaDst;
if ((intptr_t)metaDst - (intptr_t)freeDataPtr <= spaceNeeded + 64) {
if (filter != NULL && spaceNeeded != 0x7fff0000) {
LOG("out of space! needed=%d", spaceNeeded);
#ifdef RAFFS_TEST
oops();
#endif
}
return false;
}
return true;
}