diff --git a/lfs.c b/lfs.c index 70a2a955..c6437184 100644 --- a/lfs.c +++ b/lfs.c @@ -6557,26 +6557,24 @@ static inline lfsr_srid_t lfsr_mid_rid(const lfs_t *lfs, lfsr_smid_t mid) { /// metadata-pointer things /// // the mroot anchor, mdir 0x{0,1} is the entry point into the filesystem -#define LFSR_MPTR_MROOTANCHOR() ((const lfsr_mptr_t){{0, 1}}) +#define LFSR_MPTR_MROOTANCHOR() ((const lfs_block_t[2]){0, 1}) static inline int lfsr_mptr_cmp( - const lfsr_mptr_t *a, - const lfsr_mptr_t *b) { + const lfs_block_t a[static 2], + const lfs_block_t b[static 2]) { // note these can be in either order - if (lfs_max(a->blocks[0], a->blocks[1]) - != lfs_max(b->blocks[0], b->blocks[1])) { - return lfs_max(a->blocks[0], a->blocks[1]) - - lfs_max(b->blocks[0], b->blocks[1]); + if (lfs_max(a[0], a[1]) != lfs_max(b[0], b[1])) { + return lfs_max(a[0], a[1]) - lfs_max(b[0], b[1]); } else { - return lfs_min(a->blocks[0], a->blocks[1]) - - lfs_min(b->blocks[0], b->blocks[1]); + return lfs_min(a[0], a[1]) - lfs_min(b[0], b[1]); } } -static inline bool lfsr_mptr_ismrootanchor(const lfsr_mptr_t *mptr) { +static inline bool lfsr_mptr_ismrootanchor( + const lfs_block_t mptr[static 2]) { // mrootanchor is always at 0x{0,1} // just check that the first block is in mroot anchor range - return mptr->blocks[0] <= 1; + return mptr[0] <= 1; } // mptr encoding: @@ -6594,15 +6592,15 @@ static inline bool lfsr_mptr_ismrootanchor(const lfsr_mptr_t *mptr) { #define LFSR_DATA_MPTR(_mptr) \ LFSR_DATA_MPTR_(_mptr, (uint8_t[LFSR_MPTR_DSIZE]){0}) -static lfsr_data_t lfsr_data_frommptr(const lfsr_mptr_t *mptr, +static lfsr_data_t lfsr_data_frommptr(const lfs_block_t mptr[static 2], uint8_t buffer[static LFSR_MPTR_DSIZE]) { // blocks should not exceed 31-bits - LFS_ASSERT(mptr->blocks[0] <= 0x7fffffff); - LFS_ASSERT(mptr->blocks[1] <= 0x7fffffff); + LFS_ASSERT(mptr[0] <= 0x7fffffff); + LFS_ASSERT(mptr[1] <= 0x7fffffff); lfs_ssize_t d = 0; for (int i = 0; i < 2; i++) { - lfs_ssize_t d_ = lfs_toleb128(mptr->blocks[i], &buffer[d], 5); + lfs_ssize_t d_ = lfs_toleb128(mptr[i], &buffer[d], 5); if (d_ < 0) { LFS_UNREACHABLE(); } @@ -6613,9 +6611,9 @@ static lfsr_data_t lfsr_data_frommptr(const lfsr_mptr_t *mptr, } static int lfsr_data_readmptr(lfs_t *lfs, lfsr_data_t *data, - lfsr_mptr_t *mptr) { + lfs_block_t mptr[static 2]) { for (int i = 0; i < 2; i++) { - int err = lfsr_data_readleb128(lfs, data, &mptr->blocks[i]); + int err = lfsr_data_readleb128(lfs, data, &mptr[i]); if (err) { return err; } @@ -7146,30 +7144,26 @@ static inline uint32_t lfsr_rev_inc(lfs_t *lfs, uint32_t rev) { /// Metadata pair stuff /// // mdir convenience functions -static inline const lfsr_mptr_t *lfsr_mdir_mptr(const lfsr_mdir_t *mdir) { - return (const lfsr_mptr_t*)mdir->rbyd.blocks; -} - static inline int lfsr_mdir_cmp(const lfsr_mdir_t *a, const lfsr_mdir_t *b) { - return lfsr_mptr_cmp(lfsr_mdir_mptr(a), lfsr_mdir_mptr(b)); + return lfsr_mptr_cmp(a->rbyd.blocks, b->rbyd.blocks); } static inline bool lfsr_mdir_ismrootanchor(const lfsr_mdir_t *mdir) { - return lfsr_mptr_ismrootanchor(lfsr_mdir_mptr(mdir)); + return lfsr_mptr_ismrootanchor(mdir->rbyd.blocks); } // mdir operations static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, - lfsr_smid_t mid, const lfsr_mptr_t *mptr) { - // create a copy of blocks, this is so we can swap the blocks - // to keep track of the current revision, this also prevents issues - // if blocks points to the blocks in the mdir - lfs_block_t blocks_[2] = {mptr->blocks[0], mptr->blocks[1]}; + lfsr_smid_t mid, const lfs_block_t mptr[static 2]) { + // create a copy of the mptr, both so we can swap the blocks to keep + // track of the current revision, and to prevents issues if mptr + // references the blocks in the mdir + lfs_block_t blocks[2] = {mptr[0], mptr[1]}; // read both revision counts, try to figure out which block // has the most recent revision uint32_t revs[2] = {0, 0}; for (int i = 0; i < 2; i++) { - int err = lfsr_bd_read(lfs, blocks_[0], 0, 0, + int err = lfsr_bd_read(lfs, blocks[0], 0, 0, &revs[0], sizeof(uint32_t)); if (err && err != LFS_ERR_CORRUPT) { return err; @@ -7179,14 +7173,14 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, if (i == 0 || err == LFS_ERR_CORRUPT || lfs_scmp(revs[1], revs[0]) > 0) { - LFS_SWAP(lfs_block_t, &blocks_[0], &blocks_[1]); + LFS_SWAP(lfs_block_t, &blocks[0], &blocks[1]); LFS_SWAP(uint32_t, &revs[0], &revs[1]); } } // try to fetch rbyds in the order of most recent to least recent for (int i = 0; i < 2; i++) { - int err = lfsr_rbyd_fetch(lfs, &mdir->rbyd, blocks_[0], 0); + int err = lfsr_rbyd_fetch(lfs, &mdir->rbyd, blocks[0], 0); if (err && err != LFS_ERR_CORRUPT) { return err; } @@ -7194,11 +7188,11 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, if (err != LFS_ERR_CORRUPT) { mdir->mid = mid; // keep track of other block for compactions - mdir->rbyd.blocks[1] = blocks_[1]; + mdir->rbyd.blocks[1] = blocks[1]; return 0; } - LFS_SWAP(lfs_block_t, &blocks_[0], &blocks_[1]); + LFS_SWAP(lfs_block_t, &blocks[0], &blocks[1]); LFS_SWAP(uint32_t, &revs[0], &revs[1]); } @@ -7211,12 +7205,12 @@ static int lfsr_data_fetchmdir(lfs_t *lfs, lfsr_mdir_t *mdir) { // decode mptr and fetch int err = lfsr_data_readmptr(lfs, data, - (lfsr_mptr_t*)mdir->rbyd.blocks); + mdir->rbyd.blocks); if (err) { return err; } - return lfsr_mdir_fetch(lfs, mdir, mid, lfsr_mdir_mptr(mdir)); + return lfsr_mdir_fetch(lfs, mdir, mid, mdir->rbyd.blocks); } static int lfsr_mdir_lookupnext(lfs_t *lfs, const lfsr_mdir_t *mdir, @@ -7324,9 +7318,10 @@ static int lfsr_mdir_suplookup(lfs_t *lfs, const lfsr_mdir_t *mdir, #define LFSR_MTREE_NULL() ((lfsr_mtree_t){ \ .u.weight=(LFSR_MTREE_ISMPTR | 0)}) -#define LFSR_MTREE_MPTR(_mptr, _weight) ((lfsr_mtree_t){ \ +#define LFSR_MTREE_MPTR(_block0, _block1, _weight) ((lfsr_mtree_t){ \ .u.mptr.weight=(LFSR_MTREE_ISMPTR | (_weight)), \ - .u.mptr.mptr=_mptr}) + .u.mptr.blocks[0]=_block0, \ + .u.mptr.blocks[1]=_block1}) static inline bool lfsr_mtree_isnull(const lfsr_mtree_t *mtree) { return mtree->u.weight == (LFSR_MTREE_ISMPTR | 0); @@ -7352,7 +7347,7 @@ static inline int lfsr_mtree_cmp( } else if (lfsr_mtree_isnull(a)) { return 0; } else if (lfsr_mtree_ismptr(a)) { - return lfsr_mptr_cmp(&a->u.mptr.mptr, &b->u.mptr.mptr); + return lfsr_mptr_cmp(a->u.mptr.blocks, b->u.mptr.blocks); } else { return lfsr_btree_cmp(&a->u.btree, &b->u.btree); } @@ -7383,7 +7378,7 @@ static int lfsr_mtree_lookup(lfs_t *lfs, lfsr_smid_t mid, // looking up direct mdir? } else if (lfsr_mtree_ismptr(&lfs->mtree)) { // fetch mdir - return lfsr_mdir_fetch(lfs, mdir_, mid, &lfs->mtree.u.mptr.mptr); + return lfsr_mdir_fetch(lfs, mdir_, mid, lfs->mtree.u.mptr.blocks); // look up mdir in actual mtree } else { @@ -8169,17 +8164,19 @@ relocate:; return 0; } -static int lfsr_mroot_parent(lfs_t *lfs, const lfsr_mptr_t *mptr, +static int lfsr_mroot_parent(lfs_t *lfs, const lfs_block_t mptr[static 2], lfsr_mdir_t *mparent_) { // we only call this when we actually have parents LFS_ASSERT(!lfsr_mptr_ismrootanchor(mptr)); // scan list of mroots for our requested pair - lfsr_mptr_t mptr_ = LFSR_MPTR_MROOTANCHOR(); + lfs_block_t mptr_[2] = { + LFSR_MPTR_MROOTANCHOR()[0], + LFSR_MPTR_MROOTANCHOR()[1]}; while (true) { // fetch next possible superblock lfsr_mdir_t mdir; - int err = lfsr_mdir_fetch(lfs, &mdir, -1, &mptr_); + int err = lfsr_mdir_fetch(lfs, &mdir, -1, mptr_); if (err) { return err; } @@ -8194,13 +8191,13 @@ static int lfsr_mroot_parent(lfs_t *lfs, const lfsr_mptr_t *mptr, } // decode mdir - err = lfsr_data_readmptr(lfs, &data, &mptr_); + err = lfsr_data_readmptr(lfs, &data, mptr_); if (err) { return err; } // found our child? - if (lfsr_mptr_cmp(&mptr_, mptr) == 0) { + if (lfsr_mptr_cmp(mptr_, mptr) == 0) { *mparent_ = mdir; return 0; } @@ -8424,7 +8421,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MDIR, +(1 << lfs->mdir_bits), LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_[0]), + mdir_[0].rbyd.blocks, &mdir_buf[0*LFSR_MPTR_DSIZE])), LFSR_ATTR_CAT_( LFSR_TAG_NAME, +(1 << lfs->mdir_bits), @@ -8432,7 +8429,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_[1]), + mdir_[1].rbyd.blocks, &mdir_buf[1*LFSR_MPTR_DSIZE])))); if (err) { goto failed; @@ -8449,7 +8446,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_[0]), + mdir_[0].rbyd.blocks, &mdir_buf[0*LFSR_MPTR_DSIZE])), LFSR_ATTR_CAT_( LFSR_TAG_NAME, +(1 << lfs->mdir_bits), @@ -8457,7 +8454,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_[1]), + mdir_[1].rbyd.blocks, &mdir_buf[1*LFSR_MPTR_DSIZE])))); if (err) { goto failed; @@ -8510,7 +8507,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // new mtree? if (lfsr_mtree_ismptr(&lfs->mtree)) { mtree_ = LFSR_MTREE_MPTR( - *lfsr_mdir_mptr(&mdir_[0]), + mdir_[0].rbyd.blocks[0], + mdir_[0].rbyd.blocks[1], 1 << lfs->mdir_bits); } else { @@ -8524,7 +8522,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_[0]), + mdir_[0].rbyd.blocks, mdir_buf)))); if (err) { goto failed; @@ -8594,7 +8592,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, (lfsr_mtree_ismptr(&mtree_)) ? LFSR_ATTR( LFSR_TAG_SUB | LFSR_TAG_MDIR, 0, - LFSR_DATA_MPTR_(&mtree_.u.mptr.mptr, mtree_buf)) + LFSR_DATA_MPTR_(mtree_.u.mptr.blocks, mtree_buf)) : LFSR_ATTR( LFSR_TAG_SUB | LFSR_TAG_MTREE, 0, LFSR_DATA_BTREE_(&mtree_.u.btree, mtree_buf)), @@ -8619,7 +8617,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, && !lfsr_mdir_ismrootanchor(&mrootchild)) { // find the mroot's parent lfsr_mdir_t mrootparent_; - err = lfsr_mroot_parent(lfs, lfsr_mdir_mptr(&mrootchild), + err = lfsr_mroot_parent(lfs, mrootchild.rbyd.blocks, &mrootparent_); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); @@ -8647,7 +8645,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MROOT, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mrootchild_), + mrootchild_.rbyd.blocks, mrootchild_buf)))); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -8699,7 +8697,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MROOT, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mrootchild_), + mrootchild_.rbyd.blocks, mrootchild_buf)))); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -8917,7 +8915,7 @@ static int lfsr_mtree_namelookup(lfs_t *lfs, // direct mdir? } else if (lfsr_mtree_ismptr(&lfs->mtree)) { - int err = lfsr_mdir_fetch(lfs, &mdir, 0, &lfs->mtree.u.mptr.mptr); + int err = lfsr_mdir_fetch(lfs, &mdir, 0, lfs->mtree.u.mptr.blocks); if (err) { return err; } @@ -9141,7 +9139,7 @@ enum { .o.o.mdir.rbyd.blocks={-1,-1}, \ .o.bshrub.u.bshrub.blocks={-1}, \ .ot=NULL, \ - .u.mtortoise.mptr={{0, 0}}, \ + .u.mtortoise.blocks={0, 0}, \ .u.mtortoise.step=0, \ .u.mtortoise.power=0}) @@ -9157,7 +9155,7 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, case LFSR_TSTATE_MROOTANCHOR:; // fetch the first mroot 0x{0,1} int err = lfsr_mdir_fetch(lfs, &t->o.o.mdir, - -1, &LFSR_MPTR_MROOTANCHOR()); + -1, LFSR_MPTR_MROOTANCHOR()); if (err) { return err; } @@ -9209,8 +9207,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, // so creating a valid cycle is actually quite difficult // if (lfsr_mptr_cmp( - lfsr_mdir_mptr(&t->o.o.mdir), - &t->u.mtortoise.mptr) == 0) { + t->o.o.mdir.rbyd.blocks, + t->u.mtortoise.blocks) == 0) { LFS_ERROR("Cycle detected during mtree traversal " "0x{%"PRIx32",%"PRIx32"}", t->o.o.mdir.rbyd.blocks[0], @@ -9218,7 +9216,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, return LFS_ERR_CORRUPT; } if (t->u.mtortoise.step == (1U << t->u.mtortoise.power)) { - t->u.mtortoise.mptr = *lfsr_mdir_mptr(&t->o.o.mdir); + t->u.mtortoise.blocks[0] = t->o.o.mdir.rbyd.blocks[0]; + t->u.mtortoise.blocks[1] = t->o.o.mdir.rbyd.blocks[1]; t->u.mtortoise.step = 0; t->u.mtortoise.power += 1; } @@ -13376,7 +13375,8 @@ static int lfsr_mountinited(lfs_t *lfs) { // found a direct mdir? keep track of this if (lfsr_mtree_isnull(&lfs->mtree)) { lfs->mtree = LFSR_MTREE_MPTR( - *lfsr_mdir_mptr(mdir), + mdir->rbyd.blocks[0], + mdir->rbyd.blocks[1], (1 << lfs->mdir_bits)); } } @@ -14288,8 +14288,8 @@ static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t) { t->o.bshrub.u.bshrub.weight = 0; t->o.bshrub.u.bshrub.blocks[0] = -1; t->ot = NULL; - t->u.mtortoise.mptr.blocks[0] = 0; - t->u.mtortoise.mptr.blocks[1] = 0; + t->u.mtortoise.blocks[0] = 0; + t->u.mtortoise.blocks[1] = 0; t->u.mtortoise.step = 0; t->u.mtortoise.power = 0; diff --git a/lfs.h b/lfs.h index ac3fc341..6697fe4d 100644 --- a/lfs.h +++ b/lfs.h @@ -536,10 +536,6 @@ typedef struct { lfs_size_t estimate; } lfsr_shrub_t; -typedef struct lfsr_mptr { - lfs_block_t blocks[2]; -} lfsr_mptr_t; - typedef struct lfsr_mdir { lfsr_smid_t mid; lfsr_rbyd_t rbyd; @@ -706,7 +702,7 @@ typedef struct lfsr_traversal { union { // cycle detection state, only valid when traversing the mroot chain struct { - lfsr_mptr_t mptr; + lfs_block_t blocks[2]; lfs_block_t step; uint8_t power; } mtortoise; @@ -740,7 +736,7 @@ typedef struct lfsr_mtree { lfsr_mid_t weight; struct { lfsr_mid_t weight; - lfsr_mptr_t mptr; + lfs_block_t blocks[2]; } mptr; lfsr_btree_t btree; } u; diff --git a/tests/test_mtree.toml b/tests/test_mtree.toml index 7b370b6d..848d9784 100644 --- a/tests/test_mtree.toml +++ b/tests/test_mtree.toml @@ -4326,7 +4326,7 @@ code = ''' lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR( LFSR_TAG_MROOT, 0, - LFSR_DATA_MPTR(&LFSR_MPTR_MROOTANCHOR())))) => 0; + LFSR_DATA_MPTR(LFSR_MPTR_MROOTANCHOR())))) => 0; // technically, cycle detection only needs to work when we're validating lfsr_traversal_t t = LFSR_TRAVERSAL( diff --git a/tests/test_traversal.toml b/tests/test_traversal.toml index 84bb66c6..c51b4612 100644 --- a/tests/test_traversal.toml +++ b/tests/test_traversal.toml @@ -5429,7 +5429,7 @@ code = ''' // we need internals to check this lfsr_mdir_t mrootanchor; lfsr_mdir_fetch(&lfs, &mrootanchor, - -1, &LFSR_MPTR_MROOTANCHOR()) => 0; + -1, LFSR_MPTR_MROOTANCHOR()) => 0; if (lfsr_rbyd_eoff(&mrootanchor.rbyd) > GC_COMPACT_THRESH) { break; } @@ -5474,7 +5474,7 @@ code = ''' // mrootanchor should have been compacted lfsr_mdir_t mrootanchor; lfsr_mdir_fetch(&lfs, &mrootanchor, - -1, &LFSR_MPTR_MROOTANCHOR()) => 0; + -1, LFSR_MPTR_MROOTANCHOR()) => 0; assert(lfsr_rbyd_eoff(&mrootanchor.rbyd) <= GC_COMPACT_THRESH); // but because we mutated, we're still marked as uncompacted @@ -5496,7 +5496,7 @@ code = ''' // mrootanchor should have been compacted lfsr_mdir_fetch(&lfs, &mrootanchor, - -1, &LFSR_MPTR_MROOTANCHOR()) => 0; + -1, LFSR_MPTR_MROOTANCHOR()) => 0; assert(lfsr_rbyd_eoff(&mrootanchor.rbyd) <= GC_COMPACT_THRESH); // uncompacted flag should have been cleared