Dropped special LFSR_MID_RM mid

This is mostly to make it easier to merge mids/rids. Having a special
constant here is tricky when the mid/rid split point is dynamic.

Currently using rbyd.trunk=0 to indicate when an mdir is dropped. This
is nice as it preserves the last mid/rid, which is needed by the readdir
code, and it implicitly returns NOENT to all queries in
lfsr_rbyd_lookup.
This commit is contained in:
Christopher Haster
2023-08-01 11:40:00 -05:00
parent 18e1eb0b41
commit d8d8d1e2ac
3 changed files with 100 additions and 104 deletions
+72 -78
View File
@@ -577,14 +577,6 @@ static int lfsr_bd_erase(lfs_t *lfs, lfs_block_t block) {
// return sizeof(tag) + lfs_tag_size(tag + lfs_tag_isdelete(tag)); // return sizeof(tag) + lfs_tag_size(tag + lfs_tag_isdelete(tag));
//} //}
// special metadata-id values
enum {
LFSR_MID_MROOTANCHOR = -4,
LFSR_MID_WL = -3,
LFSR_MID_RM = -2,
LFSR_MID_MROOT = -1,
};
// 16-bit metadata tags // 16-bit metadata tags
enum lfsr_tag_type { enum lfsr_tag_type {
@@ -1589,17 +1581,16 @@ static int lfsr_gdelta_xor(lfs_t *lfs,
// GRM (global remove) things // GRM (global remove) things
static inline bool lfsr_grm_hasrm(const lfsr_grm_t *grm) { static inline bool lfsr_grm_hasrm(const lfsr_grm_t *grm) {
return grm->rms[0].mid != LFSR_MID_RM; return grm->rms[0].rid != -1;
} }
static inline uint8_t lfsr_grm_count(const lfsr_grm_t *grm) { static inline uint8_t lfsr_grm_count(const lfsr_grm_t *grm) {
return (grm->rms[0].mid != LFSR_MID_RM) return (grm->rms[0].rid != -1) + (grm->rms[1].rid != -1);
+ (grm->rms[1].mid != LFSR_MID_RM);
} }
static inline void lfsr_grm_pushrm(lfsr_grm_t *grm, static inline void lfsr_grm_pushrm(lfsr_grm_t *grm,
lfs_size_t mid, lfs_size_t rid) { lfs_size_t mid, lfs_size_t rid) {
LFS_ASSERT(grm->rms[1].mid == LFSR_MID_RM); LFS_ASSERT(grm->rms[1].rid == -1);
grm->rms[1] = grm->rms[0]; grm->rms[1] = grm->rms[0];
grm->rms[0].mid = mid; grm->rms[0].mid = mid;
grm->rms[0].rid = rid; grm->rms[0].rid = rid;
@@ -1607,7 +1598,8 @@ static inline void lfsr_grm_pushrm(lfsr_grm_t *grm,
static inline void lfsr_grm_poprm(lfsr_grm_t *grm) { static inline void lfsr_grm_poprm(lfsr_grm_t *grm) {
grm->rms[0] = grm->rms[1]; grm->rms[0] = grm->rms[1];
grm->rms[1].mid = LFSR_MID_RM; grm->rms[1].mid = -1;
grm->rms[1].rid = -1;
} }
static int lfsr_grm_todisk(lfs_t *lfs, const lfsr_grm_t *grm, static int lfsr_grm_todisk(lfs_t *lfs, const lfsr_grm_t *grm,
@@ -1624,9 +1616,6 @@ static int lfsr_grm_todisk(lfs_t *lfs, const lfsr_grm_t *grm,
buffer[d] = count; buffer[d] = count;
d += 1; d += 1;
// TODO is this really the best way to do this? should we just allow
// mid=0 to be mroot when mtree is inlined?
for (uint8_t i = 0; i < count; i++) { for (uint8_t i = 0; i < count; i++) {
// map mid=-1 (mroot) to mid=0 // map mid=-1 (mroot) to mid=0
lfs_ssize_t d_ = lfs_toleb128( lfs_ssize_t d_ = lfs_toleb128(
@@ -1648,6 +1637,7 @@ static int lfsr_grm_todisk(lfs_t *lfs, const lfsr_grm_t *grm,
// needed in lfsr_grm_fromdisk // needed in lfsr_grm_fromdisk
static inline int lfsr_mtree_isinlined(lfs_t *lfs); static inline int lfsr_mtree_isinlined(lfs_t *lfs);
static inline lfs_size_t lfsr_mtree_weight(lfs_t *lfs);
static int lfsr_grm_fromdisk(lfs_t *lfs, lfsr_grm_t *grm, static int lfsr_grm_fromdisk(lfs_t *lfs, lfsr_grm_t *grm,
uint8_t buffer[static LFSR_GRM_DSIZE]) { uint8_t buffer[static LFSR_GRM_DSIZE]) {
@@ -1657,8 +1647,10 @@ static int lfsr_grm_fromdisk(lfs_t *lfs, lfsr_grm_t *grm,
d += 1; d += 1;
// clear first // clear first
grm->rms[0].mid = LFSR_MID_RM; grm->rms[0].mid = -1;
grm->rms[1].mid = LFSR_MID_RM; grm->rms[0].rid = -1;
grm->rms[1].mid = -1;
grm->rms[1].rid = -1;
LFS_ASSERT(count <= 2); LFS_ASSERT(count <= 2);
for (uint8_t i = 0; i < count; i++) { for (uint8_t i = 0; i < count; i++) {
@@ -1680,16 +1672,9 @@ static int lfsr_grm_fromdisk(lfs_t *lfs, lfsr_grm_t *grm,
// TODO should these checks be in lfsr_data_readleb128? // TODO should these checks be in lfsr_data_readleb128?
LFS_ASSERT(rid < 0x7fffffff); LFS_ASSERT(rid < 0x7fffffff);
// TODO is this really the best way to do this? should we just allow
// mid=0 to be mroot when mtree is inlined?
// adjust mid if mtree is inlined // adjust mid if mtree is inlined
if (lfsr_mtree_isinlined(lfs)) { LFS_ASSERT(lfsr_mtree_isinlined(lfs) || mid < lfsr_mtree_weight(lfs));
LFS_ASSERT(mid == 0); grm->rms[i].mid = lfs_smin32(mid, lfsr_mtree_weight(lfs)-1);
mid = LFSR_MID_MROOT;
}
grm->rms[i].mid = mid;
grm->rms[i].rid = rid; grm->rms[i].rid = rid;
} }
@@ -5064,8 +5049,8 @@ static lfs_ssize_t lfsr_mdir_todisk(lfs_t *lfs, const lfsr_mdir_t *mdir,
return lfsr_mptr_todisk(lfs, lfsr_mdir_mptr(mdir), buffer); return lfsr_mptr_todisk(lfs, lfsr_mdir_mptr(mdir), buffer);
} }
static inline lfs_size_t lfsr_mdir_weight(const lfsr_mdir_t *mdir) { static inline bool lfsr_mdir_isdropped(const lfsr_mdir_t *mdir) {
return mdir->m.rbyd.weight; return mdir->m.rbyd.trunk == 0;
} }
// track "opened" mdirs that may need to by updated // track "opened" mdirs that may need to by updated
@@ -5287,7 +5272,7 @@ static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mptr_t mchild,
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
while (true) { while (true) {
// fetch next possible superblock // fetch next possible superblock
int err = lfsr_mdir_fetch(lfs, &mdir, mptr, LFSR_MID_MROOT, -1); int err = lfsr_mdir_fetch(lfs, &mdir, mptr, -1, -1);
if (err) { if (err) {
return err; return err;
} }
@@ -5343,18 +5328,22 @@ static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) {
} }
// reason is an enum that determines the exact behavior of lfsr_mdir_compact_:
// - reason = compacting => only alloc if mdir is tired (wear-leveling)
// - reason = extending => never alloc (mroot anchor)
// - reason >= 0 => always alloc, use this as the new mid (new mdir)
enum {
LFSR_MDIR_COMPACTING = -3,
LFSR_MDIR_EXTENDING = -4,
};
// 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 reason,
lfs_ssize_t start_id, lfs_ssize_t end_id, lfs_ssize_t start_id, lfs_ssize_t end_id,
const lfsr_mdir_t *mdir, const lfsr_mdir_t *mdir,
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) {
// note mid indicates some special cases:
// - mid = mrootanchor => never alloc (mroot anchor)
// - mid = wl => only alloc if mdir is tired (wear-leveling)
// - otherwise => always alloc, use this mid (new mdir)
// first thing we need to do is read our current revision count // first thing we need to do is read our current revision count
uint32_t rev; uint32_t rev;
int err = lfsr_bd_read(lfs, mdir->m.rbyd.block, 0, sizeof(uint32_t), int err = lfsr_bd_read(lfs, mdir->m.rbyd.block, 0, sizeof(uint32_t),
@@ -5366,13 +5355,13 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_,
rev = (err != LFS_ERR_CORRUPT ? lfs_fromle32_(&rev) : 0); rev = (err != LFS_ERR_CORRUPT ? lfs_fromle32_(&rev) : 0);
// decide if we need to relocate // decide if we need to relocate
if (mid != LFSR_MID_MROOTANCHOR && (mid != LFSR_MID_WL || ( if (reason != LFSR_MDIR_EXTENDING && (reason != LFSR_MDIR_COMPACTING || (
lfs->cfg->block_cycles > 0 lfs->cfg->block_cycles > 0
// TODO rev things // TODO rev things
&& (rev + 1) % lfs->cfg->block_cycles == 0))) { && (rev + 1) % lfs->cfg->block_cycles == 0))) {
// allocate a new mdir for relocation // allocate a new mdir for relocation
err = lfsr_mdir_alloc(lfs, mdir_, err = lfsr_mdir_alloc(lfs, mdir_,
(mid != LFSR_MID_WL ? mid : mdir_->mid)); (reason >= 0 ? reason : mdir_->mid));
if (err) { if (err) {
return err; return err;
} }
@@ -5392,7 +5381,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_,
// only consume gstate here during normal compacts // only consume gstate here during normal compacts
// TODO avoid duplicate conditions somehow? // TODO avoid duplicate conditions somehow?
if (mid == LFSR_MID_WL) { if (reason == LFSR_MDIR_COMPACTING) {
// consume gstate on original rbyd, we need this even if we drop // consume gstate on original rbyd, we need this even if we drop
// our mdir to avoid losing info // our mdir to avoid losing info
// //
@@ -5466,8 +5455,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_,
// //
// this pushes gstate up into the mroot when relocating, and // this pushes gstate up into the mroot when relocating, and
// helps avoid corner case issues when splitting/dropping // helps avoid corner case issues when splitting/dropping
if (mdir_->mid == LFSR_MID_MROOT if (mdir_->mid == -1 || lfsr_mdir_cmp(mdir_, mdir) == 0) {
|| lfsr_mdir_cmp(mdir_, mdir) == 0) {
err = lfsr_rbyd_appendgdelta(lfs, &mdir_->m.rbyd); err = lfsr_rbyd_appendgdelta(lfs, &mdir_->m.rbyd);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
@@ -5489,8 +5477,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_,
// TODO avoid duplicate conditions somehow? // TODO avoid duplicate conditions somehow?
// success? gstate is committed // success? gstate is committed
if (mdir_->mid == LFSR_MID_MROOT if (mdir_->mid == -1 || lfsr_mdir_cmp(mdir_, mdir) == 0) {
|| lfsr_mdir_cmp(mdir_, mdir) == 0) {
lfsr_fs_flushgdelta(lfs); lfsr_fs_flushgdelta(lfs);
} }
} }
@@ -5575,7 +5562,8 @@ compact:;
} }
// try to compact // try to compact
err = lfsr_mdir_compact_(lfs, &mdir_, LFSR_MID_WL, start_id, end_id, mdir, err = lfsr_mdir_compact_(lfs, &mdir_, LFSR_MDIR_COMPACTING,
start_id, end_id, mdir,
attrs, attr_count, attrs, attr_count,
NULL, 0); NULL, 0);
if (err) { if (err) {
@@ -5593,8 +5581,8 @@ compact:;
// //
static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
const lfsr_attr_t *attrs, lfs_size_t attr_count) { const lfsr_attr_t *attrs, lfs_size_t attr_count) {
LFS_ASSERT(mdir->mid != LFSR_MID_RM); LFS_ASSERT(!lfsr_mdir_isdropped(mdir));
LFS_ASSERT(mdir->mid == LFSR_MID_MROOT || mdir->m.rbyd.weight > 0); LFS_ASSERT(mdir->mid == -1 || mdir->m.rbyd.weight > 0);
// parse out any pending gstate, these will get automatically xored // parse out any pending gstate, these will get automatically xored
// with on-disk gdeltas in lower-level functions // with on-disk gdeltas in lower-level functions
@@ -5632,8 +5620,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// //
// TODO wait, do we need to update lfs->mroot and mdir eagerly // TODO wait, do we need to update lfs->mroot and mdir eagerly
// for the same reason? // for the same reason?
lfsr_mdir_t mroot_ = (mdir->mid == LFSR_MID_MROOT ? mdir_ : lfs->mroot); lfsr_mdir_t mroot_ = (mdir->mid == -1 ? mdir_ : lfs->mroot);
lfsr_mdir_t msibling_ = {.mid=LFSR_MID_RM, .m.rbyd.weight = 0}; lfsr_mdir_t msibling_ = {.m.rbyd.weight=0};
lfsr_btree_t mtree_ = lfs->mtree; lfsr_btree_t mtree_ = lfs->mtree;
bool dirtymroot = false; bool dirtymroot = false;
bool dirtymtree = false; bool dirtymtree = false;
@@ -5642,7 +5630,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
if (err == LFS_ERR_RANGE) { if (err == LFS_ERR_RANGE) {
// if we're the mroot, create a new mtree, assume the upper layers // if we're the mroot, create a new mtree, assume the upper layers
// will take care of grafting our mtree into the mroot as needed // will take care of grafting our mtree into the mroot as needed
if (mdir->mid == LFSR_MID_MROOT) { if (mdir->mid == -1) {
// Create a null entry in our btree first. Don't worry! Thanks // Create a null entry in our btree first. Don't worry! Thanks
// to inlining this doesn't allocate anything yet. // to inlining this doesn't allocate anything yet.
// //
@@ -5709,6 +5697,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}",
msibling_.mid, msibling_.mid,
msibling_.m.rbyd.block, msibling_.m.redund_block); msibling_.m.rbyd.block, msibling_.m.redund_block);
// mark as dropped
mdir_.m.rbyd.trunk = 0; mdir_.m.rbyd.trunk = 0;
msibling_.m.rbyd.trunk = 0; msibling_.m.rbyd.trunk = 0;
@@ -5723,6 +5712,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}",
mdir_.mid, mdir_.mid,
mdir_.m.rbyd.block, mdir_.m.redund_block); mdir_.m.rbyd.block, mdir_.m.redund_block);
// mark as dropped
mdir_.m.rbyd.trunk = 0; mdir_.m.rbyd.trunk = 0;
// update our mtree // update our mtree
@@ -5743,6 +5734,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}",
msibling_.mid, msibling_.mid,
msibling_.m.rbyd.block, msibling_.m.redund_block); msibling_.m.rbyd.block, msibling_.m.redund_block);
// mark as dropped
msibling_.m.rbyd.trunk = 0; msibling_.m.rbyd.trunk = 0;
// update our mtree // update our mtree
@@ -5804,10 +5797,12 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
dirtymtree = true; dirtymtree = true;
// mdir reduced to zero? need to drop? // mdir reduced to zero? need to drop?
} else if (mdir->mid != LFSR_MID_MROOT && mdir_.m.rbyd.weight == 0) { } else if (mdir->mid != -1 && mdir_.m.rbyd.weight == 0) {
LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}",
mdir->mid, mdir->mid,
mdir->m.rbyd.block, mdir->m.redund_block); mdir->m.rbyd.block, mdir->m.redund_block);
// mark as dropped
mdir_.m.rbyd.trunk = 0; mdir_.m.rbyd.trunk = 0;
// update our mtree // update our mtree
@@ -5821,7 +5816,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// need to relocate? // need to relocate?
} else if (lfsr_mdir_cmp(mdir, &mdir_) != 0) { } else if (lfsr_mdir_cmp(mdir, &mdir_) != 0) {
// relocate mroot // relocate mroot
if (mdir->mid == LFSR_MID_MROOT) { if (mdir->mid == -1) {
// if we're relocating our root, just mark the root as dirty // if we're relocating our root, just mark the root as dirty
// and let our dirtymroot code handle this // and let our dirtymroot code handle this
dirtymroot = true; dirtymroot = true;
@@ -5904,7 +5899,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
if (lfsr_btree_weight(&mtree_) == 0) { if (lfsr_btree_weight(&mtree_) == 0) {
LFS_ASSERT(grm->rms[j].mid <= 0); LFS_ASSERT(grm->rms[j].mid <= 0);
if (grm->rms[j].mid == 0) { if (grm->rms[j].mid == 0) {
grm->rms[j].mid = LFSR_MID_MROOT; grm->rms[j].mid = -1;
} }
} }
} }
@@ -5925,7 +5920,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// need to update mtree? // need to update mtree?
if (dirtymtree) { if (dirtymtree) {
LFS_ASSERT(mdir_.mid != LFSR_MID_MROOT); LFS_ASSERT(mdir_.mid != -1);
// commit mtree // commit mtree
lfsr_tag_t tag; lfsr_tag_t tag;
@@ -6021,7 +6016,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// compact into mparentroot, this should stay our mroot anchor // compact into mparentroot, this should stay our mroot anchor
lfsr_mdir_t mparentroot_ = mchildroot; lfsr_mdir_t mparentroot_ = mchildroot;
err = lfsr_mdir_compact_(lfs, &mparentroot_, LFSR_MID_MROOTANCHOR, 0, 0, err = lfsr_mdir_compact_(lfs, &mparentroot_, LFSR_MDIR_EXTENDING, 0, 0,
&mchildroot, NULL, 0, LFSR_ATTRS( &mchildroot, NULL, 0, LFSR_ATTRS(
LFSR_ATTR_DATA(-1, SUPERMAGIC, 0, magic), LFSR_ATTR_DATA(-1, SUPERMAGIC, 0, magic),
LFSR_ATTR_DATA(-1, SUPERCONFIG, 0, config), LFSR_ATTR_DATA(-1, SUPERCONFIG, 0, config),
@@ -6062,6 +6057,12 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// first play out any attrs that change our rid // first play out any attrs that change our rid
for (lfs_size_t i = 0; i < attr_count; i++) { for (lfs_size_t i = 0; i < attr_count; i++) {
// TODO just remove dropped mdirs from this list?
// skip dropped mdirs
if (lfsr_mdir_isdropped(&opened->mdir)) {
continue;
}
// TODO clean this up a bit // TODO clean this up a bit
// adjust opened mdirs? // adjust opened mdirs?
if (opened->mdir.mid == mdir->mid if (opened->mdir.mid == mdir->mid
@@ -6075,7 +6076,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
if (type == LFS_TYPE_DIR) { if (type == LFS_TYPE_DIR) {
opened->mdir.rid = attrs[i].id; opened->mdir.rid = attrs[i].id;
} else { } else {
opened->mdir.mid = LFSR_MID_RM; opened->mdir.mid = -1;
opened->mdir.rid = -1;
} }
} else { } else {
opened->mdir.rid += attrs[i].delta; opened->mdir.rid += attrs[i].delta;
@@ -6111,7 +6113,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// removed? // removed?
if (((lfsr_dir_t*)opened)->dstart_rid if (((lfsr_dir_t*)opened)->dstart_rid
+ attrs[i].delta < attrs[i].id) { + attrs[i].delta < attrs[i].id) {
((lfsr_dir_t*)opened)->dstart_mid = LFSR_MID_RM; ((lfsr_dir_t*)opened)->dstart_mid = -1;
((lfsr_dir_t*)opened)->dstart_rid = -1;
} else { } else {
((lfsr_dir_t*)opened)->dstart_rid += attrs[i].delta; ((lfsr_dir_t*)opened)->dstart_rid += attrs[i].delta;
} }
@@ -6264,7 +6267,7 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path,
lfsr_mdir_t *mdir_, lfsr_tag_t *tag_, lfsr_mdir_t *mdir_, lfsr_tag_t *tag_,
lfs_size_t *did_, const char **name_, lfs_size_t *name_size_) { lfs_size_t *did_, const char **name_, lfs_size_t *name_size_) {
// setup root // setup root
lfsr_mdir_t mdir = {.mid = LFSR_MID_RM, .rid = -1}; lfsr_mdir_t mdir = {.rid=-1};
lfsr_tag_t tag = LFSR_TAG_DIR; lfsr_tag_t tag = LFSR_TAG_DIR;
lfs_size_t did = LFSR_DID_ROOT; lfs_size_t did = LFSR_DID_ROOT;
@@ -6419,7 +6422,7 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
if (traversal->mdir.m.rbyd.trunk == 0) { if (traversal->mdir.m.rbyd.trunk == 0) {
// fetch the first mroot 0x{0,1} // fetch the first mroot 0x{0,1}
int err = lfsr_mdir_fetch(lfs, &traversal->mdir, int err = lfsr_mdir_fetch(lfs, &traversal->mdir,
LFSR_MPTR_MROOTANCHOR, LFSR_MID_MROOT, -1); LFSR_MPTR_MROOTANCHOR, -1, -1);
if (err) { if (err) {
return err; return err;
} }
@@ -6436,7 +6439,7 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
goto cycle_detect; goto cycle_detect;
// check for mroot/mtree/mdir // check for mroot/mtree/mdir
} else if (traversal->mdir.mid == LFSR_MID_MROOT) { } else if (traversal->mdir.mid == -1) {
// lookup mroot, if we find one this is a fake mroot // lookup mroot, if we find one this is a fake mroot
lfsr_tag_t tag; lfsr_tag_t tag;
lfsr_data_t data; lfsr_data_t data;
@@ -6455,8 +6458,7 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
return d; return d;
} }
int err = lfsr_mdir_fetch(lfs, &traversal->mdir, int err = lfsr_mdir_fetch(lfs, &traversal->mdir, mptr, -1, -1);
mptr, LFSR_MID_MROOT, -1);
if (err) { if (err) {
return err; return err;
} }
@@ -6739,7 +6741,7 @@ static int lfsr_mountinited(lfs_t *lfs) {
lfsr_mdir_t *mdir = (lfsr_mdir_t*)data.buf.buffer; lfsr_mdir_t *mdir = (lfsr_mdir_t*)data.buf.buffer;
// found an mroot? // found an mroot?
if (mdir->mid == LFSR_MID_MROOT) { if (mdir->mid == -1) {
// has magic string? // has magic string?
lfsr_data_t data; lfsr_data_t data;
err = lfsr_mdir_lookup(lfs, mdir, -1, LFSR_TAG_SUPERMAGIC, err = lfsr_mdir_lookup(lfs, mdir, -1, LFSR_TAG_SUPERMAGIC,
@@ -7005,13 +7007,9 @@ static int lfsr_mountinited(lfs_t *lfs) {
if (lfsr_grm_hasrm(&lfs->grm)) { if (lfsr_grm_hasrm(&lfs->grm)) {
LFS_DEBUG("Found pending grm %"PRId32".%"PRId32" %"PRId32".%"PRId32, LFS_DEBUG("Found pending grm %"PRId32".%"PRId32" %"PRId32".%"PRId32,
lfs->grm.rms[0].mid, lfs->grm.rms[0].mid,
(lfs->grm.rms[0].mid != LFSR_MID_RM lfs->grm.rms[0].rid,
? lfs->grm.rms[0].rid
: 0),
lfs->grm.rms[1].mid, lfs->grm.rms[1].mid,
(lfs->grm.rms[1].mid != LFSR_MID_RM lfs->grm.rms[1].rid);
? lfs->grm.rms[1].rid
: 0));
} }
return 0; return 0;
@@ -7319,7 +7317,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
LFSR_ATTR_DNAME(mdir.rid, DSTART, +1, did, NULL, 0), LFSR_ATTR_DNAME(mdir.rid, DSTART, +1, did, NULL, 0),
LFSR_ATTR_GRM(-1, GRM, 0, &((lfsr_grm_t){.rms={ LFSR_ATTR_GRM(-1, GRM, 0, &((lfsr_grm_t){.rms={
{.mid=mdir.mid, .rid=mdir.rid}, {.mid=mdir.mid, .rid=mdir.rid},
{.mid=LFSR_MID_RM}}})))); {.mid=-1, .rid=-1}}}))));
if (err) { if (err) {
goto failed_with_parent; goto failed_with_parent;
} }
@@ -7334,8 +7332,8 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
parent_did, name, name_size), parent_did, name, name_size),
LFSR_ATTR_LEB128(parent.mdir.rid, DID, 0, did), LFSR_ATTR_LEB128(parent.mdir.rid, DID, 0, did),
LFSR_ATTR_GRM(-1, GRM, 0, &((lfsr_grm_t){.rms={ LFSR_ATTR_GRM(-1, GRM, 0, &((lfsr_grm_t){.rms={
{.mid=LFSR_MID_RM}, {.mid=-1, .rid=-1},
{.mid=LFSR_MID_RM}}})))); {.mid=-1, .rid=-1}}}))));
if (err) { if (err) {
return err; return err;
} }
@@ -7758,7 +7756,7 @@ lfs_soff_t lfsr_dir_tell(lfs_t *lfs, lfsr_dir_t *dir) {
int lfsr_dir_rewind(lfs_t *lfs, lfsr_dir_t *dir) { int lfsr_dir_rewind(lfs_t *lfs, lfsr_dir_t *dir) {
// do nothing if removed // do nothing if removed
if (dir->dstart_mid == LFSR_MID_RM) { if (dir->dstart_rid == -1) {
return 0; return 0;
} }
@@ -7827,13 +7825,9 @@ static int lfsr_fs_preparemutation(lfs_t *lfs) {
if (lfsr_grm_hasrm(&lfs->grm)) { if (lfsr_grm_hasrm(&lfs->grm)) {
LFS_DEBUG("Fixing grm %"PRId32".%"PRId32" %"PRId32".%"PRId32, LFS_DEBUG("Fixing grm %"PRId32".%"PRId32" %"PRId32".%"PRId32,
lfs->grm.rms[0].mid, lfs->grm.rms[0].mid,
(lfs->grm.rms[0].mid != LFSR_MID_RM lfs->grm.rms[0].rid,
? lfs->grm.rms[0].rid
: 0),
lfs->grm.rms[1].mid, lfs->grm.rms[1].mid,
(lfs->grm.rms[1].mid != LFSR_MID_RM lfs->grm.rms[1].rid);
? lfs->grm.rms[1].rid
: 0));
int err = lfsr_fs_fixgrm(lfs); int err = lfsr_fs_fixgrm(lfs);
if (err) { if (err) {
+27 -25
View File
@@ -431,7 +431,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -456,7 +456,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -500,7 +500,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
// choose a pseudo-random rid // choose a pseudo-random rid
mdir.rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); mdir.rid = TEST_PRNG(&prng) % (mdir.m.rbyd.weight+1);
// force a compaction? // force a compaction?
if (FORCE_COMPACTION) { if (FORCE_COMPACTION) {
@@ -530,7 +530,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -559,7 +559,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -1300,7 +1300,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -1325,7 +1325,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -1381,7 +1381,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -1412,7 +1412,7 @@ code = '''
} }
assert(lfsr_mtree_weight(&lfs) == 0); assert(lfsr_mtree_weight(&lfs) == 0);
assert(lfsr_mdir_weight(&lfs.mroot) == 0); assert(lfs.mroot.m.rbyd.weight == 0);
} }
lfsr_unmount(&lfs) => 0; lfsr_unmount(&lfs) => 0;
@@ -1422,7 +1422,7 @@ code = '''
lfsr_mount(&lfs, cfg) => 0; lfsr_mount(&lfs, cfg) => 0;
assert(lfsr_mtree_weight(&lfs) == 0); assert(lfsr_mtree_weight(&lfs) == 0);
assert(lfsr_mdir_weight(&lfs.mroot) == 0); assert(lfs.mroot.m.rbyd.weight == 0);
lfsr_unmount(&lfs) => 0; lfsr_unmount(&lfs) => 0;
''' '''
@@ -1456,9 +1456,9 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
// choose a pseudo-random rid // choose a pseudo-random rid
mdir.rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); mdir.rid = TEST_PRNG(&prng) % (mdir.m.rbyd.weight+1);
// choose to create or delete // choose to create or delete
uint8_t op = (lfs_size_t)mdir.rid == lfsr_mdir_weight(&mdir) uint8_t op = (lfs_size_t)mdir.rid == mdir.m.rbyd.weight
? 0 ? 0
: TEST_PRNG(&prng) % 2; : TEST_PRNG(&prng) % 2;
@@ -1505,7 +1505,7 @@ code = '''
assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0); assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0);
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -1538,7 +1538,7 @@ code = '''
assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0); assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0);
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -2544,9 +2544,9 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
// choose a pseudo-random rid // choose a pseudo-random rid
mdir.rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); mdir.rid = TEST_PRNG(&prng) % (mdir.m.rbyd.weight+1);
// choose to create or delete // choose to create or delete
uint8_t op = (lfs_size_t)mdir.rid == lfsr_mdir_weight(&mdir) uint8_t op = (lfs_size_t)mdir.rid == mdir.m.rbyd.weight
? 0 ? 0
: TEST_PRNG(&prng) % 3; : TEST_PRNG(&prng) % 3;
@@ -2606,7 +2606,7 @@ code = '''
assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0); assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0);
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -2639,7 +2639,7 @@ code = '''
assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0); assert(mdir.mid == -1 || mdir.m.rbyd.weight > 0);
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -2746,7 +2746,8 @@ code = '''
assert(lfs.mroot.m.rbyd.weight == 1); assert(lfs.mroot.m.rbyd.weight == 1);
// assert that our neighbors were updated correctly // assert that our neighbors were updated correctly
assert(left_neighbor.mdir.mid == LFSR_MID_RM); assert(left_neighbor.mdir.mid == -1);
assert(left_neighbor.mdir.rid == -1);
assert(right_neighbor.mdir.mid == -1); assert(right_neighbor.mdir.mid == -1);
assert(right_neighbor.mdir.rid == 0); assert(right_neighbor.mdir.rid == 0);
assert(memcmp(&right_neighbor.mdir.m, &lfs.mroot.m, assert(memcmp(&right_neighbor.mdir.m, &lfs.mroot.m,
@@ -2795,7 +2796,8 @@ code = '''
assert(left_neighbor.mdir.rid == 0); assert(left_neighbor.mdir.rid == 0);
assert(memcmp(&left_neighbor.mdir.m, &lfs.mroot.m, assert(memcmp(&left_neighbor.mdir.m, &lfs.mroot.m,
sizeof(lfs.mroot.m)) == 0); sizeof(lfs.mroot.m)) == 0);
assert(right_neighbor.mdir.mid == LFSR_MID_RM); assert(right_neighbor.mdir.mid == -1);
assert(right_neighbor.mdir.rid == -1);
lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor);
lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor);
@@ -3946,7 +3948,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -4028,7 +4030,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -4072,7 +4074,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
// choose a pseudo-random rid // choose a pseudo-random rid
mdir.rid = TEST_PRNG(&prng) % (lfsr_mdir_weight(&mdir)+1); mdir.rid = TEST_PRNG(&prng) % (mdir.m.rbyd.weight+1);
// force a compaction? // force a compaction?
if (FORCE_COMPACTION) { if (FORCE_COMPACTION) {
@@ -4102,7 +4104,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
@@ -4189,7 +4191,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,
+1 -1
View File
@@ -147,7 +147,7 @@ code = '''
lfsr_mdir_t mdir; lfsr_mdir_t mdir;
lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0; lfsr_mtree_lookup(&lfs, mid, -1, &mdir) => 0;
for (mdir.rid = 0; for (mdir.rid = 0;
mdir.rid < (lfs_ssize_t)lfsr_mdir_weight(&mdir); mdir.rid < (lfs_ssize_t)mdir.m.rbyd.weight;
mdir.rid++) { mdir.rid++) {
uint8_t buffer[4]; uint8_t buffer[4];
lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED, lfsr_mdir_get(&lfs, &mdir, mdir.rid, LFSR_TAG_INLINED,