Added handling of readonly grms to the mtree layer

This bit of code allows us to mount an "inconsistent" filesystem after
powerloss and behave as though we've fixed any pending grms without
actually fixing the grms. This lets the filesystem appear consistent
without needing to modify the disk, and allows truely readonly mounts
without sacrificing powerloss-resilience.

This works by just checking any readonly mid operations against pending
grms and returning NOENT if a fix would remove the mid. Fortunately the
more complex mid operations occur when mutating the filesystem, which we
can ignore as any mutation must be preceded by fixing pending grms.

This check has been added to lfsr_mtree_namelookup and lfsr_mtree_seek,
which should propagate the behavior to high-level functions with minimal
code impact.

This leaves only lfsr_mtree_lookup ignoring pending grms, which is useful
because we need it to actually fix the grms. I don't believe this
function will ever be called by a high-level function directly...

Coverage of readonly grms have also been added to the tests.
This commit is contained in:
Christopher Haster
2023-09-04 16:17:35 -05:00
parent cf90398197
commit c56124f90f
2 changed files with 1030 additions and 43 deletions
+20 -3
View File
@@ -4882,6 +4882,7 @@ static int lfsr_mtree_parent(lfs_t *lfs, const lfs_block_t blocks[static 2],
}
static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) {
while (true) {
// calculate new mid, be careful to avoid rid overflow
lfs_size_t bid = mdir->mid & lfsr_mbidmask(lfs);
lfs_size_t rid = (mdir->mid & lfsr_mridmask(lfs)) + off;
@@ -4905,8 +4906,16 @@ static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) {
}
mdir->mid = bid + rid;
// wait are we grmed? pretend this mid doesn't exist
if (mdir->mid == lfs->grm.rms[0]
|| mdir->mid == lfs->grm.rms[1]) {
continue;
}
return 0;
}
}
// reason is an enum that determines the exact behavior of lfsr_mdir_compact_:
@@ -5852,16 +5861,24 @@ static int lfsr_mtree_namelookup(lfs_t *lfs,
int err = lfsr_mdir_namelookup(lfs, &mdir,
did, name, name_size,
&rid, tag_, data_);
// update mdir weith best place to insert even if we fail
// update mdir with best place to insert even if we fail
mdir.mid += rid;
if (mdir_) {
*mdir_ = mdir;
}
if (err) {
return err;
}
// wait are we grmed? pretend this mid doesn't exist
if (mdir.mid == lfs->grm.rms[0]
|| mdir.mid == lfs->grm.rms[1]) {
return LFS_ERR_NOENT;
}
return 0;
}
// special directory-ids
enum {
+990 -20
View File
File diff suppressed because it is too large Load Diff