Fixed mroot chain commits not working
Maybe the subject line should say "Implemented", because these never
worked in the first place. Unfortunately our tests missed this due to a
couple reasons:
- Mroot chains are difficult to create due to the required exponential
growth.
- The only thing that actually commits to chain mroots is mdir
compaction. Though this functionality will be useful for future block
eviction/error correction.
- Previous revision count issues were making relocations in our
compaction tests unlikely.
Fortunately, now that revision count behavior is more correct, our tests
are correctly highlighting that this is broken.
---
Implementing chain mroot commits was a bit intimidating, but fortunately
it just required a bit of teasing to get lfs3_mdir_commit_ to trigger
the tail-recursive mroot chain update when the mdir is a non-active
mroot.
The gcksum is also doing a great job here with identifying bugs. Without
it this bug would have been difficult to notice, since compactions
otherwise have no observable effect on the system.
Code changes:
code stack ctx
before: 35164 2136 660
after: 35224 (+0.2%) 2136 (+0.0%) 660 (+0.0%)
code stack ctx
gbmap before: 38400 2144 776
gbmap after: 38464 (+0.2%) 2144 (+0.0%) 776 (+0.0%)
code stack ctx
preerase before: 38940 2168 796
preerase after: 39008 (+0.2%) 2168 (+0.0%) 796 (+0.0%)
This commit is contained in:
@@ -9140,7 +9140,8 @@ static int lfs3_mdir_commit_(lfs3_t *lfs3, lfs3_mdir_t *mdir,
|
||||
|
||||
// need to relocate?
|
||||
} else if (lfs3_mdir_cmp(&mdir_[0], mdir) != 0
|
||||
&& lfs3_mdir_cmp(mdir, &lfs3->mroot) != 0) {
|
||||
&& lfs3_mdir_cmp(mdir, &lfs3->mroot) != 0
|
||||
&& mdir->mid > -1) {
|
||||
LFS3_INFO("Relocating mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"} "
|
||||
"-> 0x{%"PRIx32",%"PRIx32"}",
|
||||
lfs3_dbgmbid(lfs3, mdir->mid),
|
||||
@@ -9230,10 +9231,18 @@ 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) {
|
||||
if (lfs3_mdir_cmp(&mroot_, &lfs3->mroot) != 0
|
||||
|| (mdelta == 0 && mdir->mid <= -1)) {
|
||||
// tail recurse, updating mroots until a commit sticks
|
||||
lfs3_mdir_t mrootchild = lfs3->mroot;
|
||||
lfs3_mdir_t mrootchild_ = mroot_;
|
||||
lfs3_mdir_t mrootchild;
|
||||
lfs3_mdir_t mrootchild_;
|
||||
if (lfs3_mdir_cmp(&mroot_, &lfs3->mroot) != 0) {
|
||||
mrootchild = lfs3->mroot;
|
||||
mrootchild_ = mroot_;
|
||||
} else {
|
||||
mrootchild = *mdir;
|
||||
mrootchild_ = mdir_[0];
|
||||
}
|
||||
while (lfs3_mdir_cmp(&mrootchild_, &mrootchild) != 0
|
||||
&& !lfs3_mdir_ismrootanchor(&mrootchild)) {
|
||||
// find the mroot's parent
|
||||
@@ -9370,8 +9379,12 @@ static int lfs3_mdir_commit_(lfs3_t *lfs3, lfs3_mdir_t *mdir,
|
||||
continue;
|
||||
}
|
||||
|
||||
// update any mroots, this clobbers chain mroots but that's
|
||||
// better than letting them point to garbage
|
||||
if (h->mdir.mid <= -1) {
|
||||
lfs3_mdir_sync(&h->mdir, &mroot_);
|
||||
// update any splits/drops
|
||||
if (lfs3_mdir_cmp(&h->mdir, mdir) == 0) {
|
||||
} else if (lfs3_mdir_cmp(&h->mdir, mdir) == 0) {
|
||||
if (mdelta > 0
|
||||
&& lfs3_mrid(lfs3, h->mdir.mid)
|
||||
>= (lfs3_srid_t)mdir_[0].r.weight) {
|
||||
@@ -9382,9 +9395,6 @@ static int lfs3_mdir_commit_(lfs3_t *lfs3, lfs3_mdir_t *mdir,
|
||||
}
|
||||
} else if (h->mdir.mid > mdir->mid) {
|
||||
h->mdir.mid += mdelta;
|
||||
// and any mroot updates, though this clobbers chain mroots
|
||||
} else if (h->mdir.mid <= -1) {
|
||||
lfs3_mdir_sync(&h->mdir, &mroot_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user