Reworked manchor compact to be able to use lfsr_mdir_compact_

More code reuse => smaller code size generally. Though this adds another
special mid value.

Note that the range in this compact excludes all tags, we really only
want the revision count. It's tempting to implicitly copy the
magic/config via the compact range, but this risks included user
attributes and other things that we really don't want cluttering up our
mroot chain.
This commit is contained in:
Christopher Haster
2023-06-19 15:43:09 -05:00
parent 5a88eaccbc
commit 98ef342942
+46 -48
View File
@@ -616,6 +616,7 @@ enum lfsr_tag_type {
LFSR_TAG_RMUATTR = 0x1400,
LFSR_TAG_RMWIDEUATTR = 0x5400, // test only? TODO
LFSR_TAG_SATTR = 0x0500, // test only? TODO
LFSR_TAG_RMWIDESATTR = 0x5500,
LFSR_TAG_ALT = 0x4000,
LFSR_TAG_ALTLE = 0x4000,
@@ -4533,6 +4534,14 @@ static int lfsr_btree_traversal_next(lfs_t *lfs,
/// Metadata pair operations ///
// special mid values
enum {
LFSR_MID_MANCHOR = -4,
LFSR_MID_WL = -3,
LFSR_MID_RM = -2,
LFSR_MID_MROOT = -1,
};
typedef struct lfsr_mpair {
lfs_block_t blocks[2];
} lfsr_mpair_t;
@@ -4785,7 +4794,7 @@ static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mpair_t child,
lfsr_mdir_t mdir;
while (true) {
// fetch next possible superblock
int err = lfsr_mdir_fetch(lfs, &mdir, -1, mpair);
int err = lfsr_mdir_fetch(lfs, &mdir, LFSR_MID_MROOT, mpair);
if (err) {
return err;
}
@@ -4821,15 +4830,16 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
const lfsr_attr_t *attr1s, lfs_size_t attr1_count,
const lfsr_attr_t *attr2s, lfs_size_t attr2_count) {
// TODO different indicator?
// two cases we should alloc:
// 1. if mid != -4, caller expects a new mdir
// 2. if we've compacted this mdir block_cycles number of times,
// trigger a relocation
if (mid != -4 || (
// note mid indicates some special cases:
// - mid = manchor => never alloc (mroot anchor)
// - mid = wl => only alloc if mdir is tired (wear-leveling)
// - otherwise => always alloc, use this mid (new mdir)
if (mid != LFSR_MID_MANCHOR && (mid != LFSR_MID_WL || (
lfs->cfg->block_cycles > 0
&& (mdir->rbyd.rev+1) % lfs->cfg->block_cycles == 0)) {
&& (mdir->rbyd.rev+1) % lfs->cfg->block_cycles == 0))) {
// allocate a new mdir for relocation
int err = lfsr_mdir_alloc(lfs, mdir, (mid != -4 ? mid : mdir->mid));
int err = lfsr_mdir_alloc(lfs, mdir,
(mid != LFSR_MID_WL ? mid : mdir->mid));
if (err) {
return err;
}
@@ -4870,7 +4880,9 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
return err;
}
err = lfsr_rbyd_appendall(lfs, &mdir->rbyd, start_id, end_id,
// note we don't filter attrs from our second pending list, this
// is used for some auxiliary attrs in lfsr_mdir_commit
err = lfsr_rbyd_appendall(lfs, &mdir->rbyd, -1, -1,
attr2s, attr2_count);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
@@ -4943,7 +4955,7 @@ compact:;
}
// try to compact
err = lfsr_mdir_compact_(lfs, &mdir_, -4, -1, -1, mdir,
err = lfsr_mdir_compact_(lfs, &mdir_, LFSR_MID_WL, -1, -1, mdir,
attrs, attr_count,
NULL, 0);
if (err) {
@@ -4957,7 +4969,7 @@ compact:;
static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
const lfsr_attr_t *attrs, lfs_size_t attr_count) {
LFS_ASSERT(mdir->mid != -2);
LFS_ASSERT(mdir->mid != LFSR_MID_RM);
// attempt to commit/compact the mdir normally
lfsr_mdir_t mdir_ = *mdir;
@@ -4982,7 +4994,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
//
// we need to uninline before we split, and it's possible uninlining
// makes the mdir small enough that we don't even need to split
if (mdir->mid == -1) {
if (mdir->mid == LFSR_MID_MROOT) {
// wait, not inlined? this shouldn't happen, most likely too many
// attributes in mroot
LFS_ASSERT(lfsr_btree_weight(&mtree_) == 0);
@@ -5181,7 +5193,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
return d;
}
err = lfsr_mdir_compact_(lfs, &mroot_, -4, -1, 0,
err = lfsr_mdir_compact_(lfs, &mroot_, LFSR_MID_WL, -1, 0,
mdir, attrs, attr_count, LFSR_ATTRS(
LFSR_ATTR_(-1, tag, 0, buf, d)));
if (err) {
@@ -5324,7 +5336,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
}
// mdir reduced to zero? need to drop?
} else if (mdir->mid != -1 && mdir_.rbyd.weight == 0) {
} else if (mdir->mid != LFSR_MID_MROOT && mdir_.rbyd.weight == 0) {
LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.block, mdir->other_block);
@@ -5339,7 +5351,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
// need to relocate?
} else if (!lfsr_mdir_eq(mdir, &mdir_)) {
// relocate mroot
if (mdir->mid == -1) {
if (mdir->mid == LFSR_MID_MROOT) {
mroot_ = mdir_;
dirtymroot = true;
@@ -5367,13 +5379,13 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
}
// just update the root
} else if (mdir->mid == -1) {
} else if (mdir->mid == LFSR_MID_MROOT) {
mroot_ = mdir_;
}
// need to update mtree?
if (dirtymtree) {
LFS_ASSERT(mdir_.mid != -1);
LFS_ASSERT(mdir_.mid != LFSR_MID_MROOT);
// commit mtree
lfsr_tag_t tag;
@@ -5437,7 +5449,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
if (dirtymroot) {
// mchildroot should be our initial mroot at this point
LFS_ASSERT(lfsr_mpair_eq(
lfsr_mdir_mpair(&mchildroot), LFSR_MPAIR(0, 1)));
lfsr_mdir_mpair(&mchildroot),
LFSR_MPAIR(0, 1)));
LFS_DEBUG("Extending mroot 0x{%"PRIx32",%"PRIx32"}"
" -> 0x{%"PRIx32",%"PRIx32"}"
@@ -5446,9 +5459,6 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
mchildroot.other_block, mchildroot.rbyd.block,
mchildroot_.rbyd.block, mchildroot_.other_block);
// TODO should we make mdir_compact accept a range of id+tags and use
// a range to copy over the magic+config?
// copy magic/config from current mroot
lfsr_data_t magic;
err = lfsr_mdir_lookup(lfs, &mchildroot,
@@ -5464,35 +5474,21 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
return err;
}
// commit mrootchild
uint8_t buf[LFSR_MPAIR_DSIZE];
lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mchildroot_, buf);
if (d < 0) {
return d;
}
// TODO should this swap be an mdir function?
// compact into mparentroot, this should stay our mroot anchor
lfsr_mdir_t mparentroot_ = mchildroot;
// swap our rbyds
lfs_swap32(&mparentroot_.rbyd.block, &mparentroot_.other_block);
// update our revision count
// TODO rev things
mparentroot_.rbyd.rev += 1;
mparentroot_.rbyd.off = 0;
mparentroot_.rbyd.trunk = 0;
mparentroot_.rbyd.weight = 0;
mparentroot_.rbyd.crc = 0;
// erase, preparing for compact
err = lfsr_bd_erase(lfs, mparentroot_.rbyd.block);
if (err) {
return err;
}
// compact into new mparentroot
err = lfsr_rbyd_commit(lfs, &mparentroot_.rbyd, LFSR_ATTRS(
LFSR_ATTR_DATA(-1, SUPERMAGIC, 0, magic),
LFSR_ATTR_DATA(-1, SUPERCONFIG, 0, config),
LFSR_ATTR(-1, MROOT, 0, buf, d)));
err = lfsr_mdir_compact_(lfs, &mparentroot_, LFSR_MID_MANCHOR, 0, 0,
&mchildroot, NULL, 0, LFSR_ATTRS(
LFSR_ATTR_DATA(-1, SUPERMAGIC, 0, magic),
LFSR_ATTR_DATA(-1, SUPERCONFIG, 0, config),
// commit our new mchildroot
LFSR_ATTR(-1, MROOT, 0, buf, d)));
if (err) {
return err;
}
@@ -5518,7 +5514,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
// removed?
if (opened->rid + attrs[i].delta < attrs[i].id) {
opened->rid = -2;
opened->mdir.mid = -2;
opened->mdir.mid = LFSR_MID_RM;
} else {
opened->rid += attrs[i].delta;
}
@@ -5588,7 +5584,8 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
//
if (traversal->mdir.rbyd.trunk == 0) {
// fetch the first mroot 0x{0,1}
int err = lfsr_mdir_fetch(lfs, &traversal->mdir, -1, LFSR_MPAIR(0, 1));
int err = lfsr_mdir_fetch(lfs, &traversal->mdir,
LFSR_MID_MROOT, LFSR_MPAIR(0, 1));
if (err) {
return err;
}
@@ -5605,7 +5602,7 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
goto cycle_detect;
// check for mroot/mtree/mdir
} else if (traversal->mdir.mid == -1) {
} else if (traversal->mdir.mid == LFSR_MID_MROOT) {
// lookup mroot, if we find one this is a fake mroot
lfsr_tag_t tag;
lfsr_data_t data;
@@ -5624,7 +5621,8 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
return d;
}
int err = lfsr_mdir_fetch(lfs, &traversal->mdir, -1, mpair);
int err = lfsr_mdir_fetch(lfs, &traversal->mdir,
LFSR_MID_MROOT, mpair);
if (err) {
return err;
}
@@ -5903,7 +5901,7 @@ static int lfsr_mountinited(lfs_t *lfs) {
lfsr_mdir_t *mdir = (lfsr_mdir_t*)data.buf.buffer;
// found an mroot?
if (mdir->mid == -1) {
if (mdir->mid == LFSR_MID_MROOT) {
// has magic string?
lfsr_data_t data;
err = lfsr_mdir_lookup(lfs, mdir, -1, LFSR_TAG_SUPERMAGIC,