From a9c18862c6452c1e794c80abb0220e6de68f90da Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 31 Dec 2025 14:10:52 -0600 Subject: [PATCH] Fixed mroot commit conditions that relied on mdelta==0 This was broken. The good news is this was easily detected by our test_mtree tests. The problem is that mroot split + drop (resulting in an mtree with one mdir) is indistinguishable from mroot relocation via mdelta. Both cases have an mdelta of 0. This also breaks the later mid-mdir update if we wanted to stay on the current chain mroot. The tricky part is we have several entangled cases: - mdir=active mroot, mid>=0 - follow mdir_ - mdir=active mroot, mid<=-1 - follow mroot_, not mdir_! - mdir=chain mroot, mid<=-1 - follow mdir_, not mroot_! --- It's tempting to rely on mid<=-2 vs mid==-1 for chain mroots vs active mroot, but this doesn't always work! During traversals mid is always <=-2, in part because we don't actually know if the current mroot is the active mroot until we try to lookup its child. Fortunately, what _does_ work is just comparing against the mroot's blocks, which we know. Though the continued reliance and reliability of mptr comparisons makes me wonder if it's possible to simplify said function... Code changes: code stack ctx before: 35224 2136 660 after: 35260 (+0.1%) 2136 (+0.0%) 660 (+0.0%) code stack ctx gbmap before: 38464 2144 776 gbmap after: 38492 (+0.1%) 2144 (+0.0%) 776 (+0.0%) code stack ctx preerase before: 39008 2168 796 preerase after: 39036 (+0.1%) 2168 (+0.0%) 796 (+0.0%) --- lfs3.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lfs3.c b/lfs3.c index a5693f80..882bf58d 100644 --- a/lfs3.c +++ b/lfs3.c @@ -9232,7 +9232,7 @@ static int lfs3_mdir_commit_(lfs3_t *lfs3, lfs3_mdir_t *mdir, // need to update mroot chain? if (lfs3_mdir_cmp(&mroot_, &lfs3->mroot) != 0 - || (mdelta == 0 && mdir->mid <= -1)) { + || (mdir->mid <= -1 && lfs3_mdir_cmp(mdir, &lfs3->mroot) != 0)) { // tail recurse, updating mroots until a commit sticks lfs3_mdir_t mrootchild; lfs3_mdir_t mrootchild_; @@ -9399,8 +9399,7 @@ static int lfs3_mdir_commit_(lfs3_t *lfs3, lfs3_mdir_t *mdir, } // update mdir to follow requested rid - if (mdelta > 0 - && mdir->mid <= -1) { + if (mdir->mid <= -1 && lfs3_mdir_cmp(mdir, &lfs3->mroot) == 0) { lfs3_mdir_sync(mdir, &mroot_); } else if (mdelta > 0 && lfs3_mrid(lfs3, mdir->mid)