Tweaked lfsr_mdir_commit_ a bit

Mostly just shuffled code around. I was trying to clean this function up
a bit but didn't really get anywhere.

I did try deduplicating the two lfsr_mdir_commit__ calls, but it only
saves ~8 bytes of code, so I didn't think it was worth making this
function inconsistent with other compaction patterns in the codebase:

           code          stack
  before: 36476           2672
  dedup:  36456 (-0.1%)   2672 (+0.0%)
  after:  36464 (-0.0%)   2672 (+0.0%)

---

One, uh, dangerously subtle change here is we no longer consider
corruption errors as not "overcompactable". I tried digging through the
commit messages but couldn't find the motivation for this extra check.

It may seem wrong, but trying to overcompact even on corrupt errors
matches our current "we may try a bad block again later" strategy.
Alternative strategies (which are probably more correct) are a TODO
item.
This commit is contained in:
Christopher Haster
2024-08-15 13:48:07 -05:00
parent 91809ad884
commit 0dca8327a8
+38 -35
View File
@@ -5268,7 +5268,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
}
}
compact_relocate:;
relocate:;
// allocate a new rbyd
err = lfsr_rbyd_alloc(lfs, &rbyd__);
if (err) {
@@ -5281,7 +5281,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
if (err == LFS_ERR_CORRUPT) {
goto compact_relocate;
goto relocate;
}
return err;
}
@@ -5294,7 +5294,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
if (err == LFS_ERR_CORRUPT) {
goto compact_relocate;
goto relocate;
}
return err;
}
@@ -8066,7 +8066,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir,
mid, attrs, attr_count);
if (err) {
if (err == LFS_ERR_RANGE || err == LFS_ERR_CORRUPT) {
goto compact;
goto swap;
}
return err;
}
@@ -8075,8 +8075,10 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir,
*mdir = mdir_;
return 0;
compact:;
// can't commit, try to compact
swap:;
// can't commit, can we compact?
bool relocated = false;
bool overcompacted = false;
// check if we're within our compaction threshold
lfs_ssize_t estimate = lfsr_mdir_estimate__(lfs, mdir, start_rid, end_rid,
@@ -8092,45 +8094,46 @@ compact:;
// swap blocks, increment revision count
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, false);
if (err && err != LFS_ERR_NOSPC
&& err != LFS_ERR_CORRUPT) {
if (err) {
if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {
goto relocate;
}
return err;
}
bool overcompactable = (err != LFS_ERR_CORRUPT);
bool all = true;
goto compact;
relocate:;
// relocate? bad prog? ok, try allocating a new mdir
if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {
err = lfsr_mdir_alloc__(lfs, &mdir_, mdir->mid, all);
if (err && !(err == LFS_ERR_NOSPC && overcompactable)) {
return err;
}
all = false;
// needs relocation? bad prog? ok, try allocating a new mdir
err = lfsr_mdir_alloc__(lfs, &mdir_, mdir->mid, !relocated);
if (err && !(err == LFS_ERR_NOSPC && !overcompacted)) {
return err;
}
relocated = true;
// no more blocks? wear-leveling falls apart here, but we can try
// without relocating
if (err == LFS_ERR_NOSPC) {
LFS_WARN("Overcompacting mdir %"PRId32" "
"0x{%"PRIx32",%"PRIx32"}",
mdir->mid >> lfs->mdir_bits,
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1]);
overcompactable = false;
// no more blocks? wear-leveling falls apart here, but we can try
// without relocating
if (err == LFS_ERR_NOSPC) {
LFS_WARN("Overcompacting mdir %"PRId32" "
"0x{%"PRIx32",%"PRIx32"}",
mdir->mid >> lfs->mdir_bits,
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1]);
overcompacted = true;
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, true);
if (err) {
// bad prog? can't do much here, mdir stuck
if (err == LFS_ERR_CORRUPT) {
LFS_DEBUG("Stuck mdir 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.blocks[0],
mdir->rbyd.blocks[1]);
return LFS_ERR_NOSPC;
}
return err;
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, true);
if (err) {
// bad prog? can't do much here, mdir stuck
if (err == LFS_ERR_CORRUPT) {
LFS_DEBUG("Stuck mdir 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.blocks[0],
mdir->rbyd.blocks[1]);
return LFS_ERR_NOSPC;
}
return err;
}
}
compact:;
// compact our mdir
err = lfsr_mdir_compact__(lfs, &mdir_, mdir, start_rid, end_rid);
if (err) {