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:
@@ -5268,7 +5268,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compact_relocate:;
|
relocate:;
|
||||||
// allocate a new rbyd
|
// allocate a new rbyd
|
||||||
err = lfsr_rbyd_alloc(lfs, &rbyd__);
|
err = lfsr_rbyd_alloc(lfs, &rbyd__);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -5281,7 +5281,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
// bad prog? try another block
|
// bad prog? try another block
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
goto compact_relocate;
|
goto relocate;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -5294,7 +5294,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
// bad prog? try another block
|
// bad prog? try another block
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
goto compact_relocate;
|
goto relocate;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -8066,7 +8066,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
mid, attrs, attr_count);
|
mid, attrs, attr_count);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_RANGE || err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_RANGE || err == LFS_ERR_CORRUPT) {
|
||||||
goto compact;
|
goto swap;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -8075,8 +8075,10 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
*mdir = mdir_;
|
*mdir = mdir_;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
compact:;
|
swap:;
|
||||||
// can't commit, try to compact
|
// can't commit, can we compact?
|
||||||
|
bool relocated = false;
|
||||||
|
bool overcompacted = false;
|
||||||
|
|
||||||
// check if we're within our compaction threshold
|
// check if we're within our compaction threshold
|
||||||
lfs_ssize_t estimate = lfsr_mdir_estimate__(lfs, mdir, start_rid, end_rid,
|
lfs_ssize_t estimate = lfsr_mdir_estimate__(lfs, mdir, start_rid, end_rid,
|
||||||
@@ -8092,45 +8094,46 @@ compact:;
|
|||||||
|
|
||||||
// swap blocks, increment revision count
|
// swap blocks, increment revision count
|
||||||
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, false);
|
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, false);
|
||||||
if (err && err != LFS_ERR_NOSPC
|
if (err) {
|
||||||
&& err != LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {
|
||||||
|
goto relocate;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overcompactable = (err != LFS_ERR_CORRUPT);
|
goto compact;
|
||||||
bool all = true;
|
|
||||||
relocate:;
|
relocate:;
|
||||||
// relocate? bad prog? ok, try allocating a new mdir
|
// needs relocation? 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, !relocated);
|
||||||
err = lfsr_mdir_alloc__(lfs, &mdir_, mdir->mid, all);
|
if (err && !(err == LFS_ERR_NOSPC && !overcompacted)) {
|
||||||
if (err && !(err == LFS_ERR_NOSPC && overcompactable)) {
|
return err;
|
||||||
return err;
|
}
|
||||||
}
|
relocated = true;
|
||||||
all = false;
|
|
||||||
|
|
||||||
// no more blocks? wear-leveling falls apart here, but we can try
|
// no more blocks? wear-leveling falls apart here, but we can try
|
||||||
// without relocating
|
// without relocating
|
||||||
if (err == LFS_ERR_NOSPC) {
|
if (err == LFS_ERR_NOSPC) {
|
||||||
LFS_WARN("Overcompacting mdir %"PRId32" "
|
LFS_WARN("Overcompacting mdir %"PRId32" "
|
||||||
"0x{%"PRIx32",%"PRIx32"}",
|
"0x{%"PRIx32",%"PRIx32"}",
|
||||||
mdir->mid >> lfs->mdir_bits,
|
mdir->mid >> lfs->mdir_bits,
|
||||||
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1]);
|
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1]);
|
||||||
overcompactable = false;
|
overcompacted = true;
|
||||||
|
|
||||||
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, true);
|
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, true);
|
||||||
if (err) {
|
if (err) {
|
||||||
// bad prog? can't do much here, mdir stuck
|
// bad prog? can't do much here, mdir stuck
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
LFS_DEBUG("Stuck mdir 0x{%"PRIx32",%"PRIx32"}",
|
LFS_DEBUG("Stuck mdir 0x{%"PRIx32",%"PRIx32"}",
|
||||||
mdir->rbyd.blocks[0],
|
mdir->rbyd.blocks[0],
|
||||||
mdir->rbyd.blocks[1]);
|
mdir->rbyd.blocks[1]);
|
||||||
return LFS_ERR_NOSPC;
|
return LFS_ERR_NOSPC;
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compact:;
|
||||||
// compact our mdir
|
// compact our mdir
|
||||||
err = lfsr_mdir_compact__(lfs, &mdir_, mdir, start_rid, end_rid);
|
err = lfsr_mdir_compact__(lfs, &mdir_, mdir, start_rid, end_rid);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user