Some minor tweaks to internal ptr types

- Renamed mpair -> mptr, may have >2 blocks in the future.

- Renamed branch -> bptr for consistency.

- Renamed other_block -> redund_rbyd.

- Changed comparison functions to use -1, 0, +1, even for unordered
  types.

- Added lfs_cmp function for unioning comparisons with signed errors.
This commit is contained in:
Christopher Haster
2023-06-27 13:15:15 -05:00
parent cf588ac3fa
commit 91d90b7eef
3 changed files with 237 additions and 246 deletions
+190 -199
View File
@@ -9,22 +9,32 @@
#include "lfs_util.h"
// TODO do we still need these?
// some constants used throughout the code
#define LFS_BLOCK_NULL ((lfs_block_t)-1)
#define LFS_BLOCK_INLINE ((lfs_block_t)-2)
// TODO do we still need these?
enum {
LFS_OK_RELOCATED = 1,
LFS_OK_DROPPED = 2,
LFS_OK_ORPHANED = 3,
};
// a normal compare enum, but shifted up by one to allow unioning with
// negative error codes
enum {
LFS_CMP_EQ = 0,
LFS_CMP_LT = 1,
LFS_CMP_LT = 0,
LFS_CMP_EQ = 1,
LFS_CMP_GT = 2,
};
typedef int lfs_scmp_t;
static inline int lfs_cmp(lfs_scmp_t cmp) {
return cmp - 1;
}
/// Caching block device operations ///
@@ -245,14 +255,14 @@ static int lfs_bd_flush(lfs_t *lfs,
if (validate) {
// check data on disk
lfs_cache_drop(lfs, rcache);
int res = lfs_bd_cmp(lfs,
lfs_scmp_t cmp = lfs_bd_cmp(lfs,
NULL, rcache, diff,
pcache->block, pcache->off, pcache->buffer, diff);
if (res < 0) {
return res;
if (cmp < 0) {
return cmp;
}
if (res != LFS_CMP_EQ) {
if (lfs_cmp(cmp) != 0) {
return LFS_ERR_CORRUPT;
}
}
@@ -401,31 +411,16 @@ static int lfsr_bd_csum(lfs_t *lfs,
block, off, size, crc_);
}
static int lfsr_bd_cmp(lfs_t *lfs,
static lfs_scmp_t lfsr_bd_cmp(lfs_t *lfs,
lfs_block_t block, lfs_off_t off, lfs_size_t hint,
const void *buffer, lfs_size_t size,
int *cmp) {
const void *buffer, lfs_size_t size) {
// check for in-bounds
if (off+size > lfs->cfg->block_size) {
return LFS_ERR_RANGE;
}
int res = lfs_bd_cmp(lfs, &lfs->pcache, &lfs->rcache, hint,
return lfs_bd_cmp(lfs, &lfs->pcache, &lfs->rcache, hint,
block, off, buffer, size);
if (res < 0) {
return res;
}
// TODO this should be eventually flattened away
if (res == LFS_CMP_EQ) {
*cmp = 0;
} else if (res == LFS_CMP_LT) {
*cmp = -1;
} else {
*cmp = +1;
}
return 0;
}
// program data with optional checksum
@@ -1040,21 +1035,6 @@ static inline lfs_size_t lfsr_data_setondisk(lfs_size_t size) {
return size | 0x80000000;
}
static lfsr_data_t lfsr_data_add(lfsr_data_t data, lfs_off_t off) {
// limit our off to data range
lfs_off_t off_ = lfs_min32(off, lfsr_data_size(data));
if (lfsr_data_ondisk(data)) {
data.disk.off += off_;
data.disk.size -= off_;
} else {
data.buf.buffer += off_;
data.buf.size -= off_;
}
return data;
}
// data<->bd interactions
static lfs_ssize_t lfsr_data_read(lfs_t *lfs, lfsr_data_t data,
lfs_off_t off, void *buffer, lfs_size_t size) {
@@ -1106,35 +1086,32 @@ static lfs_ssize_t lfsr_data_readleb128(lfs_t *lfs, lfsr_data_t data,
return lfs_fromleb128(word, buf, d);
}
// TODO really should we bring back GT/EQ/LT as return values here?
static int lfsr_data_cmp(lfs_t *lfs, lfsr_data_t data,
lfs_off_t off, const void *buffer, lfs_size_t size,
int *cmp) {
static lfs_scmp_t lfsr_data_cmp(lfs_t *lfs, lfsr_data_t data,
lfs_off_t off, const void *buffer, lfs_size_t size) {
// limit our off/size to data range
lfs_off_t off_ = lfs_min32(off, lfsr_data_size(data));
lfs_size_t hint_ = lfsr_data_size(data)-off_;
// return early if our size doesn't match
if (hint_ < size) {
*cmp = -1;
return 0;
return LFS_CMP_LT;
} else if (hint_ > size) {
*cmp = +1;
return 0;
return LFS_CMP_GT;
}
if (lfsr_data_ondisk(data)) {
int err = lfsr_bd_cmp(lfs, data.disk.block, data.disk.off+off_, 0,
buffer, size,
cmp);
if (err) {
return err;
}
return lfsr_bd_cmp(lfs, data.disk.block, data.disk.off+off_, 0,
buffer, size);
} else {
*cmp = memcmp(data.buf.buffer+off_, buffer, size);
int cmp = memcmp(data.buf.buffer+off_, buffer, size);
if (cmp < 0) {
return LFS_CMP_LT;
} else if (cmp == 0) {
return LFS_CMP_EQ;
} else {
return LFS_CMP_GT;
}
}
return 0;
}
static lfs_ssize_t lfsr_bd_progdata(lfs_t *lfs,
@@ -3197,24 +3174,24 @@ static int lfsr_rbyd_namelookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
}
// if we have no name or a vestigial name, treat this id as always lt
int cmp;
lfs_scmp_t cmp;
if (id__-(weight__-1) == 0
|| lfsr_tag_suptype(tag__) != LFSR_TAG_NAME) {
cmp = -1;
cmp = LFS_CMP_LT;
// compare names
} else {
err = lfsr_data_cmp(lfs, data__, 0, name, name_size, &cmp);
if (err) {
return err;
cmp = lfsr_data_cmp(lfs, data__, 0, name, name_size);
if (cmp < 0) {
return cmp;
}
}
// bisect search space
if (cmp > 0) {
if (lfs_cmp(cmp) > 0) {
upper = id__-weight__ + 1;
} else if (cmp < 0) {
} else if (lfs_cmp(cmp) < 0) {
lower = id__ + 1;
// keep track of best-matching name so far
@@ -3280,32 +3257,32 @@ static inline lfs_size_t lfsr_btree_setinlined(lfs_size_t weight) {
}
// branch on-disk encoding
// bptr on-disk encoding
// 1 crc32c + 3 leb128 => 19 bytes (worst case)
#define LFSR_BRANCH_DSIZE (4+5+5+5)
#define LFSR_BPTR_DSIZE (4+5+5+5)
static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch,
uint8_t buffer[static LFSR_BRANCH_DSIZE]) {
static lfs_ssize_t lfsr_bptr_todisk(lfs_t *lfs, const lfsr_rbyd_t *bptr,
uint8_t buffer[static LFSR_BPTR_DSIZE]) {
(void)lfs;
lfs_ssize_t d = 0;
lfs_tole32_(branch->crc, &buffer[d]);
lfs_tole32_(bptr->crc, &buffer[d]);
d += 4;
lfs_ssize_t d_ = lfs_toleb128(branch->weight, &buffer[d], 5);
lfs_ssize_t d_ = lfs_toleb128(bptr->weight, &buffer[d], 5);
if (d_ < 0) {
return d_;
}
d += d_;
d_ = lfs_toleb128(branch->trunk, &buffer[d], 5);
d_ = lfs_toleb128(bptr->trunk, &buffer[d], 5);
if (d_ < 0) {
return d_;
}
d += d_;
d_ = lfs_toleb128(branch->block, &buffer[d], 5);
d_ = lfs_toleb128(bptr->block, &buffer[d], 5);
if (d_ < 0) {
return d_;
}
@@ -3314,32 +3291,32 @@ static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch,
return d;
}
static lfs_ssize_t lfsr_branch_fromdisk(lfs_t *lfs, lfsr_rbyd_t *branch,
static lfs_ssize_t lfsr_bptr_fromdisk(lfs_t *lfs, lfsr_rbyd_t *bptr,
lfsr_data_t data) {
// setting off to 0 here will trigger asserts if we try to append
// without fetching first
branch->off = 0;
bptr->off = 0;
lfs_ssize_t d = 0;
lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &branch->crc);
lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &bptr->crc);
if (d_ < 0) {
return d_;
}
d += d_;
d_ = lfsr_data_readleb128(lfs, data, d, &branch->weight);
d_ = lfsr_data_readleb128(lfs, data, d, &bptr->weight);
if (d_ < 0) {
return d_;
}
d += d_;
d_ = lfsr_data_readleb128(lfs, data, d, &branch->trunk);
d_ = lfsr_data_readleb128(lfs, data, d, &bptr->trunk);
if (d_ < 0) {
return d_;
}
d += d_;
d_ = lfsr_data_readleb128(lfs, data, d, &branch->block);
d_ = lfsr_data_readleb128(lfs, data, d, &bptr->block);
if (d_ < 0) {
return d_;
}
@@ -3352,8 +3329,8 @@ static lfs_ssize_t lfsr_branch_fromdisk(lfs_t *lfs, lfsr_rbyd_t *branch,
//
// note we leave disambiguating inlined/non-inlined btrees up to the caller
#define LFSR_BTREE_DSIZE ( \
LFSR_BRANCH_DSIZE > LFSR_BTREE_INLINESIZE \
? LFSR_BRANCH_DSIZE \
LFSR_BPTR_DSIZE > LFSR_BTREE_INLINESIZE \
? LFSR_BPTR_DSIZE \
: LFSR_BTREE_INLINESIZE)
static lfs_ssize_t lfsr_btree_todisk(lfs_t *lfs, const lfsr_btree_t *btree,
@@ -3371,7 +3348,7 @@ static lfs_ssize_t lfsr_btree_todisk(lfs_t *lfs, const lfsr_btree_t *btree,
// not inlined
} else {
*tag_ = lfsr_tag_setwide(btree_tag);
return lfsr_branch_todisk(lfs, &btree->root, buffer);
return lfsr_bptr_todisk(lfs, &btree->root, buffer);
}
}
@@ -3393,7 +3370,7 @@ static lfs_ssize_t lfsr_btree_fromdisk(lfs_t *lfs, lfsr_btree_t *btree,
// not inlined
} else {
return lfsr_branch_fromdisk(lfs, &btree->root, data);
return lfsr_bptr_fromdisk(lfs, &btree->root, data);
}
}
@@ -3461,7 +3438,7 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs,
rid -= (rid__ - (weight__-1));
// fetch the next branch
lfs_ssize_t d = lfsr_branch_fromdisk(lfs, &branch, data__);
lfs_ssize_t d = lfsr_bptr_fromdisk(lfs, &branch, data__);
if (d < 0) {
return d;
}
@@ -3586,7 +3563,7 @@ static int lfsr_btree_parent(lfs_t *lfs,
// fetch the next branch
lfsr_rbyd_t branch_;
lfs_ssize_t d = lfsr_branch_fromdisk(lfs, &branch_, data__);
lfs_ssize_t d = lfsr_bptr_fromdisk(lfs, &branch_, data__);
if (d < 0) {
return d;
}
@@ -3664,7 +3641,7 @@ static lfs_ssize_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
bid += rid__ - (weight__-1);
// fetch the next branch
lfs_ssize_t d = lfsr_branch_fromdisk(lfs, &branch, data__);
lfs_ssize_t d = lfsr_bptr_fromdisk(lfs, &branch, data__);
if (d < 0) {
return d;
}
@@ -3698,7 +3675,7 @@ static lfs_ssize_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
// array allocations
#define LFSR_BTREE_SCRATCHATTRS ( \
4 \
+ ((2*LFSR_BRANCH_DSIZE) + sizeof(lfsr_attr_t)-1) \
+ ((2*LFSR_BPTR_DSIZE) + sizeof(lfsr_attr_t)-1) \
/ sizeof(lfsr_attr_t))
// this macro creates an attr list with enough reserved space for
@@ -3770,7 +3747,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
// cannibalize some attributes in our attr list to store
// our branch
uint8_t *scratch_buf = (uint8_t*)&attrs[2];
lfs_ssize_t d = lfsr_branch_todisk(lfs, rbyd, scratch_buf);
lfs_ssize_t d = lfsr_bptr_todisk(lfs, rbyd, scratch_buf);
if (d < 0) {
return d;
}
@@ -3882,7 +3859,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
// cannibalize some attributes in our attr list to store
// our branch
scratch_buf = (uint8_t*)&attrs[2];
d = lfsr_branch_todisk(lfs, rbyd, scratch_buf);
d = lfsr_bptr_todisk(lfs, rbyd, scratch_buf);
if (d < 0) {
return d;
}
@@ -3990,12 +3967,12 @@ static int lfsr_btree_commit(lfs_t *lfs,
// cannibalize some attributes in our attr list to store
// our branches
uint8_t *scratch_buf1 = (uint8_t*)&attrs[4];
uint8_t *scratch_buf2 = (uint8_t*)&attrs[4] + LFSR_BRANCH_DSIZE;
lfs_ssize_t d1 = lfsr_branch_todisk(lfs, &rbyd_, scratch_buf1);
uint8_t *scratch_buf2 = (uint8_t*)&attrs[4] + LFSR_BPTR_DSIZE;
lfs_ssize_t d1 = lfsr_bptr_todisk(lfs, &rbyd_, scratch_buf1);
if (d1 < 0) {
return d1;
}
lfs_ssize_t d2 = lfsr_branch_todisk(lfs, &sibling, scratch_buf2);
lfs_ssize_t d2 = lfsr_bptr_todisk(lfs, &sibling, scratch_buf2);
if (d2 < 0) {
return d2;
}
@@ -4115,7 +4092,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
continue;
}
d = lfsr_branch_fromdisk(lfs, &sibling, sdata);
d = lfsr_bptr_fromdisk(lfs, &sibling, sdata);
if (d < 0) {
return d;
}
@@ -4236,7 +4213,7 @@ static int lfsr_btree_commit(lfs_t *lfs,
// cannibalize some attributes in our attr list to store
// our branch
uint8_t *scratch_buf = (uint8_t*)&attrs[3];
lfs_ssize_t d = lfsr_branch_todisk(lfs, &rbyd_, scratch_buf);
lfs_ssize_t d = lfsr_bptr_todisk(lfs, &rbyd_, scratch_buf);
if (d < 0) {
return d;
}
@@ -4690,7 +4667,7 @@ static int lfsr_btree_traversal_next(lfs_t *lfs,
traversal->rid -= (rid__ - (weight__-1));
// fetch the next branch
lfs_ssize_t d = lfsr_branch_fromdisk(lfs,
lfs_ssize_t d = lfsr_bptr_fromdisk(lfs,
&traversal->branch, data__);
if (d < 0) {
return d;
@@ -4751,33 +4728,45 @@ static int lfsr_btree_traversal_next(lfs_t *lfs,
// special mid values
enum {
LFSR_MID_MANCHOR = -4,
LFSR_MID_WL = -3,
LFSR_MID_RM = -2,
LFSR_MID_MROOT = -1,
LFSR_MID_MROOTANCHOR = -4,
LFSR_MID_WL = -3,
LFSR_MID_RM = -2,
LFSR_MID_MROOT = -1,
};
typedef struct lfsr_mpair {
// mptr things
typedef struct lfsr_mptr {
lfs_block_t blocks[2];
} lfsr_mpair_t;
} lfsr_mptr_t;
#define LFSR_MPAIR(block0, block1) ((lfsr_mpair_t){.blocks={block0, block1}})
#define LFSR_MPTR(block0, block1) ((lfsr_mptr_t){.blocks={block0, block1}})
static inline bool lfsr_mpair_eq(lfsr_mpair_t a, lfsr_mpair_t b) {
// the mroot anchor, mdir 0x{0,1} is the entry point into the filesystem
#define LFSR_MPTR_MROOTANCHOR LFSR_MPTR(0, 1)
static inline int lfsr_mptr_cmp(lfsr_mptr_t a, lfsr_mptr_t b) {
// allow either order
return (a.blocks[0] == b.blocks[0] && a.blocks[1] == b.blocks[1])
|| (a.blocks[0] == b.blocks[1] && a.blocks[1] == b.blocks[0]);
if ((a.blocks[0] == b.blocks[0] && a.blocks[1] == b.blocks[1])
|| (a.blocks[0] == b.blocks[1] && a.blocks[1] == b.blocks[0])) {
return 0;
} else {
return 1;
}
}
static inline bool lfsr_mptr_ismrootanchor(lfsr_mptr_t a) {
return lfsr_mptr_cmp(a, LFSR_MPTR_MROOTANCHOR) == 0;
}
// 2 leb128 => 10 bytes (worst case)
#define LFSR_MPAIR_DSIZE (5+5)
#define LFSR_MPTR_DSIZE (5+5)
static lfs_ssize_t lfsr_mpair_todisk(lfs_t *lfs, lfsr_mpair_t mpair,
uint8_t buffer[static LFSR_MPAIR_DSIZE]) {
static lfs_ssize_t lfsr_mptr_todisk(lfs_t *lfs, lfsr_mptr_t mptr,
uint8_t buffer[static LFSR_MPTR_DSIZE]) {
(void)lfs;
lfs_ssize_t d = 0;
for (int i = 0; i < 2; i++) {
lfs_ssize_t d_ = lfs_toleb128(mpair.blocks[i], &buffer[d], 5);
lfs_ssize_t d_ = lfs_toleb128(mptr.blocks[i], &buffer[d], 5);
if (d_ < 0) {
return d_;
}
@@ -4787,12 +4776,11 @@ static lfs_ssize_t lfsr_mpair_todisk(lfs_t *lfs, lfsr_mpair_t mpair,
return d;
}
// TODO should our fromdisk functions accept an lfsr_data_t?
static lfs_ssize_t lfsr_mpair_fromdisk(lfs_t *lfs, lfsr_mpair_t *mpair,
static lfs_ssize_t lfsr_mptr_fromdisk(lfs_t *lfs, lfsr_mptr_t *mptr,
lfsr_data_t data) {
lfs_ssize_t d = 0;
for (int i = 0; i < 2; i++) {
lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &mpair->blocks[i]);
lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &mptr->blocks[i]);
if (d_ < 0) {
return d_;
}
@@ -4802,19 +4790,24 @@ static lfs_ssize_t lfsr_mpair_fromdisk(lfs_t *lfs, lfsr_mpair_t *mpair,
return d;
}
static inline lfsr_mpair_t lfsr_mdir_mpair(const lfsr_mdir_t *mdir) {
return LFSR_MPAIR(mdir->rbyd.block, mdir->other_block);
// mdir things
static inline lfsr_mptr_t lfsr_mdir_mptr(const lfsr_mdir_t *mdir) {
return LFSR_MPTR(mdir->rbyd.block, mdir->redund_block);
}
#define LFSR_MDIR_NULL ((lfsr_mdir_t){.mid=-3, .rbyd.weight=0})
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));
}
static inline bool lfsr_mdir_eq(const lfsr_mdir_t *a, const lfsr_mdir_t *b) {
return lfsr_mpair_eq(lfsr_mdir_mpair(a), lfsr_mdir_mpair(b));
static inline bool lfsr_mdir_ismrootanchor(const lfsr_mdir_t *a) {
// mrootanchor is always at 0x{0,1}
// just check that at least one block is at 0x0
return a->rbyd.block == 0 || a->redund_block == 0;
}
static lfs_ssize_t lfsr_mdir_todisk(lfs_t *lfs, const lfsr_mdir_t *mdir,
uint8_t buffer[static LFSR_MPAIR_DSIZE]) {
return lfsr_mpair_todisk(lfs, lfsr_mdir_mpair(mdir), buffer);
uint8_t buffer[static LFSR_MPTR_DSIZE]) {
return lfsr_mptr_todisk(lfs, lfsr_mdir_mptr(mdir), buffer);
}
static inline lfs_size_t lfsr_mdir_weight(const lfsr_mdir_t *mdir) {
@@ -4879,7 +4872,7 @@ static int lfsr_mdir_alloc(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t mid) {
// setup mdir struct
mdir->mid = mid;
mdir->other_block = blocks[0];
mdir->redund_block = blocks[0];
mdir->rbyd.weight = 0;
mdir->rbyd.block = blocks[1];
// mark mdir as needing compaction
@@ -4889,12 +4882,12 @@ static int lfsr_mdir_alloc(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t mid) {
}
static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir,
lfs_ssize_t mid, lfsr_mpair_t mpair) {
lfs_ssize_t mid, lfsr_mptr_t mptr) {
// 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, mpair.blocks[0], 0, 0,
int err = lfsr_bd_read(lfs, mptr.blocks[0], 0, 0,
&revs[0], sizeof(uint32_t));
if (err && err != LFS_ERR_CORRUPT) {
return err;
@@ -4904,14 +4897,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_swap32(&mpair.blocks[0], &mpair.blocks[1]);
lfs_swap32(&mptr.blocks[0], &mptr.blocks[1]);
lfs_swap32(&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, mpair.blocks[0], 0);
int err = lfsr_rbyd_fetch(lfs, &mdir->rbyd, mptr.blocks[0], 0);
if (err && err != LFS_ERR_CORRUPT) {
return err;
}
@@ -4919,11 +4912,11 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir,
if (!err) {
mdir->mid = mid;
// keep track of other block for compactions
mdir->other_block = mpair.blocks[1];
mdir->redund_block = mptr.blocks[1];
return 0;
}
lfs_swap32(&mpair.blocks[0], &mpair.blocks[1]);
lfs_swap32(&mptr.blocks[0], &mptr.blocks[1]);
lfs_swap32(&revs[0], &revs[1]);
}
@@ -4984,31 +4977,31 @@ static int lfsr_mtree_lookup(lfs_t *lfs, lfs_ssize_t mid, lfsr_mdir_t *mdir_) {
}
LFS_ASSERT(tag == LFSR_TAG_MDIR);
// decode mpair
lfsr_mpair_t mpair;
lfs_ssize_t d = lfsr_mpair_fromdisk(lfs, &mpair, data);
// decode mptr
lfsr_mptr_t mptr;
lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data);
if (d < 0) {
return d;
}
// fetch mdir
return lfsr_mdir_fetch(lfs, mdir_, mid, mpair);
return lfsr_mdir_fetch(lfs, mdir_, mid, mptr);
}
}
static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mpair_t child,
lfsr_mdir_t *parent_) {
// if mpair is our initial 0x{0,1} blocks, we have no parent
if (lfsr_mpair_eq(child, LFSR_MPAIR(0, 1))) {
static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mptr_t mchild,
lfsr_mdir_t *mparent_) {
// if mptr is our initial 0x{0,1} blocks, we have no parent
if (lfsr_mptr_ismrootanchor(mchild)) {
return LFS_ERR_NOENT;
}
// scan list of mroots for our requested pair
lfsr_mpair_t mpair = LFSR_MPAIR(0, 1);
lfsr_mptr_t mptr = LFSR_MPTR_MROOTANCHOR;
lfsr_mdir_t mdir;
while (true) {
// fetch next possible superblock
int err = lfsr_mdir_fetch(lfs, &mdir, LFSR_MID_MROOT, mpair);
int err = lfsr_mdir_fetch(lfs, &mdir, LFSR_MID_MROOT, mptr);
if (err) {
return err;
}
@@ -5021,16 +5014,16 @@ static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mpair_t child,
return err;
}
// decode mpair
lfsr_mpair_t mpair;
lfs_ssize_t d = lfsr_mpair_fromdisk(lfs, &mpair, data);
// decode mptr
lfsr_mptr_t mptr;
lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data);
if (d < 0) {
return d;
}
// found our child?
if (lfsr_mpair_eq(mpair, child)) {
*parent_ = mdir;
if (lfsr_mptr_cmp(mptr, mchild) == 0) {
*mparent_ = mdir;
return 0;
}
}
@@ -5044,9 +5037,9 @@ 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) {
// 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)
// - 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
uint32_t rev;
@@ -5059,7 +5052,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
rev = (err != LFS_ERR_CORRUPT ? lfs_fromle32_(&rev) : 0);
// decide if we need to relocate
if (mid != LFSR_MID_MANCHOR && (mid != LFSR_MID_WL || (
if (mid != LFSR_MID_MROOTANCHOR && (mid != LFSR_MID_WL || (
lfs->cfg->block_cycles > 0
// TODO rev things
&& (rev + 1) % lfs->cfg->block_cycles == 0))) {
@@ -5084,7 +5077,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir,
}
// swap our rbyds
lfs_swap32(&mdir->rbyd.block, &mdir->other_block);
lfs_swap32(&mdir->rbyd.block, &mdir->redund_block);
// update our revision count
mdir->rbyd.off = 0;
mdir->rbyd.trunk = 0;
@@ -5260,9 +5253,9 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree,
LFS_DEBUG("Splitting mdir 0x{%"PRIx32",%"PRIx32"} "
"-> 0x{%"PRIx32",%"PRIx32"}"
", 0x{%"PRIx32",%"PRIx32"}",
msource->rbyd.block, msource->other_block,
mdir->rbyd.block, mdir->other_block,
msibling->rbyd.block, msibling->other_block);
msource->rbyd.block, msource->redund_block,
mdir->rbyd.block, mdir->redund_block,
msibling->rbyd.block, msibling->redund_block);
// because of defered commits, both children can still be reduced
// to zero, need to catch this here
@@ -5282,12 +5275,12 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree,
return err;
}
uint8_t buf1[LFSR_MPAIR_DSIZE];
uint8_t buf1[LFSR_MPTR_DSIZE];
lfs_ssize_t d1 = lfsr_mdir_todisk(lfs, mdir, buf1);
if (d1 < 0) {
return d1;
}
uint8_t buf2[LFSR_MPAIR_DSIZE];
uint8_t buf2[LFSR_MPTR_DSIZE];
lfs_ssize_t d2 = lfsr_mdir_todisk(lfs, msibling, buf2);
if (d2 < 0) {
return d2;
@@ -5306,10 +5299,10 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree,
// one sibling reduced to zero
} else if (mdir->rbyd.weight > 0) {
LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// update our mtree
uint8_t buf[LFSR_MPAIR_DSIZE];
uint8_t buf[LFSR_MPTR_DSIZE];
lfs_ssize_t d = lfsr_mdir_todisk(lfs, mdir, buf);
if (d < 0) {
return d;
@@ -5324,10 +5317,10 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree,
// other sibling reduced to zero
} else if (msibling->rbyd.weight > 0) {
LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}",
msibling->rbyd.block, msibling->other_block);
msibling->rbyd.block, msibling->redund_block);
// update our mtree
uint8_t buf[LFSR_MPAIR_DSIZE];
uint8_t buf[LFSR_MPTR_DSIZE];
lfs_ssize_t d = lfsr_mdir_todisk(lfs, msibling, buf);
if (d < 0) {
return d;
@@ -5342,9 +5335,9 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree,
// both siblings reduced to zero
} else {
LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}",
msibling->rbyd.block, msibling->other_block);
msibling->rbyd.block, msibling->redund_block);
// update our mtree
err = lfsr_btree_pop(lfs, mtree, mid);
@@ -5371,7 +5364,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
// handle possible mtree updates, this gets a bit messy
lfsr_mdir_t mroot_ = lfs->mroot;
lfsr_btree_t mtree_ = lfs->mtree;
lfsr_mdir_t msibling_ = LFSR_MDIR_NULL;
lfsr_mdir_t msibling_;
bool dirtymroot = false;
bool dirtymtree = false;
@@ -5409,15 +5402,15 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
LFS_DEBUG("Uninlining mdir 0x{%"PRIx32",%"PRIx32"} "
"-> 0x{%"PRIx32",%"PRIx32"}"
", 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.block, mdir->other_block,
mdir->rbyd.block, mdir->other_block,
mdir_.rbyd.block, mdir_.other_block);
mdir->rbyd.block, mdir->redund_block,
mdir->rbyd.block, mdir->redund_block,
mdir_.rbyd.block, mdir_.redund_block);
// because of defered commits, our child can still be
// reduced to zero, need to catch this here
if (mdir_.rbyd.weight > 0) {
// update our mtree
uint8_t buf[LFSR_MPAIR_DSIZE];
uint8_t buf[LFSR_MPTR_DSIZE];
lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mdir_, buf);
if (d < 0) {
return d;
@@ -5431,7 +5424,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
} else {
LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}",
mdir_.rbyd.block, mdir_.other_block);
mdir_.rbyd.block, mdir_.redund_block);
// don't really need to update our mtree here
}
@@ -5439,7 +5432,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
// uninlining and splitting
} else {
LFS_DEBUG("Uninlining mdir 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// let lfsr_mtree_split_ do most of the work
int err = lfsr_mtree_split_(lfs, &mtree_,
@@ -5468,7 +5461,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
return err;
}
dirtymroot = !lfsr_mdir_eq(&lfs->mroot, &mroot_);
dirtymroot = (lfsr_mdir_cmp(&lfs->mroot, &mroot_) != 0);
// splitting a normal mdir
} else {
@@ -5487,7 +5480,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 != LFSR_MID_MROOT && mdir_.rbyd.weight == 0) {
LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// update our mtree
err = lfsr_btree_pop(lfs, &mtree_, mdir->mid);
@@ -5498,7 +5491,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
dirtymtree = true;
// need to relocate?
} else if (!lfsr_mdir_eq(mdir, &mdir_)) {
} else if (lfsr_mdir_cmp(mdir, &mdir_) != 0) {
// relocate mroot
if (mdir->mid == LFSR_MID_MROOT) {
mroot_ = mdir_;
@@ -5508,11 +5501,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
} else {
LFS_DEBUG("Relocating mdir 0x{%"PRIx32",%"PRIx32"} "
"-> 0x{%"PRIx32",%"PRIx32"}",
mdir->rbyd.block, mdir->other_block,
mdir_.rbyd.block, mdir_.other_block);
mdir->rbyd.block, mdir->redund_block,
mdir_.rbyd.block, mdir_.redund_block);
// update our mtree
uint8_t buf[LFSR_MPAIR_DSIZE];
uint8_t buf[LFSR_MPTR_DSIZE];
lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mdir_, buf);
if (d < 0) {
return d;
@@ -5552,7 +5545,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
return err;
}
dirtymroot = !lfsr_mdir_eq(&lfs->mroot, &mroot_);
dirtymroot = (lfsr_mdir_cmp(&lfs->mroot, &mroot_) != 0);
}
// need to update mroot? tail recurse, updating mroots until a commit sticks
@@ -5560,7 +5553,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
lfsr_mdir_t mchildroot_ = mroot_;
while (dirtymroot) {
lfsr_mdir_t mparentroot;
int err = lfsr_mtree_parent(lfs, lfsr_mdir_mpair(&mchildroot),
int err = lfsr_mtree_parent(lfs, lfsr_mdir_mptr(&mchildroot),
&mparentroot);
if (err && err != LFS_ERR_NOENT) {
return err;
@@ -5571,11 +5564,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
LFS_DEBUG("Relocating mroot 0x{%"PRIx32",%"PRIx32"} "
"-> 0x{%"PRIx32",%"PRIx32"}",
mchildroot.rbyd.block, mchildroot.other_block,
mchildroot_.rbyd.block, mchildroot_.other_block);
mchildroot.rbyd.block, mchildroot.redund_block,
mchildroot_.rbyd.block, mchildroot_.redund_block);
// commit mrootchild
uint8_t buf[LFSR_MPAIR_DSIZE];
uint8_t buf[LFSR_MPTR_DSIZE];
lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mchildroot_, buf);
if (d < 0) {
return d;
@@ -5591,22 +5584,20 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
mchildroot = mparentroot;
mchildroot_ = mparentroot_;
dirtymroot = !lfsr_mdir_eq(&mchildroot, &mchildroot_);
dirtymroot = (lfsr_mdir_cmp(&mchildroot, &mchildroot_) != 0);
}
// uh oh, we ran out of mrootparents, need to extend mroot chain
if (dirtymroot) {
// mchildroot should be our initial mroot at this point
LFS_ASSERT(lfsr_mpair_eq(
lfsr_mdir_mpair(&mchildroot),
LFSR_MPAIR(0, 1)));
LFS_ASSERT(lfsr_mdir_ismrootanchor(&mchildroot));
LFS_DEBUG("Extending mroot 0x{%"PRIx32",%"PRIx32"}"
" -> 0x{%"PRIx32",%"PRIx32"}"
", 0x{%"PRIx32",%"PRIx32"}",
mchildroot.rbyd.block, mchildroot.other_block,
mchildroot.other_block, mchildroot.rbyd.block,
mchildroot_.rbyd.block, mchildroot_.other_block);
mchildroot.rbyd.block, mchildroot.redund_block,
mchildroot.redund_block, mchildroot.rbyd.block,
mchildroot_.rbyd.block, mchildroot_.redund_block);
// copy magic/config from current mroot
lfsr_data_t magic;
@@ -5624,7 +5615,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
}
// commit mrootchild
uint8_t buf[LFSR_MPAIR_DSIZE];
uint8_t buf[LFSR_MPTR_DSIZE];
lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mchildroot_, buf);
if (d < 0) {
return d;
@@ -5632,7 +5623,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid,
// compact into mparentroot, this should stay our mroot anchor
lfsr_mdir_t mparentroot_ = mchildroot;
err = lfsr_mdir_compact_(lfs, &mparentroot_, LFSR_MID_MANCHOR, 0, 0,
err = lfsr_mdir_compact_(lfs, &mparentroot_, LFSR_MID_MROOTANCHOR, 0, 0,
&mchildroot, NULL, 0, LFSR_ATTRS(
LFSR_ATTR_DATA(-1, SUPERMAGIC, 0, magic),
LFSR_ATTR_DATA(-1, SUPERCONFIG, 0, config),
@@ -5709,7 +5700,7 @@ typedef struct lfsr_mtree_traversal {
// cycle detection state
uint8_t tortoise_power;
lfs_size_t tortoise_step;
lfsr_mpair_t tortoise_mpair;
lfsr_mptr_t tortoise_mptr;
} lfsr_mtree_traversal_t;
enum {
@@ -5734,7 +5725,7 @@ 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,
LFSR_MID_MROOT, LFSR_MPAIR(0, 1));
LFSR_MID_MROOT, LFSR_MPTR_MROOTANCHOR);
if (err) {
return err;
}
@@ -5764,14 +5755,14 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
// found a new mroot
if (err != LFS_ERR_NOENT && tag == LFSR_TAG_MROOT) {
lfsr_mpair_t mpair;
lfs_ssize_t d = lfsr_mpair_fromdisk(lfs, &mpair, data);
lfsr_mptr_t mptr;
lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data);
if (d < 0) {
return d;
}
int err = lfsr_mdir_fetch(lfs, &traversal->mdir,
LFSR_MID_MROOT, mpair);
LFSR_MID_MROOT, mptr);
if (err) {
return err;
}
@@ -5883,13 +5874,13 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs,
// fetch mdir if we're on a leaf
} else if (tag == LFSR_TAG_MDIR) {
lfsr_mpair_t mpair;
lfs_ssize_t d = lfsr_mpair_fromdisk(lfs, &mpair, data);
lfsr_mptr_t mptr;
lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data);
if (d < 0) {
return d;
}
int err = lfsr_mdir_fetch(lfs, &traversal->mdir, mid, mpair);
int err = lfsr_mdir_fetch(lfs, &traversal->mdir, mid, mptr);
if (err) {
return err;
}
@@ -5917,16 +5908,17 @@ cycle_detect:;
// require checksums of their pointers, so creating a valid
// cycle is actually quite difficult
//
if (lfsr_mpair_eq(lfsr_mdir_mpair(&traversal->mdir),
traversal->tortoise_mpair)) {
if (lfsr_mptr_cmp(
lfsr_mdir_mptr(&traversal->mdir),
traversal->tortoise_mptr) == 0) {
LFS_ERROR("Cycle detected during mtree traversal "
"(0x{%"PRIx32",%"PRIx32"})",
traversal->mdir.rbyd.block, traversal->mdir.other_block);
traversal->mdir.rbyd.block, traversal->mdir.redund_block);
return LFS_ERR_CORRUPT;
}
if (traversal->tortoise_step
== ((lfs_size_t)1 << traversal->tortoise_power)) {
traversal->tortoise_mpair = lfsr_mdir_mpair(&traversal->mdir);
traversal->tortoise_mptr = lfsr_mdir_mptr(&traversal->mdir);
traversal->tortoise_step = 0;
traversal->tortoise_power += 1;
}
@@ -6060,14 +6052,13 @@ static int lfsr_mountinited(lfs_t *lfs) {
}
if (err != LFS_ERR_NOENT) {
int cmp;
err = lfsr_data_cmp(lfs, data, 0, "littlefs", 8, &cmp);
if (err) {
return err;
lfs_scmp_t cmp = lfsr_data_cmp(lfs, data, 0, "littlefs", 8);
if (cmp < 0) {
return cmp;
}
// treat corrupted magic as no magic
if (cmp != 0) {
if (lfs_cmp(cmp) != 0) {
err = LFS_ERR_NOENT;
}
}
+1 -1
View File
@@ -374,8 +374,8 @@ typedef struct lfsr_mdir {
// -1 => mroot
// >=0 => bid in the mtree
lfs_ssize_t mid;
lfs_block_t other_block;
lfsr_rbyd_t rbyd;
lfs_block_t redund_block;
} lfsr_mdir_t;
typedef struct lfsr_openedmdir {
+46 -46
View File
@@ -1557,7 +1557,7 @@ code = '''
LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -1584,7 +1584,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -1648,7 +1648,7 @@ code = '''
LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert that our entries are still in the mtree
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
@@ -1675,7 +1675,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert that our entries are still in the mtree
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
@@ -1739,7 +1739,7 @@ code = '''
LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert that our entries are still in the mtree
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
@@ -1766,7 +1766,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert that our entries are still in the mtree
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
@@ -1813,7 +1813,7 @@ code = '''
LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -1827,7 +1827,7 @@ code = '''
lfsr_mount(&lfs, cfg) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -1871,7 +1871,7 @@ code = '''
LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -1885,7 +1885,7 @@ code = '''
lfsr_mount(&lfs, cfg) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -1922,7 +1922,7 @@ code = '''
lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, NULL, 0) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// force mroot to compact twice again, this should relocate the mroot
old_mroot = lfs.mroot;
@@ -1935,7 +1935,7 @@ code = '''
LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -1949,7 +1949,7 @@ code = '''
lfsr_mount(&lfs, cfg) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2011,10 +2011,10 @@ code = '''
LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0;
// assert we relocated our mdir
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2041,10 +2041,10 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mdir
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2117,7 +2117,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2149,7 +2149,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2222,7 +2222,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2241,7 +2241,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2290,7 +2290,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2318,7 +2318,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -2374,7 +2374,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our entries are still in the mtree
lfsr_mdir_t mdir;
@@ -2402,7 +2402,7 @@ code = '''
assert(lfs.mroot.rbyd.weight == 0);
// assert we relocated our mroot
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our entries are still in the mtree
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
@@ -2966,7 +2966,7 @@ code = '''
LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -3045,7 +3045,7 @@ code = '''
LFSR_ATTR(1, INLINED, 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mdir, &mdir));
assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -3133,11 +3133,11 @@ code = '''
printf("traversal: %d 0x%x mdir 0x{%x,%x}\n",
mid_,
tag_,
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// keep track of seen blocks
seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8);
seen[mdir->other_block / 8] |= 1 << (mdir->other_block % 8);
seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8);
} else {
// this shouldn't happen
printf("traversal: %d 0x%x %d\n",
@@ -3251,11 +3251,11 @@ code = '''
printf("traversal: %d 0x%x mdir 0x{%x,%x}\n",
mid_,
tag_,
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// keep track of seen blocks
seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8);
seen[mdir->other_block / 8] |= 1 << (mdir->other_block % 8);
seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8);
} else {
// this shouldn't happen
printf("traversal: %d 0x%x %d\n",
@@ -3380,11 +3380,11 @@ code = '''
printf("traversal: %d 0x%x mdir 0x{%x,%x}\n",
mid_,
tag_,
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// keep track of seen blocks
seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8);
seen[mdir->other_block / 8] |= 1 << (mdir->other_block % 8);
seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8);
} else {
// this shouldn't happen
printf("traversal: %d 0x%x %d\n",
@@ -3459,7 +3459,7 @@ code = '''
LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -3501,11 +3501,11 @@ code = '''
printf("traversal: %d 0x%x mdir 0x{%x,%x}\n",
mid_,
tag_,
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// keep track of seen blocks
seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8);
seen[mdir->other_block / 8] |= 1 << (mdir->other_block % 8);
seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8);
} else {
// this shouldn't happen
printf("traversal: %d 0x%x %d\n",
@@ -3530,7 +3530,7 @@ code = '''
// and the tree should still work
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -3629,11 +3629,11 @@ code = '''
printf("traversal: %d 0x%x mdir 0x{%x,%x}\n",
mid_,
tag_,
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// keep track of seen blocks
seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8);
seen[mdir->other_block / 8] |= 1 << (mdir->other_block % 8);
seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8);
} else {
// this shouldn't happen
printf("traversal: %d 0x%x %d\n",
@@ -3795,11 +3795,11 @@ code = '''
printf("traversal: %d 0x%x mdir 0x{%x,%x}\n",
mid_,
tag_,
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
// keep track of seen blocks
seen[mdir->rbyd.block / 8] |= 1 << (mdir->rbyd.block % 8);
seen[mdir->other_block / 8] |= 1 << (mdir->other_block % 8);
seen[mdir->redund_block / 8] |= 1 << (mdir->redund_block % 8);
} else {
// this shouldn't happen
printf("traversal: %d 0x%x %d\n",
@@ -3861,8 +3861,8 @@ code = '''
lfsr_format(&lfs, cfg) => 0;
lfsr_mount(&lfs, cfg) => 0;
uint8_t buffer[LFSR_MPAIR_DSIZE];
lfs_ssize_t d = lfsr_mpair_todisk(&lfs, LFSR_MPAIR(0, 1), buffer);
uint8_t buffer[LFSR_MPTR_DSIZE];
lfs_ssize_t d = lfsr_mptr_todisk(&lfs, LFSR_MPTR_MROOTANCHOR, buffer);
assert(d >= 0);
lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS(
LFSR_ATTR(-1, MROOT, 0, buffer, d))) => 0;
@@ -3896,7 +3896,7 @@ code = '''
printf("traversal: %d 0x%x mdir 0x{%x,%x}\n",
mid_,
tag_,
mdir->rbyd.block, mdir->other_block);
mdir->rbyd.block, mdir->redund_block);
} else {
// this shouldn't happen
printf("traversal: %d 0x%x %d\n",
@@ -3962,7 +3962,7 @@ code = '''
LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),
@@ -4018,7 +4018,7 @@ code = '''
LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0;
// assert we relocated
assert(!lfsr_mdir_eq(&old_mroot, &lfs.mroot));
assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0);
// assert that our attr is still in the mroot
lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),