Tried to reorganize lfsr_mdir_commit_ to make a bit more sense
This should better match other relocation loops in the codebase, and is
hopefully a bit more readable.
---
Note we generally have two patterns for relocation loops:
Loops where we unconditionally allocate/relocate:
relocate:;
alloc();
compact();
if (err) goto relocate;
commit();
if (err) goto relocate;
return;
And loops where we fallback to allocation/relocation:
while (true) {
commit();
if (err) goto relocate;
return;
relocate:;
alloc();
compact();
if (err) goto relocate;
}
lfsr_mdir_commit_ falls into the latter.
No code changes.
This commit is contained in:
@@ -8410,7 +8410,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
mid, rattrs, rattr_count);
|
mid, rattrs, rattr_count);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_RANGE || err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_RANGE || err == LFS_ERR_CORRUPT) {
|
||||||
goto swap;
|
goto compact;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -8419,7 +8419,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
*mdir = mdir_;
|
*mdir = mdir_;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
swap:;
|
compact:;
|
||||||
// can't commit, can we compact?
|
// can't commit, can we compact?
|
||||||
bool relocated = false;
|
bool relocated = false;
|
||||||
bool overrecyclable = true;
|
bool overrecyclable = true;
|
||||||
@@ -8446,88 +8446,88 @@ swap:;
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto compact;
|
while (true) {
|
||||||
|
// try to compact
|
||||||
relocate:;
|
#ifdef LFS_DBGMDIRCOMMITS
|
||||||
// needs relocation? bad prog? ok, try allocating a new mdir
|
LFS_DEBUG("Compacting mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"} "
|
||||||
err = lfsr_mdir_alloc__(lfs, &mdir_, mdir->mid, relocated);
|
"-> 0x{%"PRIx32",%"PRIx32"}",
|
||||||
if (err && !(err == LFS_ERR_NOSPC && overrecyclable)) {
|
|
||||||
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("Overrecycling mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}",
|
|
||||||
lfsr_dbgmbid(lfs, mdir->mid),
|
lfsr_dbgmbid(lfs, mdir->mid),
|
||||||
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1]);
|
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1],
|
||||||
relocated = false;
|
mdir_.rbyd.blocks[0], mdir_.rbyd.blocks[1]);
|
||||||
overrecyclable = false;
|
#endif
|
||||||
|
|
||||||
err = lfsr_mdir_swap__(lfs, &mdir_, mdir, true);
|
// don't copy over gcksum if relocating
|
||||||
|
lfsr_srid_t start_rid_ = start_rid;
|
||||||
|
if (relocated) {
|
||||||
|
start_rid_ = lfs_smax(start_rid_, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compact our mdir
|
||||||
|
err = lfsr_mdir_compact__(lfs, &mdir_, mdir, start_rid_, end_rid);
|
||||||
if (err) {
|
if (err) {
|
||||||
// bad prog? can't do much here, mdir stuck
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
|
// bad prog? try another block
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
LFS_ERROR("Stuck mdir 0x{%"PRIx32",%"PRIx32"}",
|
overrecyclable &= relocated;
|
||||||
mdir->rbyd.blocks[0],
|
goto relocate;
|
||||||
mdir->rbyd.blocks[1]);
|
|
||||||
return LFS_ERR_NOSPC;
|
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
compact:;
|
// now try to commit again
|
||||||
#ifdef LFS_DBGMDIRCOMMITS
|
//
|
||||||
LFS_DEBUG("Compacting mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"} "
|
// upper layers should make sure this can't fail by limiting the
|
||||||
"-> 0x{%"PRIx32",%"PRIx32"}",
|
// maximum commit size
|
||||||
lfsr_dbgmbid(lfs, mdir->mid),
|
err = lfsr_mdir_commit__(lfs, &mdir_, start_rid_, end_rid,
|
||||||
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1],
|
mid, rattrs, rattr_count);
|
||||||
mdir_.rbyd.blocks[0], mdir_.rbyd.blocks[1]);
|
if (err) {
|
||||||
#endif
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
|
// bad prog? try another block
|
||||||
// don't copy over gcksum if relocating
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
lfsr_srid_t start_rid_ = start_rid;
|
overrecyclable &= relocated;
|
||||||
if (relocated) {
|
goto relocate;
|
||||||
start_rid_ = lfs_smax(start_rid_, -1);
|
}
|
||||||
}
|
return err;
|
||||||
|
|
||||||
// compact our mdir
|
|
||||||
err = lfsr_mdir_compact__(lfs, &mdir_, mdir, start_rid_, end_rid);
|
|
||||||
if (err) {
|
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
|
||||||
// bad prog? try another block
|
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
|
||||||
overrecyclable &= relocated;
|
|
||||||
goto relocate;
|
|
||||||
}
|
}
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now try to commit again
|
// consume gcksumdelta if relocated
|
||||||
//
|
if (relocated) {
|
||||||
// upper layers should make sure this can't fail by limiting the
|
lfs->gcksum_d ^= mdir->gcksumdelta;
|
||||||
// maximum commit size
|
|
||||||
err = lfsr_mdir_commit__(lfs, &mdir_, start_rid_, end_rid,
|
|
||||||
mid, rattrs, rattr_count);
|
|
||||||
if (err) {
|
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
|
||||||
// bad prog? try another block
|
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
|
||||||
overrecyclable &= relocated;
|
|
||||||
goto relocate;
|
|
||||||
}
|
}
|
||||||
return err;
|
// update mdir
|
||||||
}
|
*mdir = mdir_;
|
||||||
|
return 0;
|
||||||
|
|
||||||
// consume gcksumdelta if relocated
|
relocate:;
|
||||||
if (relocated) {
|
// needs relocation? bad prog? ok, try allocating a new mdir
|
||||||
lfs->gcksum_d ^= mdir->gcksumdelta;
|
err = lfsr_mdir_alloc__(lfs, &mdir_, mdir->mid, relocated);
|
||||||
|
if (err && !(err == LFS_ERR_NOSPC && overrecyclable)) {
|
||||||
|
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("Overrecycling mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}",
|
||||||
|
lfsr_dbgmbid(lfs, mdir->mid),
|
||||||
|
mdir->rbyd.blocks[0], mdir->rbyd.blocks[1]);
|
||||||
|
relocated = false;
|
||||||
|
overrecyclable = false;
|
||||||
|
|
||||||
|
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_ERROR("Stuck mdir 0x{%"PRIx32",%"PRIx32"}",
|
||||||
|
mdir->rbyd.blocks[0],
|
||||||
|
mdir->rbyd.blocks[1]);
|
||||||
|
return LFS_ERR_NOSPC;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// update mdir
|
|
||||||
*mdir = mdir_;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfsr_mroot_parent(lfs_t *lfs, const lfs_block_t mptr[static 2],
|
static int lfsr_mroot_parent(lfs_t *lfs, const lfs_block_t mptr[static 2],
|
||||||
|
|||||||
Reference in New Issue
Block a user