Skip to content

Commit cafe6ab

Browse files
committed
Fixed issue with splitting metadata-pairs in full filesystem
Depending on your perspective, this may not be a necessary operation, given that a nearly-full filesystem is already prone to ENOSPC errors, especially a COW filesystem. However, splitting metadata-pairs can happen in really unfortunate situations, such as removing files. The solution here is to allow "overcompaction", that is, a compaction without bounds checking to allow splitting. This unfortunately pushes our metadata-pairs past their reasonable limit of saturation, which means writes get exponentially costly. However it does allow littlefs to continue working in extreme situations.
1 parent 29b8810 commit cafe6ab

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

lfs.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,7 @@ static int lfs_dir_compact(lfs_t *lfs,
12901290
// setup compaction
12911291
bool splitted = false;
12921292
bool exhausted = false;
1293+
bool overcompacting = false;
12931294

12941295
struct lfs_commit commit;
12951296
commit.block = dir->pair[1];
@@ -1310,9 +1311,11 @@ static int lfs_dir_compact(lfs_t *lfs,
13101311
// cleanup delete, and we cap at half a block to give room
13111312
// for metadata updates
13121313
commit.begin = 0;
1313-
commit.end = lfs_min(
1314-
lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size),
1315-
lfs->cfg->block_size - 38);
1314+
commit.end = lfs->cfg->block_size - 38;
1315+
if (!overcompacting) {
1316+
commit.end = lfs_min(commit.end,
1317+
lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size));
1318+
}
13161319

13171320
if (!splitted) {
13181321
// increment revision count
@@ -1369,8 +1372,9 @@ static int lfs_dir_compact(lfs_t *lfs,
13691372
0x003ff000, LFS_MKTAG(0, id, 0),
13701373
-LFS_MKTAG(0, begin, 0),
13711374
source, attrs);
1372-
if (err && !(splitted && err == LFS_ERR_NOSPC)) {
1373-
if (err == LFS_ERR_NOSPC) {
1375+
if (err && !(splitted && !overcompacting &&
1376+
err == LFS_ERR_NOSPC)) {
1377+
if (!overcompacting && err == LFS_ERR_NOSPC) {
13741378
goto split;
13751379
} else if (err == LFS_ERR_CORRUPT) {
13761380
goto relocate;
@@ -1457,6 +1461,11 @@ static int lfs_dir_compact(lfs_t *lfs,
14571461
lfs_mdir_t tail;
14581462
err = lfs_dir_alloc(lfs, &tail);
14591463
if (err) {
1464+
if (err == LFS_ERR_NOSPC) {
1465+
// No space to expand? Try overcompacting
1466+
overcompacting = true;
1467+
goto commit;
1468+
}
14601469
return err;
14611470
}
14621471

0 commit comments

Comments
 (0)