Reverted "source rbyd optional" and moved reloc/alloc into lfsr_mdir_compact_

This consolidates all mdir relocation and allocation logic into
lfsr_mdir_compact by using an extra mid hint to indicate if the mdir is
new and unallocated. When mid == -4, the mdir is NOT new, and the mid
should be taken from the mdir.

This deduplicates quite a bit of logic between mdir compaction and
unlining, though it is incompatible with the optional rbyd scheme
previously used to compact mroot 0x{0,1} during mroot extensions.

Though I'm not sure this is the best approach. We should probably look
at this again after things have more of a shape.
This commit is contained in:
Christopher Haster
2023-05-15 01:46:14 -05:00
parent cd2d54855e
commit bac740a90e
+42 -69
View File
@@ -4614,10 +4614,26 @@ static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mpair_t child,
// low-level mdir compaction // low-level mdir compaction
static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir, static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
lfs_ssize_t mid,
lfs_ssize_t start_id, lfs_ssize_t end_id, lfs_ssize_t start_id, lfs_ssize_t end_id,
const lfsr_mdir_t *source, const lfsr_mdir_t *source,
const lfsr_attr_t *attr1s, lfs_size_t attr1_count, const lfsr_attr_t *attr1s, lfs_size_t attr1_count,
const lfsr_attr_t *attr2s, lfs_size_t attr2_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 || (
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));
if (err) {
return err;
}
}
// swap our rbyds // swap our rbyds
lfs_swap32(&mdir->rbyd.block, &mdir->other_block); lfs_swap32(&mdir->rbyd.block, &mdir->other_block);
// update our revision count // update our revision count
@@ -4635,14 +4651,12 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
} }
// copy over attrs // copy over attrs
if (source) {
err = lfsr_rbyd_compact(lfs, &mdir->rbyd, start_id, end_id, false, err = lfsr_rbyd_compact(lfs, &mdir->rbyd, start_id, end_id, false,
&source->rbyd); &source->rbyd);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
} }
}
// append any pending attrs // append any pending attrs
// //
@@ -4727,20 +4741,8 @@ compact:;
return LFS_ERR_RANGE; return LFS_ERR_RANGE;
} }
// if we've compacted this mdir block_cycles number of times, trigger
// a relocation
if (lfs->cfg->block_cycles > 0
&& (mdir->rbyd.rev+1) % lfs->cfg->block_cycles == 0) {
// allocate a new mdir for relocation
err = lfsr_mdir_alloc(lfs, &mdir_, mdir->mid);
if (err) {
return err;
}
}
while (true) {
// try to compact // try to compact
err = lfsr_mdir_compact_(lfs, &mdir_, -1, -1, mdir, err = lfsr_mdir_compact_(lfs, &mdir_, -4, -1, -1, mdir,
attrs, attr_count, attrs, attr_count,
NULL, 0); NULL, 0);
if (err) { if (err) {
@@ -4751,7 +4753,6 @@ compact:;
*mdir = mdir_; *mdir = mdir_;
return 0; return 0;
} }
}
static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid, 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) { const lfsr_attr_t *attrs, lfs_size_t attr_count) {
@@ -4796,14 +4797,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
// uninlining, but not splitting // uninlining, but not splitting
if (fits) { if (fits) {
// allocate a new mdir for uninlining
err = lfsr_mdir_alloc(lfs, &mdir_, 0);
if (err) {
return err;
}
// compact into new mdir tags >= 0 // compact into new mdir tags >= 0
err = lfsr_mdir_compact_(lfs, &mdir_, 0, -1, err = lfsr_mdir_compact_(lfs, &mdir_, 0, 0, -1,
mdir, attrs, attr_count, NULL, 0); mdir, attrs, attr_count, NULL, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
@@ -4849,28 +4844,16 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
return split_id; return split_id;
} }
// allocate a new mdir
err = lfsr_mdir_alloc(lfs, &mdir_, 0);
if (err) {
return err;
}
// compact into new mdir tags < split_id, >= 0 // compact into new mdir tags < split_id, >= 0
err = lfsr_mdir_compact_(lfs, &mdir_, 0, split_id, err = lfsr_mdir_compact_(lfs, &mdir_, 0, 0, split_id,
mdir, attrs, attr_count, NULL, 0); mdir, attrs, attr_count, NULL, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
} }
// allocate a new msibling
err = lfsr_mdir_alloc(lfs, &msibling_, 1);
if (err) {
return err;
}
// compact into new mdir tags >= split_id // compact into new mdir tags >= split_id
err = lfsr_mdir_compact_(lfs, &msibling_, split_id, -1, err = lfsr_mdir_compact_(lfs, &msibling_, 1, split_id, -1,
mdir, attrs, attr_count, NULL, 0); mdir, attrs, attr_count, NULL, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
@@ -5002,22 +4985,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
} }
} }
// TODO adding this here is a cludge and should definitely
// be deduplicated
//
// if we've compacted the mroot block_cycles number of times,
// trigger a relocation
if (lfs->cfg->block_cycles > 0
&& (mroot_.rbyd.rev+1) % lfs->cfg->block_cycles == 0) {
// allocate a new mdir for relocation
err = lfsr_mdir_alloc(lfs, &mroot_, -1);
if (err) {
return err;
}
}
// TODO yeah we're going to need a wide-rm // TODO yeah we're going to need a wide-rm
err = lfsr_mdir_compact_(lfs, &mroot_, -1, 0, err = lfsr_mdir_compact_(lfs, &mroot_, -4, -1, 0,
mdir, attrs, attr_count, mdir, attrs, attr_count,
LFSR_ATTRS( LFSR_ATTRS(
LFSR_ATTR(-1, RMMDIR, 0, NULL, 0), LFSR_ATTR(-1, RMMDIR, 0, NULL, 0),
@@ -5041,28 +5010,16 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
return split_id; return split_id;
} }
// allocate a new mdir
err = lfsr_mdir_alloc(lfs, &mdir_, mdir->mid);
if (err) {
return err;
}
// compact into new mdir tags < split_id // compact into new mdir tags < split_id
err = lfsr_mdir_compact_(lfs, &mdir_, -1, split_id, err = lfsr_mdir_compact_(lfs, &mdir_, mdir->mid, -1, split_id,
mdir, attrs, attr_count, NULL, 0); mdir, attrs, attr_count, NULL, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
} }
// allocate a new msibling
err = lfsr_mdir_alloc(lfs, &msibling_, mdir->mid+1);
if (err) {
return err;
}
// compact into new mdir tags >= split_id // compact into new mdir tags >= split_id
err = lfsr_mdir_compact_(lfs, &msibling_, split_id, -1, err = lfsr_mdir_compact_(lfs, &msibling_, mdir->mid+1, split_id, -1,
mdir, attrs, attr_count, NULL, 0); mdir, attrs, attr_count, NULL, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
@@ -5332,10 +5289,26 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
return d; return d;
} }
// compact into new mparentroot // TODO should this swap be an mdir function?
lfsr_mdir_t mparentroot_ = mchildroot; lfsr_mdir_t mparentroot_ = mchildroot;
err = lfsr_mdir_compact_(lfs, &mparentroot_, -1, -1, // swap our rbyds
NULL, NULL, 0, LFSR_ATTRS( 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, MAGIC, 0, magic), LFSR_ATTR_DATA(-1, MAGIC, 0, magic),
LFSR_ATTR_DATA(-1, CONFIG, 0, config), LFSR_ATTR_DATA(-1, CONFIG, 0, config),
LFSR_ATTR(-1, MROOT, 0, buf, d))); LFSR_ATTR(-1, MROOT, 0, buf, d)));