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:
Christopher Haster
2025-05-22 16:39:14 -05:00
parent 6f46ed0031
commit fb736394a4
+71 -71
View File
@@ -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],