Adopted SUPWIDE tag bit, parallel to the SUBWIDE (was WIDE) bit
Like SUBWIDE, SUPWIDE allows for "mask-like" operation during rbyd
commits, where you replace an entire subrange of tags with a single tag.
- SUBWIDE - Replace all subtypes of the given suptype - Useful for
changing the subtype of an attr, for example replacing a BTREE with a
BSHRUB.
- SUPWIDE - Replace all suptypes of the given rid - Useful for changing
the suptype of an attr, for example replacing a REG file with an
ORPHAN file.
These are effectively the same modifier, just with different ranges.
One benefit is this simplifies mid-level operations a bit, rename,
remove, etc, and decreases the stack cost of the related attr lists.
Though this isn't on the hot-path, so not measurable:
code stack
before: 33956 2912
after: 33928 (-0.1%) 2912 (+0.0%)
But the real motivation for this change is to remove cases where
lfsr_mdir_commit needs to operate on multiple mids. There may be an API
simplification here.
This commit is contained in:
@@ -662,7 +662,8 @@ enum lfsr_tag {
|
|||||||
// some in-device only tag modifiers
|
// some in-device only tag modifiers
|
||||||
LFSR_TAG_RM = 0x8000,
|
LFSR_TAG_RM = 0x8000,
|
||||||
LFSR_TAG_GROW = 0x4000,
|
LFSR_TAG_GROW = 0x4000,
|
||||||
LFSR_TAG_WIDE = 0x2000,
|
LFSR_TAG_SUPWIDE = 0x2000,
|
||||||
|
LFSR_TAG_SUBWIDE = 0x1000,
|
||||||
|
|
||||||
// lfsr_rbyd_appendattr specific flags, also in-device only
|
// lfsr_rbyd_appendattr specific flags, also in-device only
|
||||||
LFSR_TAG_DIVERGED = 0x4000,
|
LFSR_TAG_DIVERGED = 0x4000,
|
||||||
@@ -675,10 +676,11 @@ enum lfsr_tag {
|
|||||||
#define LFSR_TAG_TAG(tag) (tag)
|
#define LFSR_TAG_TAG(tag) (tag)
|
||||||
|
|
||||||
// some tag modifiers
|
// some tag modifiers
|
||||||
#define LFSR_TAG_SHRUB(tag) (LFSR_TAG_SHRUB | LFSR_TAG_##tag)
|
#define LFSR_TAG_SHRUB(tag) (LFSR_TAG_SHRUB | LFSR_TAG_##tag)
|
||||||
#define LFSR_TAG_RM(tag) (LFSR_TAG_RM | LFSR_TAG_##tag)
|
#define LFSR_TAG_RM(tag) (LFSR_TAG_RM | LFSR_TAG_##tag)
|
||||||
#define LFSR_TAG_GROW(tag) (LFSR_TAG_GROW | LFSR_TAG_##tag)
|
#define LFSR_TAG_GROW(tag) (LFSR_TAG_GROW | LFSR_TAG_##tag)
|
||||||
#define LFSR_TAG_WIDE(tag) (LFSR_TAG_WIDE | LFSR_TAG_##tag)
|
#define LFSR_TAG_SUPWIDE(tag) (LFSR_TAG_SUPWIDE | LFSR_TAG_##tag)
|
||||||
|
#define LFSR_TAG_SUBWIDE(tag) (LFSR_TAG_SUBWIDE | LFSR_TAG_##tag)
|
||||||
|
|
||||||
// some other tag encodings with their own subfields
|
// some other tag encodings with their own subfields
|
||||||
#define LFSR_TAG_ALT(d, c, key) \
|
#define LFSR_TAG_ALT(d, c, key) \
|
||||||
@@ -746,8 +748,12 @@ static inline bool lfsr_tag_isgrow(lfsr_tag_t tag) {
|
|||||||
return tag & LFSR_TAG_GROW;
|
return tag & LFSR_TAG_GROW;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfsr_tag_iswide(lfsr_tag_t tag) {
|
static inline bool lfsr_tag_issupwide(lfsr_tag_t tag) {
|
||||||
return tag & LFSR_TAG_WIDE;
|
return tag & LFSR_TAG_SUPWIDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool lfsr_tag_issubwide(lfsr_tag_t tag) {
|
||||||
|
return tag & LFSR_TAG_SUBWIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lfsr_rbyd_appendattr diverged specific flags
|
// lfsr_rbyd_appendattr diverged specific flags
|
||||||
@@ -2339,7 +2345,7 @@ static int lfsr_rbyd_lookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfsr_rbyd_lookupwide(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
static int lfsr_rbyd_sublookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||||
lfsr_srid_t rid, lfsr_tag_t tag,
|
lfsr_srid_t rid, lfsr_tag_t tag,
|
||||||
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
||||||
// looking up a wide tag with subtype is probably a mistake
|
// looking up a wide tag with subtype is probably a mistake
|
||||||
@@ -2353,7 +2359,7 @@ static int lfsr_rbyd_lookupwide(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the difference between lookup and lookupwide is we accept any
|
// the difference between lookup and sublookup is we accept any
|
||||||
// subtype of the requested tag
|
// subtype of the requested tag
|
||||||
if (rid_ != rid || lfsr_tag_suptype(tag__) != tag) {
|
if (rid_ != rid || lfsr_tag_suptype(tag__) != tag) {
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
@@ -2365,6 +2371,29 @@ static int lfsr_rbyd_lookupwide(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lfsr_rbyd_suplookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||||
|
lfsr_srid_t rid,
|
||||||
|
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
||||||
|
lfsr_srid_t rid_;
|
||||||
|
lfsr_tag_t tag__;
|
||||||
|
int err = lfsr_rbyd_lookupnext(lfs, rbyd, rid, 0,
|
||||||
|
&rid_, &tag__, NULL, data_);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the difference between lookup and suplookup is we accept any tag
|
||||||
|
if (rid_ != rid) {
|
||||||
|
return LFS_ERR_NOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag_) {
|
||||||
|
*tag_ = tag__;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// append a revision count
|
// append a revision count
|
||||||
//
|
//
|
||||||
@@ -2530,8 +2559,6 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
lfsr_tag_t other_tag_;
|
lfsr_tag_t other_tag_;
|
||||||
if (delta != 0 && !lfsr_tag_isgrow(tag)) {
|
if (delta != 0 && !lfsr_tag_isgrow(tag)) {
|
||||||
LFS_ASSERT(!lfsr_tag_iswide(tag));
|
|
||||||
|
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
LFS_ASSERT(rid <= rbyd->weight);
|
LFS_ASSERT(rid <= rbyd->weight);
|
||||||
|
|
||||||
@@ -2562,7 +2589,10 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
|
|
||||||
// note both normal and rm wide-tags have the same bounds, really it's
|
// note both normal and rm wide-tags have the same bounds, really it's
|
||||||
// the normal non-wide-tags that are an outlier here
|
// the normal non-wide-tags that are an outlier here
|
||||||
if (lfsr_tag_iswide(tag)) {
|
if (lfsr_tag_issupwide(tag)) {
|
||||||
|
tag_ = 0x1;
|
||||||
|
other_tag_ = tag_ + 0x800;
|
||||||
|
} else if (lfsr_tag_issubwide(tag)) {
|
||||||
tag_ = lfsr_tag_supkey(tag);
|
tag_ = lfsr_tag_supkey(tag);
|
||||||
other_tag_ = tag_ + 0x100;
|
other_tag_ = tag_ + 0x100;
|
||||||
} else if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
} else if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
||||||
@@ -2893,9 +2923,11 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
&& (upper_rid-1 < rid-lfs_smax32(-delta, 0)
|
&& (upper_rid-1 < rid-lfs_smax32(-delta, 0)
|
||||||
|| (upper_rid-1 == rid-lfs_smax32(-delta, 0)
|
|| (upper_rid-1 == rid-lfs_smax32(-delta, 0)
|
||||||
&& ((delta > 0 && !lfsr_tag_isgrow(tag))
|
&& ((delta > 0 && !lfsr_tag_isgrow(tag))
|
||||||
|| ((lfsr_tag_iswide(tag))
|
|| (!lfsr_tag_issupwide(tag)
|
||||||
? lfsr_tag_supkey(tag_) < lfsr_tag_supkey(tag)
|
&& lfsr_tag_supkey(tag_) < lfsr_tag_supkey(tag))
|
||||||
: lfsr_tag_key(tag_) < lfsr_tag_key(tag)))))) {
|
|| (!lfsr_tag_issupwide(tag)
|
||||||
|
&& !lfsr_tag_issubwide(tag)
|
||||||
|
&& lfsr_tag_key(tag_) < lfsr_tag_key(tag)))))) {
|
||||||
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
||||||
// if removed, make our tag unreachable
|
// if removed, make our tag unreachable
|
||||||
alt = LFSR_TAG_ALT(GT, B, 0);
|
alt = LFSR_TAG_ALT(GT, B, 0);
|
||||||
@@ -2917,9 +2949,11 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
&& (upper_rid-1 > rid
|
&& (upper_rid-1 > rid
|
||||||
|| (upper_rid-1 == rid
|
|| (upper_rid-1 == rid
|
||||||
&& ((delta > 0 && !lfsr_tag_isgrow(tag))
|
&& ((delta > 0 && !lfsr_tag_isgrow(tag))
|
||||||
|| ((lfsr_tag_iswide(tag))
|
|| (!lfsr_tag_issupwide(tag)
|
||||||
? lfsr_tag_supkey(tag_) > lfsr_tag_supkey(tag)
|
&& lfsr_tag_supkey(tag_) > lfsr_tag_supkey(tag))
|
||||||
: lfsr_tag_key(tag_) > lfsr_tag_key(tag)))))) {
|
|| (!lfsr_tag_issupwide(tag)
|
||||||
|
&& !lfsr_tag_issubwide(tag)
|
||||||
|
&& lfsr_tag_key(tag_) > lfsr_tag_key(tag)))))) {
|
||||||
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
if (lfsr_tag_isrm(tag) || !lfsr_tag_key(tag)) {
|
||||||
// if removed, make our tag unreachable
|
// if removed, make our tag unreachable
|
||||||
alt = LFSR_TAG_ALT(GT, B, 0);
|
alt = LFSR_TAG_ALT(GT, B, 0);
|
||||||
@@ -3814,7 +3848,7 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
|
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
|
||||||
err = lfsr_rbyd_lookupwide(lfs, &branch, rid__, LFSR_TAG_STRUCT,
|
err = lfsr_rbyd_sublookup(lfs, &branch, rid__, LFSR_TAG_STRUCT,
|
||||||
&tag__, &data__);
|
&tag__, &data__);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
@@ -3911,7 +3945,7 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
|
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
|
||||||
err = lfsr_rbyd_lookupwide(lfs, &branch, rid__, LFSR_TAG_STRUCT,
|
err = lfsr_rbyd_sublookup(lfs, &branch, rid__, LFSR_TAG_STRUCT,
|
||||||
&tag__, &data__);
|
&tag__, &data__);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
@@ -4141,7 +4175,7 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sibling_tag == LFSR_TAG_NAME) {
|
if (sibling_tag == LFSR_TAG_NAME) {
|
||||||
err = lfsr_rbyd_lookupwide(lfs, &parent,
|
err = lfsr_rbyd_sublookup(lfs, &parent,
|
||||||
sibling_rid, LFSR_TAG_STRUCT,
|
sibling_rid, LFSR_TAG_STRUCT,
|
||||||
&sibling_tag, &sibling_data);
|
&sibling_tag, &sibling_data);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -4189,7 +4223,7 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sibling_tag == LFSR_TAG_NAME) {
|
if (sibling_tag == LFSR_TAG_NAME) {
|
||||||
err = lfsr_rbyd_lookupwide(lfs, &parent,
|
err = lfsr_rbyd_sublookup(lfs, &parent,
|
||||||
sibling_rid, LFSR_TAG_STRUCT,
|
sibling_rid, LFSR_TAG_STRUCT,
|
||||||
&sibling_tag, &sibling_data);
|
&sibling_tag, &sibling_data);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -4537,7 +4571,7 @@ static lfs_scmp_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
// the name may not match exactly, but indicates which branch to follow
|
// the name may not match exactly, but indicates which branch to follow
|
||||||
lfsr_tag_t tag__;
|
lfsr_tag_t tag__;
|
||||||
lfsr_data_t data__;
|
lfsr_data_t data__;
|
||||||
int err = lfsr_rbyd_lookupwide(lfs, &branch, rid__, LFSR_TAG_STRUCT,
|
int err = lfsr_rbyd_sublookup(lfs, &branch, rid__, LFSR_TAG_STRUCT,
|
||||||
&tag__, &data__);
|
&tag__, &data__);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
@@ -4639,7 +4673,7 @@ static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
|
if (lfsr_tag_suptype(tag__) == LFSR_TAG_NAME) {
|
||||||
err = lfsr_rbyd_lookupwide(lfs, &btraversal->branch,
|
err = lfsr_rbyd_sublookup(lfs, &btraversal->branch,
|
||||||
rid__, LFSR_TAG_STRUCT,
|
rid__, LFSR_TAG_STRUCT,
|
||||||
&tag__, &data__);
|
&tag__, &data__);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -5145,7 +5179,7 @@ static int lfsr_mdir_lookup(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfsr_mdir_lookupwide(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
static int lfsr_mdir_sublookup(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
||||||
lfsr_smid_t mid, lfsr_tag_t tag,
|
lfsr_smid_t mid, lfsr_tag_t tag,
|
||||||
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
||||||
// looking up a wide tag with subtype is probably a mistake
|
// looking up a wide tag with subtype is probably a mistake
|
||||||
@@ -5158,7 +5192,7 @@ static int lfsr_mdir_lookupwide(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the difference between lookup and lookupwide is we accept any
|
// the difference between lookup and sublookup is we accept any
|
||||||
// subtype of the requested tag
|
// subtype of the requested tag
|
||||||
if (lfsr_tag_suptype(tag__) != tag) {
|
if (lfsr_tag_suptype(tag__) != tag) {
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
@@ -5170,6 +5204,23 @@ static int lfsr_mdir_lookupwide(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lfsr_mdir_suplookup(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
||||||
|
lfsr_smid_t mid,
|
||||||
|
lfsr_tag_t *tag_, lfsr_data_t *data_) {
|
||||||
|
lfsr_tag_t tag__;
|
||||||
|
int err = lfsr_mdir_lookupnext(lfs, mdir, mid, 0,
|
||||||
|
&tag__, data_);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the difference between lookup and sublookup is we accept any tag
|
||||||
|
if (tag_) {
|
||||||
|
*tag_ = tag__;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// track opened mdirs to keep state in-sync
|
// track opened mdirs to keep state in-sync
|
||||||
static bool lfsr_isopened(lfs_t *lfs, const lfsr_opened_t *opened) {
|
static bool lfsr_isopened(lfs_t *lfs, const lfsr_opened_t *opened) {
|
||||||
for (lfsr_opened_t *p = lfs->opened; p; p = p->next) {
|
for (lfsr_opened_t *p = lfs->opened; p; p = p->next) {
|
||||||
@@ -6224,7 +6275,7 @@ static int lfsr_mroot_commit_(lfs_t *lfs,
|
|||||||
uint8_t mrootchild_buf[LFSR_MPTR_DSIZE];
|
uint8_t mrootchild_buf[LFSR_MPTR_DSIZE];
|
||||||
err = lfsr_mdir_commit__(lfs, &mrootanchor_, -1, -1, LFSR_ATTRS(
|
err = lfsr_mdir_commit__(lfs, &mrootanchor_, -1, -1, LFSR_ATTRS(
|
||||||
LFSR_ATTR(-1,
|
LFSR_ATTR(-1,
|
||||||
WIDE(MROOT), 0,
|
SUBWIDE(MROOT), 0,
|
||||||
FROMMPTR(lfsr_mdir_mptr(&mrootchild_), mrootchild_buf))));
|
FROMMPTR(lfsr_mdir_mptr(&mrootchild_), mrootchild_buf))));
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
@@ -6295,7 +6346,7 @@ static int lfsr_mtree_commit_(lfs_t *lfs,
|
|||||||
uint8_t mtree_buf[LFSR_BTREE_DSIZE];
|
uint8_t mtree_buf[LFSR_BTREE_DSIZE];
|
||||||
err = lfsr_mroot_commit_(lfs, -1, 0, NULL, LFSR_ATTRS(
|
err = lfsr_mroot_commit_(lfs, -1, 0, NULL, LFSR_ATTRS(
|
||||||
LFSR_ATTR(-1,
|
LFSR_ATTR(-1,
|
||||||
WIDE(MTREE), 0, FROMBTREE(&mtree_, mtree_buf))));
|
SUBWIDE(MTREE), 0, FROMBTREE(&mtree_, mtree_buf))));
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
return err;
|
return err;
|
||||||
@@ -6542,7 +6593,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
// note we need to do this after playing out pending attrs in
|
// note we need to do this after playing out pending attrs in
|
||||||
// case they introduce a new name!
|
// case they introduce a new name!
|
||||||
lfsr_data_t split_data;
|
lfsr_data_t split_data;
|
||||||
err = lfsr_rbyd_lookupwide(lfs, &msibling_.rbyd, 0, LFSR_TAG_NAME,
|
err = lfsr_rbyd_sublookup(lfs, &msibling_.rbyd, 0, LFSR_TAG_NAME,
|
||||||
NULL, &split_data);
|
NULL, &split_data);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
@@ -6661,7 +6712,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
uint8_t mdir_buf[LFSR_MPTR_DSIZE];
|
uint8_t mdir_buf[LFSR_MPTR_DSIZE];
|
||||||
err = lfsr_mroot_commit_(lfs, -1, 0, NULL, LFSR_ATTRS(
|
err = lfsr_mroot_commit_(lfs, -1, 0, NULL, LFSR_ATTRS(
|
||||||
LFSR_ATTR(-1,
|
LFSR_ATTR(-1,
|
||||||
WIDE(MDIR), 0,
|
SUBWIDE(MDIR), 0,
|
||||||
FROMMPTR(lfsr_mdir_mptr(&mdir_), mdir_buf))));
|
FROMMPTR(lfsr_mdir_mptr(&mdir_), mdir_buf))));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -6718,12 +6769,18 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
|
|||||||
// adjust opened mdirs?
|
// adjust opened mdirs?
|
||||||
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0
|
if (lfsr_mdir_cmp(&opened->mdir, mdir) == 0
|
||||||
&& opened->mdir.mid >= attrs[i].rid) {
|
&& opened->mdir.mid >= attrs[i].rid) {
|
||||||
// removed?
|
// replaced?
|
||||||
if (opened->mdir.mid < attrs[i].rid - attrs[i].delta) {
|
if (opened->mdir.mid == attrs[i].rid - attrs[i].delta
|
||||||
// mark as zombied and move onto the next rid, upper
|
&& lfsr_tag_issupwide(attrs[i].tag)) {
|
||||||
// layers should handle the repercussions
|
opened->flags |= LFS_F_ZOMBIE
|
||||||
opened->flags |= LFS_F_ZOMBIE | LFS_F_UNSYNC | LFS_O_DESYNC;
|
| LFS_F_UNSYNC
|
||||||
|
| LFS_O_DESYNC;
|
||||||
opened->flags &= ~LFS_F_ORPHAN;
|
opened->flags &= ~LFS_F_ORPHAN;
|
||||||
|
// removed?
|
||||||
|
} else if (opened->mdir.mid < attrs[i].rid - attrs[i].delta) {
|
||||||
|
// we should not be removing opened regular files
|
||||||
|
LFS_ASSERT(opened->type != LFS_TYPE_REG);
|
||||||
|
opened->flags |= LFS_F_ZOMBIE;
|
||||||
opened->mdir.mid = attrs[i].rid;
|
opened->mdir.mid = attrs[i].rid;
|
||||||
} else {
|
} else {
|
||||||
opened->mdir.mid += attrs[i].delta;
|
opened->mdir.mid += attrs[i].delta;
|
||||||
@@ -7152,7 +7209,7 @@ static int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *traversal,
|
|||||||
// 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;
|
||||||
err = lfsr_mdir_lookupwide(lfs, &traversal->file.mdir,
|
err = lfsr_mdir_sublookup(lfs, &traversal->file.mdir,
|
||||||
-1, LFSR_TAG_STRUCT,
|
-1, LFSR_TAG_STRUCT,
|
||||||
&tag, &data);
|
&tag, &data);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -8492,14 +8549,12 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
|
|||||||
// commit our new directory into our parent, zeroing the grm in the
|
// commit our new directory into our parent, zeroing the grm in the
|
||||||
// process
|
// process
|
||||||
err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS(
|
err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS(
|
||||||
LFSR_ATTR(mdir.mid + ((exists) ? 1 : 0),
|
LFSR_ATTR(mdir.mid,
|
||||||
DIR, +1, CAT(
|
SUPWIDE(DIR), (!exists) ? +1 : 0, CAT(
|
||||||
LFSR_DATA_LEB128(did),
|
LFSR_DATA_LEB128(did),
|
||||||
LFSR_DATA_BUF(name, name_size))),
|
LFSR_DATA_BUF(name, name_size))),
|
||||||
LFSR_ATTR(mdir.mid + ((exists) ? 1 : 0),
|
LFSR_ATTR(mdir.mid,
|
||||||
DID, 0, LEB128(did_)),
|
DID, 0, LEB128(did_)),
|
||||||
LFSR_ATTR_IF((exists),
|
|
||||||
mdir.mid, RM, -1, NULL()),
|
|
||||||
LFSR_ATTR(-1, GRM, 0, GRM(&((lfsr_grm_t){{-1, -1}})))));
|
LFSR_ATTR(-1, GRM, 0, GRM(&((lfsr_grm_t){{-1, -1}})))));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -8570,7 +8625,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) {
|
|||||||
|
|
||||||
if (err != LFS_ERR_NOENT) {
|
if (err != LFS_ERR_NOENT) {
|
||||||
lfsr_tag_t bookmark_tag;
|
lfsr_tag_t bookmark_tag;
|
||||||
err = lfsr_mdir_lookupwide(lfs, &bookmark_mdir,
|
err = lfsr_mdir_sublookup(lfs, &bookmark_mdir,
|
||||||
bookmark_mdir.mid, LFSR_TAG_NAME,
|
bookmark_mdir.mid, LFSR_TAG_NAME,
|
||||||
&bookmark_tag, NULL);
|
&bookmark_tag, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -8581,16 +8636,16 @@ int lfsr_remove(lfs_t *lfs, const char *path) {
|
|||||||
return LFS_ERR_NOTEMPTY;
|
return LFS_ERR_NOTEMPTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust rid if grm is on the same mdir as our dir
|
|
||||||
if (lfsr_mid_bid(lfs, grm.rms[0]) == lfsr_mid_bid(lfs, mdir.mid)
|
|
||||||
&& grm.rms[0] > mdir.mid) {
|
|
||||||
grm.rms[0] -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// are we removing an opened file?
|
// are we removing an opened file?
|
||||||
bool zombie = lfsr_mid_isopened(lfs, mdir.mid);
|
bool zombie = lfsr_mid_isopened(lfs, mdir.mid);
|
||||||
|
// adjust grm rid if grm is on the same mdir as our dir
|
||||||
|
if (!zombie
|
||||||
|
&& lfsr_mid_bid(lfs, grm.rms[0]) == lfsr_mid_bid(lfs, mdir.mid)
|
||||||
|
&& grm.rms[0] > mdir.mid) {
|
||||||
|
grm.rms[0] -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
// remove the metadata entry
|
// remove the metadata entry
|
||||||
err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS(
|
err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS(
|
||||||
@@ -8598,11 +8653,11 @@ int lfsr_remove(lfs_t *lfs, const char *path) {
|
|||||||
//
|
//
|
||||||
// we use a create+delete here to also clear any attrs
|
// we use a create+delete here to also clear any attrs
|
||||||
// and trim the entry size
|
// and trim the entry size
|
||||||
LFSR_ATTR_IF((zombie),
|
(zombie)
|
||||||
mdir.mid+1, ORPHAN, +1, CAT(
|
? LFSR_ATTR(mdir.mid, SUPWIDE(ORPHAN), 0, CAT(
|
||||||
LFSR_DATA_LEB128(did),
|
LFSR_DATA_LEB128(did),
|
||||||
LFSR_DATA_BUF(name, name_size))),
|
LFSR_DATA_BUF(name, name_size)))
|
||||||
LFSR_ATTR(mdir.mid, RM, -1, NULL()),
|
: LFSR_ATTR(mdir.mid, RM, -1, NULL()),
|
||||||
LFSR_ATTR(-1, GRM, 0, GRM(&grm))));
|
LFSR_ATTR(-1, GRM, 0, GRM(&grm))));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -8733,7 +8788,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) {
|
|||||||
|
|
||||||
if (err != LFS_ERR_NOENT) {
|
if (err != LFS_ERR_NOENT) {
|
||||||
lfsr_tag_t bookmark_tag;
|
lfsr_tag_t bookmark_tag;
|
||||||
err = lfsr_mdir_lookupwide(lfs, &bookmark_mdir,
|
err = lfsr_mdir_sublookup(lfs, &bookmark_mdir,
|
||||||
bookmark_mdir.mid, LFSR_TAG_NAME,
|
bookmark_mdir.mid, LFSR_TAG_NAME,
|
||||||
&bookmark_tag, NULL);
|
&bookmark_tag, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -8750,14 +8805,12 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) {
|
|||||||
// rename our entry, copying all tags associated with the old rid to the
|
// rename our entry, copying all tags associated with the old rid to the
|
||||||
// new rid, while also marking the old rid for removal
|
// new rid, while also marking the old rid for removal
|
||||||
err = lfsr_mdir_commit(lfs, &new_mdir, LFSR_ATTRS(
|
err = lfsr_mdir_commit(lfs, &new_mdir, LFSR_ATTRS(
|
||||||
LFSR_ATTR(new_mdir.mid + ((exists) ? 1 : 0),
|
LFSR_ATTR(new_mdir.mid,
|
||||||
TAG(old_tag), +1, CAT(
|
SUPWIDE(TAG(old_tag)), (!exists) ? +1 : 0, CAT(
|
||||||
LFSR_DATA_LEB128(new_did),
|
LFSR_DATA_LEB128(new_did),
|
||||||
LFSR_DATA_BUF(new_name, new_name_size))),
|
LFSR_DATA_BUF(new_name, new_name_size))),
|
||||||
LFSR_ATTR(new_mdir.mid + ((exists) ? 1 : 0),
|
LFSR_ATTR(new_mdir.mid,
|
||||||
MOVE, 0, MOVE(&old_mdir)),
|
MOVE, 0, MOVE(&old_mdir)),
|
||||||
LFSR_ATTR_IF((exists),
|
|
||||||
new_mdir.mid, RM, -1, NULL()),
|
|
||||||
LFSR_ATTR(-1, GRM, 0, GRM(&grm))));
|
LFSR_ATTR(-1, GRM, 0, GRM(&grm))));
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -8959,7 +9012,7 @@ int lfsr_dir_read(lfs_t *lfs, lfsr_dir_t *dir, struct lfs_info *info) {
|
|||||||
// lookup the next name tag
|
// lookup the next name tag
|
||||||
lfsr_tag_t tag;
|
lfsr_tag_t tag;
|
||||||
lfsr_data_t data;
|
lfsr_data_t data;
|
||||||
err = lfsr_mdir_lookupwide(lfs, &dir->p.mdir,
|
err = lfsr_mdir_sublookup(lfs, &dir->p.mdir,
|
||||||
dir->p.mdir.mid, LFSR_TAG_NAME,
|
dir->p.mdir.mid, LFSR_TAG_NAME,
|
||||||
&tag, &data);
|
&tag, &data);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -9941,7 +9994,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
|
|
||||||
err = lfsr_bshrub_commit(lfs, file, LFSR_ATTRS(
|
err = lfsr_bshrub_commit(lfs, file, LFSR_ATTRS(
|
||||||
LFSR_ATTR(bid_,
|
LFSR_ATTR(bid_,
|
||||||
GROW(WIDE(DATA)),
|
GROW(SUBWIDE(DATA)),
|
||||||
-(weight_ - lfs->cfg->fragment_size),
|
-(weight_ - lfs->cfg->fragment_size),
|
||||||
DATA(lfsr_data_truncate(left_slice_,
|
DATA(lfsr_data_truncate(left_slice_,
|
||||||
lfs->cfg->fragment_size))),
|
lfs->cfg->fragment_size))),
|
||||||
@@ -9968,7 +10021,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
|
|
||||||
err = lfsr_bshrub_commit(lfs, file, LFSR_ATTRS(
|
err = lfsr_bshrub_commit(lfs, file, LFSR_ATTRS(
|
||||||
LFSR_ATTR(bid_,
|
LFSR_ATTR(bid_,
|
||||||
GROW(WIDE(BLOCK)),
|
GROW(SUBWIDE(BLOCK)),
|
||||||
-(weight_ - lfsr_data_size(&bptr_.data)),
|
-(weight_ - lfsr_data_size(&bptr_.data)),
|
||||||
FROMBPTR(&bptr_, buf)),
|
FROMBPTR(&bptr_, buf)),
|
||||||
LFSR_ATTR(bid_
|
LFSR_ATTR(bid_
|
||||||
@@ -10002,14 +10055,14 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
.cksum = bptr_.cksum,
|
.cksum = bptr_.cksum,
|
||||||
};
|
};
|
||||||
attrs[attr_count++] = LFSR_ATTR(bid_,
|
attrs[attr_count++] = LFSR_ATTR(bid_,
|
||||||
GROW(WIDE(BLOCK)), -(bid_+1 - pos),
|
GROW(SUBWIDE(BLOCK)), -(bid_+1 - pos),
|
||||||
FROMBPTR(&bptr__, &buf[buf_size]));
|
FROMBPTR(&bptr__, &buf[buf_size]));
|
||||||
buf_size += LFSR_BPTR_DSIZE;
|
buf_size += LFSR_BPTR_DSIZE;
|
||||||
|
|
||||||
// carve fragment?
|
// carve fragment?
|
||||||
} else {
|
} else {
|
||||||
attrs[attr_count++] = LFSR_ATTR(bid_,
|
attrs[attr_count++] = LFSR_ATTR(bid_,
|
||||||
GROW(WIDE(DATA)), -(bid_+1 - pos),
|
GROW(SUBWIDE(DATA)), -(bid_+1 - pos),
|
||||||
DATA(left_slice_));
|
DATA(left_slice_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11006,7 +11059,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
||||||
WIDE(REG), 0, DATA(data));
|
SUBWIDE(REG), 0, DATA(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit the file state
|
// commit the file state
|
||||||
@@ -11014,22 +11067,22 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
// null? no attr?
|
// null? no attr?
|
||||||
if (lfsr_f_isunflush(file->m.flags) && file->buffer_size == 0) {
|
if (lfsr_f_isunflush(file->m.flags) && file->buffer_size == 0) {
|
||||||
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
||||||
WIDE(RM(STRUCT)), 0,
|
SUBWIDE(RM(STRUCT)), 0,
|
||||||
NULL());
|
NULL());
|
||||||
// small file inlined in mdir?
|
// small file inlined in mdir?
|
||||||
} else if (lfsr_f_isunflush(file->m.flags)) {
|
} else if (lfsr_f_isunflush(file->m.flags)) {
|
||||||
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
||||||
WIDE(DATA), 0,
|
SUBWIDE(DATA), 0,
|
||||||
BUF(file->buffer, file->buffer_size));
|
BUF(file->buffer, file->buffer_size));
|
||||||
// bshrub?
|
// bshrub?
|
||||||
} else if (lfsr_bshrub_isbshrub(&file->m.mdir, &file->bshrub)) {
|
} else if (lfsr_bshrub_isbshrub(&file->m.mdir, &file->bshrub)) {
|
||||||
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
||||||
WIDE(SHRUBTRUNK), 0,
|
SUBWIDE(SHRUBTRUNK), 0,
|
||||||
SHRUBTRUNK(&file->bshrub_.u.bshrub));
|
SHRUBTRUNK(&file->bshrub_.u.bshrub));
|
||||||
// btree?
|
// btree?
|
||||||
} else if (lfsr_bshrub_isbtree(&file->m.mdir, &file->bshrub)) {
|
} else if (lfsr_bshrub_isbtree(&file->m.mdir, &file->bshrub)) {
|
||||||
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
attrs[attr_count++] = LFSR_ATTR(file->m.mdir.mid,
|
||||||
WIDE(BTREE), 0,
|
SUBWIDE(BTREE), 0,
|
||||||
FROMBTREE(&file->bshrub.u.btree, &buf[buf_size]));
|
FROMBTREE(&file->bshrub.u.btree, &buf[buf_size]));
|
||||||
buf_size += LFSR_BTREE_DSIZE;
|
buf_size += LFSR_BTREE_DSIZE;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ code = '''
|
|||||||
// name attributes, the name attribute holds the weight not
|
// name attributes, the name attribute holds the weight not
|
||||||
// the struct tag
|
// the struct tag
|
||||||
return lfsr_btree_commit(lfs, btree, LFSR_ATTRS(
|
return lfsr_btree_commit(lfs, btree, LFSR_ATTRS(
|
||||||
LFSR_ATTR(bid, WIDE(TAG(tag)), 0, DATA(data)),
|
LFSR_ATTR(bid, SUBWIDE(TAG(tag)), 0, DATA(data)),
|
||||||
LFSR_ATTR(bid, GROW, weight - weight_, NULL())));
|
LFSR_ATTR(bid, GROW, weight - weight_, NULL())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+400
-28
@@ -11584,9 +11584,10 @@ code = '''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
### Wide-tag things ###
|
### Supertype/subtype-wide things ###
|
||||||
|
|
||||||
[cases.test_rbyd_wide_lookup_permutations]
|
# subtype-wide
|
||||||
|
[cases.test_rbyd_subwide_lookup_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -11660,7 +11661,7 @@ code = '''
|
|||||||
for (unsigned j = 0; j < N; j++) {
|
for (unsigned j = 0; j < N; j++) {
|
||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
lfsr_data_t data_;
|
lfsr_data_t data_;
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, j, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, j, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
|
|
||||||
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
|
||||||
@@ -11671,7 +11672,7 @@ code = '''
|
|||||||
|
|
||||||
# NOTE if we separate physical/logical block sizes we may be able to
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
# use emubd's copy-on-write copy to speed this up significantly
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
[cases.test_rbyd_wide_remove_permutations]
|
[cases.test_rbyd_subwide_remove_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -11761,7 +11762,7 @@ code = '''
|
|||||||
|
|
||||||
// remove with a wide tag
|
// remove with a wide tag
|
||||||
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
LFSR_ATTR(j, RM(WIDE(UATTR)), 0, NULL()))) => 0;
|
LFSR_ATTR(j, RM(SUBWIDE(UATTR)), 0, NULL()))) => 0;
|
||||||
|
|
||||||
// try traversing over the tags
|
// try traversing over the tags
|
||||||
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
||||||
@@ -11792,10 +11793,10 @@ code = '''
|
|||||||
// also test that we can lookup each tag with a wide lookup
|
// also test that we can lookup each tag with a wide lookup
|
||||||
for (unsigned k = 0; k < N; k++) {
|
for (unsigned k = 0; k < N; k++) {
|
||||||
if (k == j) {
|
if (k == j) {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => LFS_ERR_NOENT;
|
&tag_, &data_) => LFS_ERR_NOENT;
|
||||||
} else {
|
} else {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
||||||
assert(lfsr_data_size(&data_) == 2);
|
assert(lfsr_data_size(&data_) == 2);
|
||||||
@@ -11810,7 +11811,7 @@ code = '''
|
|||||||
|
|
||||||
# NOTE if we separate physical/logical block sizes we may be able to
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
# use emubd's copy-on-write copy to speed this up significantly
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
[cases.test_rbyd_wide_replace_permutations]
|
[cases.test_rbyd_subwide_replace_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -11900,7 +11901,7 @@ code = '''
|
|||||||
|
|
||||||
// replace with bitwise inverse
|
// replace with bitwise inverse
|
||||||
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
LFSR_ATTR(j, WIDE(UATTR(~(j + SHIFT) & 0x7f)), 0,
|
LFSR_ATTR(j, SUBWIDE(UATTR(~(j + SHIFT) & 0x7f)), 0,
|
||||||
BUF(names[j % 6], 3)))) => 0;
|
BUF(names[j % 6], 3)))) => 0;
|
||||||
|
|
||||||
// try traversing over the tags
|
// try traversing over the tags
|
||||||
@@ -11936,7 +11937,7 @@ code = '''
|
|||||||
|
|
||||||
// also test that we can lookup each tag with a wide lookup
|
// also test that we can lookup each tag with a wide lookup
|
||||||
for (unsigned k = 0; k < N; k++) {
|
for (unsigned k = 0; k < N; k++) {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
if (k == j) {
|
if (k == j) {
|
||||||
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
||||||
@@ -11953,7 +11954,7 @@ code = '''
|
|||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
[cases.test_rbyd_wide_mixed_lookup_permutations]
|
[cases.test_rbyd_subwide_mixed_lookup_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -12029,7 +12030,7 @@ code = '''
|
|||||||
for (unsigned j = 0; j < N; j++) {
|
for (unsigned j = 0; j < N; j++) {
|
||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
lfsr_data_t data_;
|
lfsr_data_t data_;
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, j, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, j, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
|
|
||||||
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
|
||||||
@@ -12040,7 +12041,7 @@ code = '''
|
|||||||
|
|
||||||
# NOTE if we separate physical/logical block sizes we may be able to
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
# use emubd's copy-on-write copy to speed this up significantly
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
[cases.test_rbyd_wide_mixed_remove_permutations]
|
[cases.test_rbyd_subwide_mixed_remove_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -12132,7 +12133,7 @@ code = '''
|
|||||||
|
|
||||||
// remove with a wide tag
|
// remove with a wide tag
|
||||||
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
LFSR_ATTR(j, RM(WIDE(UATTR)), 0, NULL()))) => 0;
|
LFSR_ATTR(j, RM(SUBWIDE(UATTR)), 0, NULL()))) => 0;
|
||||||
|
|
||||||
// try traversing over the tags
|
// try traversing over the tags
|
||||||
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
||||||
@@ -12170,10 +12171,10 @@ code = '''
|
|||||||
// also test that we can lookup each tag with a wide lookup
|
// also test that we can lookup each tag with a wide lookup
|
||||||
for (unsigned k = 0; k < N; k++) {
|
for (unsigned k = 0; k < N; k++) {
|
||||||
if (k == j) {
|
if (k == j) {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => LFS_ERR_NOENT;
|
&tag_, &data_) => LFS_ERR_NOENT;
|
||||||
} else {
|
} else {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
||||||
assert(lfsr_data_size(&data_) == 2);
|
assert(lfsr_data_size(&data_) == 2);
|
||||||
@@ -12188,7 +12189,7 @@ code = '''
|
|||||||
|
|
||||||
# NOTE if we separate physical/logical block sizes we may be able to
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
# use emubd's copy-on-write copy to speed this up significantly
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
[cases.test_rbyd_wide_mixed_replace_permutations]
|
[cases.test_rbyd_subwide_mixed_replace_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -12280,7 +12281,7 @@ code = '''
|
|||||||
|
|
||||||
// replace with bitwise inverse
|
// replace with bitwise inverse
|
||||||
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
LFSR_ATTR(j, WIDE(UATTR(~(j + SHIFT) & 0x7f)), 0,
|
LFSR_ATTR(j, SUBWIDE(UATTR(~(j + SHIFT) & 0x7f)), 0,
|
||||||
BUF(names[j % 6], 3)))) => 0;
|
BUF(names[j % 6], 3)))) => 0;
|
||||||
|
|
||||||
// try traversing over the tags
|
// try traversing over the tags
|
||||||
@@ -12323,7 +12324,7 @@ code = '''
|
|||||||
|
|
||||||
// also test that we can lookup each tag with a wide lookup
|
// also test that we can lookup each tag with a wide lookup
|
||||||
for (unsigned k = 0; k < N; k++) {
|
for (unsigned k = 0; k < N; k++) {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
if (k == j) {
|
if (k == j) {
|
||||||
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
||||||
@@ -12340,7 +12341,7 @@ code = '''
|
|||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
[cases.test_rbyd_wide_weighted_lookup_permutations]
|
[cases.test_rbyd_subwide_weighted_lookup_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -12413,7 +12414,7 @@ code = '''
|
|||||||
for (unsigned j = 0; j < N; j++) {
|
for (unsigned j = 0; j < N; j++) {
|
||||||
lfsr_tag_t tag_;
|
lfsr_tag_t tag_;
|
||||||
lfsr_data_t data_;
|
lfsr_data_t data_;
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, j, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, j, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
|
|
||||||
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR((j + SHIFT) & 0x7f));
|
||||||
@@ -12424,7 +12425,7 @@ code = '''
|
|||||||
|
|
||||||
# NOTE if we separate physical/logical block sizes we may be able to
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
# use emubd's copy-on-write copy to speed this up significantly
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
[cases.test_rbyd_wide_weighted_remove_permutations]
|
[cases.test_rbyd_subwide_weighted_remove_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -12513,7 +12514,7 @@ code = '''
|
|||||||
|
|
||||||
// remove with a wide tag
|
// remove with a wide tag
|
||||||
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
LFSR_ATTR(j, RM(WIDE(UATTR)), 0, NULL()))) => 0;
|
LFSR_ATTR(j, RM(SUBWIDE(UATTR)), 0, NULL()))) => 0;
|
||||||
|
|
||||||
// try traversing over the tags
|
// try traversing over the tags
|
||||||
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
||||||
@@ -12547,10 +12548,10 @@ code = '''
|
|||||||
// also test that we can lookup each tag with a wide lookup
|
// also test that we can lookup each tag with a wide lookup
|
||||||
for (unsigned k = 0; k < N; k++) {
|
for (unsigned k = 0; k < N; k++) {
|
||||||
if (k == j) {
|
if (k == j) {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => LFS_ERR_NOENT;
|
&tag_, &data_) => LFS_ERR_NOENT;
|
||||||
} else {
|
} else {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
||||||
assert(lfsr_data_size(&data_) == 4);
|
assert(lfsr_data_size(&data_) == 4);
|
||||||
@@ -12565,7 +12566,7 @@ code = '''
|
|||||||
|
|
||||||
# NOTE if we separate physical/logical block sizes we may be able to
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
# use emubd's copy-on-write copy to speed this up significantly
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
[cases.test_rbyd_wide_weighted_replace_permutations]
|
[cases.test_rbyd_subwide_weighted_replace_permutations]
|
||||||
defines.N = 'range(1, 7)'
|
defines.N = 'range(1, 7)'
|
||||||
defines.SHIFT = [0, 3, -3]
|
defines.SHIFT = [0, 3, -3]
|
||||||
# -1 => exhaust all permutations
|
# -1 => exhaust all permutations
|
||||||
@@ -12654,7 +12655,7 @@ code = '''
|
|||||||
|
|
||||||
// replace with bitwise inverse
|
// replace with bitwise inverse
|
||||||
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
LFSR_ATTR(j, WIDE(UATTR(~(j + SHIFT) & 0x7f)), 0,
|
LFSR_ATTR(j, SUBWIDE(UATTR(~(j + SHIFT) & 0x7f)), 0,
|
||||||
BUF(names[j % 6], 6)))) => 0;
|
BUF(names[j % 6], 6)))) => 0;
|
||||||
|
|
||||||
// try traversing over the tags
|
// try traversing over the tags
|
||||||
@@ -12683,7 +12684,7 @@ code = '''
|
|||||||
|
|
||||||
// also test that we can lookup each tag with a wide lookup
|
// also test that we can lookup each tag with a wide lookup
|
||||||
for (unsigned k = 0; k < N; k++) {
|
for (unsigned k = 0; k < N; k++) {
|
||||||
lfsr_rbyd_lookupwide(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
&tag_, &data_) => 0;
|
&tag_, &data_) => 0;
|
||||||
if (k == j) {
|
if (k == j) {
|
||||||
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
||||||
@@ -12699,3 +12700,374 @@ code = '''
|
|||||||
free(backup_block);
|
free(backup_block);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# supertype-wide
|
||||||
|
[cases.test_rbyd_supwide_lookup_permutations]
|
||||||
|
defines.N = 'range(1, 7)'
|
||||||
|
defines.SHIFT = [0, 3, -3]
|
||||||
|
# -1 => exhaust all permutations
|
||||||
|
# n => reproduce a specific permutation
|
||||||
|
defines.PERMUTATION = -1
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_init(&lfs, CFG) => 0;
|
||||||
|
|
||||||
|
lfsr_rbyd_t init_rbyd = {
|
||||||
|
.blocks[0] = 0,
|
||||||
|
.eoff = 0,
|
||||||
|
.cksum = 0,
|
||||||
|
.trunk = 0,
|
||||||
|
.weight = 0,
|
||||||
|
};
|
||||||
|
lfsr_rbyd_t rbyd;
|
||||||
|
const uint8_t names[6][4] = {
|
||||||
|
"\xaa\xaa\xaa\xaa",
|
||||||
|
"\xbb\xbb\xbb\xbb",
|
||||||
|
"\xcc\xcc\xcc\xcc",
|
||||||
|
"\xdd\xdd\xdd\xdd",
|
||||||
|
"\xee\xee\xee\xee",
|
||||||
|
"\xff\xff\xff\xff",
|
||||||
|
};
|
||||||
|
|
||||||
|
// test all permutations of a given size
|
||||||
|
size_t perm_count = TEST_FACTORIAL(N);
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < ((PERMUTATION == -1) ? perm_count : 1);
|
||||||
|
i++) {
|
||||||
|
uint32_t perm[N];
|
||||||
|
size_t perm_i = (PERMUTATION == -1) ? i : (size_t)PERMUTATION;
|
||||||
|
TEST_PERMUTATION(perm_i, perm, N);
|
||||||
|
|
||||||
|
// print permutation to help debugging
|
||||||
|
printf("--- permutation: %zd [", perm_i);
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
if (j > 0) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
printf("%d", perm[j]);
|
||||||
|
}
|
||||||
|
printf("] ---\n");
|
||||||
|
|
||||||
|
// build the attribute list for the current permutation
|
||||||
|
rbyd = init_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0;
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
// adjust rid based on future insertions
|
||||||
|
uint16_t rid = perm[j];
|
||||||
|
for (unsigned k = j+1; k < N; k++) {
|
||||||
|
if (perm[j] > perm[k]) {
|
||||||
|
rid -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// give each attr a subtype based on its rid + SHIFT
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
|
LFSR_ATTR(rid, REG, +1, BUF(names[perm[j] % 6], 4)),
|
||||||
|
LFSR_ATTR(rid, UATTR((perm[j] + SHIFT) & 0x7f), 0,
|
||||||
|
BUF(names[perm[j] % 6], 2)))) => 0;
|
||||||
|
}
|
||||||
|
assert(rbyd.weight == N);
|
||||||
|
|
||||||
|
// a supwide attr lookup only gets the file type
|
||||||
|
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0;
|
||||||
|
assert(rbyd.weight == N);
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
lfsr_tag_t tag_;
|
||||||
|
lfsr_data_t data_;
|
||||||
|
lfsr_rbyd_suplookup(&lfs, &rbyd, j,
|
||||||
|
&tag_, &data_) => 0;
|
||||||
|
|
||||||
|
assert(tag_ == LFSR_TAG_REG);
|
||||||
|
assert(lfsr_data_size(&data_) == 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
|
[cases.test_rbyd_supwide_remove_permutations]
|
||||||
|
defines.N = 'range(1, 7)'
|
||||||
|
defines.SHIFT = [0, 3, -3]
|
||||||
|
# -1 => exhaust all permutations
|
||||||
|
# n => reproduce a specific permutation
|
||||||
|
defines.PERMUTATION = -1
|
||||||
|
# large progs take too long for now
|
||||||
|
if = 'PROG_SIZE < 512'
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_init(&lfs, CFG) => 0;
|
||||||
|
|
||||||
|
lfsr_rbyd_t init_rbyd = {
|
||||||
|
.blocks[0] = 0,
|
||||||
|
.eoff = 0,
|
||||||
|
.cksum = 0,
|
||||||
|
.trunk = 0,
|
||||||
|
.weight = 0,
|
||||||
|
};
|
||||||
|
lfsr_rbyd_t rbyd;
|
||||||
|
const uint8_t names[6][4] = {
|
||||||
|
"\xaa\xaa\xaa\xaa",
|
||||||
|
"\xbb\xbb\xbb\xbb",
|
||||||
|
"\xcc\xcc\xcc\xcc",
|
||||||
|
"\xdd\xdd\xdd\xdd",
|
||||||
|
"\xee\xee\xee\xee",
|
||||||
|
"\xff\xff\xff\xff",
|
||||||
|
};
|
||||||
|
|
||||||
|
// test all permutations of a given size
|
||||||
|
size_t perm_count = TEST_FACTORIAL(N);
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < ((PERMUTATION == -1) ? perm_count : 1);
|
||||||
|
i++) {
|
||||||
|
uint32_t perm[N];
|
||||||
|
size_t perm_i = (PERMUTATION == -1) ? i : (size_t)PERMUTATION;
|
||||||
|
TEST_PERMUTATION(perm_i, perm, N);
|
||||||
|
|
||||||
|
// print permutation to help debugging
|
||||||
|
printf("--- permutation: %zd [", perm_i);
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
if (j > 0) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
printf("%d", perm[j]);
|
||||||
|
}
|
||||||
|
printf("] ---\n");
|
||||||
|
|
||||||
|
// create given permutation with multiple commits
|
||||||
|
rbyd = init_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0;
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
// adjust rid based on future insertions
|
||||||
|
uint16_t rid = perm[j];
|
||||||
|
for (unsigned k = j+1; k < N; k++) {
|
||||||
|
if (perm[j] > perm[k]) {
|
||||||
|
rid -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// give each attr a subtype based on its rid + SHIFT
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
|
LFSR_ATTR(rid, REG, +1, BUF(names[perm[j] % 6], 4)),
|
||||||
|
LFSR_ATTR(rid, UATTR((perm[j] + SHIFT) & 0x7f), 0,
|
||||||
|
BUF(names[perm[j] % 6], 2)))) => 0;
|
||||||
|
}
|
||||||
|
assert(rbyd.weight == N);
|
||||||
|
|
||||||
|
// copy block so we can reset after each remove
|
||||||
|
lfsr_rbyd_t backup_rbyd = rbyd;
|
||||||
|
uint8_t *backup_block = malloc(rbyd.eoff);
|
||||||
|
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.eoff,
|
||||||
|
rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0;
|
||||||
|
|
||||||
|
// try removing each tag
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
// print what we are removing to help debugging
|
||||||
|
printf("--- remove: %d ---\n", j);
|
||||||
|
|
||||||
|
rbyd = backup_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0;
|
||||||
|
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
|
||||||
|
rbyd.blocks[0], 0, backup_block, rbyd.eoff,
|
||||||
|
NULL) => 0;
|
||||||
|
lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false,
|
||||||
|
NULL) => 0;
|
||||||
|
|
||||||
|
// remove with a wide tag
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
|
LFSR_ATTR(j, RM(SUPWIDE(UATTR)), 0, NULL()))) => 0;
|
||||||
|
|
||||||
|
// try traversing over the tags
|
||||||
|
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
||||||
|
lfsr_tag_t tag_ = 0;
|
||||||
|
lfs_ssize_t rid_ = -1;
|
||||||
|
lfs_size_t weight_;
|
||||||
|
lfsr_data_t data_;
|
||||||
|
for (unsigned k = 0; k < N; k++) {
|
||||||
|
if (k != j) {
|
||||||
|
lfsr_rbyd_lookupnext(&lfs, &rbyd, rid_, tag_+1,
|
||||||
|
&rid_, &tag_, &weight_, &data_) => 0;
|
||||||
|
assert(rid_ == k);
|
||||||
|
assert(tag_ == LFSR_TAG_REG);
|
||||||
|
assert(weight_ == ((k == j+1) ? 2 : 1));
|
||||||
|
assert(lfsr_data_size(&data_) == 4);
|
||||||
|
|
||||||
|
lfsr_rbyd_lookupnext(&lfs, &rbyd, rid_, tag_+1,
|
||||||
|
&rid_, &tag_, &weight_, &data_) => 0;
|
||||||
|
assert(rid_ == k);
|
||||||
|
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
||||||
|
assert(weight_ == 0);
|
||||||
|
assert(lfsr_data_size(&data_) == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lfsr_rbyd_lookupnext(&lfs, &rbyd, rid_, tag_+1,
|
||||||
|
&rid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT;
|
||||||
|
|
||||||
|
// also test that we can lookup each tag with a wide lookup
|
||||||
|
for (unsigned k = 0; k < N; k++) {
|
||||||
|
if (k == j) {
|
||||||
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
|
&tag_, &data_) => LFS_ERR_NOENT;
|
||||||
|
} else {
|
||||||
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
|
&tag_, &data_) => 0;
|
||||||
|
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
||||||
|
assert(lfsr_data_size(&data_) == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
free(backup_block);
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
# NOTE if we separate physical/logical block sizes we may be able to
|
||||||
|
# use emubd's copy-on-write copy to speed this up significantly
|
||||||
|
[cases.test_rbyd_supwide_replace_permutations]
|
||||||
|
defines.N = 'range(1, 7)'
|
||||||
|
defines.SHIFT = [0, 3, -3]
|
||||||
|
# -1 => exhaust all permutations
|
||||||
|
# n => reproduce a specific permutation
|
||||||
|
defines.PERMUTATION = -1
|
||||||
|
# large progs take too long for now
|
||||||
|
if = 'PROG_SIZE < 512'
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_init(&lfs, CFG) => 0;
|
||||||
|
|
||||||
|
lfsr_rbyd_t init_rbyd = {
|
||||||
|
.blocks[0] = 0,
|
||||||
|
.eoff = 0,
|
||||||
|
.cksum = 0,
|
||||||
|
.trunk = 0,
|
||||||
|
.weight = 0,
|
||||||
|
};
|
||||||
|
lfsr_rbyd_t rbyd;
|
||||||
|
const uint8_t names[6][6] = {
|
||||||
|
"\xaa\xaa\xaa\xaa\xaa\xaa",
|
||||||
|
"\xbb\xbb\xbb\xbb\xbb\xbb",
|
||||||
|
"\xcc\xcc\xcc\xcc\xcc\xcc",
|
||||||
|
"\xdd\xdd\xdd\xdd\xdd\xdd",
|
||||||
|
"\xee\xee\xee\xee\xee\xee",
|
||||||
|
"\xff\xff\xff\xff\xff\xff",
|
||||||
|
};
|
||||||
|
|
||||||
|
// test all permutations of a given size
|
||||||
|
size_t perm_count = TEST_FACTORIAL(N);
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < ((PERMUTATION == -1) ? perm_count : 1);
|
||||||
|
i++) {
|
||||||
|
uint32_t perm[N];
|
||||||
|
size_t perm_i = (PERMUTATION == -1) ? i : (size_t)PERMUTATION;
|
||||||
|
TEST_PERMUTATION(perm_i, perm, N);
|
||||||
|
|
||||||
|
// print permutation to help debugging
|
||||||
|
printf("--- permutation: %zd [", perm_i);
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
if (j > 0) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
printf("%d", perm[j]);
|
||||||
|
}
|
||||||
|
printf("] ---\n");
|
||||||
|
|
||||||
|
// create given permutation with multiple commits
|
||||||
|
rbyd = init_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0;
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
// adjust rid based on future insertions
|
||||||
|
uint16_t rid = perm[j];
|
||||||
|
for (unsigned k = j+1; k < N; k++) {
|
||||||
|
if (perm[j] > perm[k]) {
|
||||||
|
rid -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// give each attr a subtype based on its rid + SHIFT
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
|
LFSR_ATTR(rid, REG, +1, BUF(names[perm[j] % 6], 4)),
|
||||||
|
LFSR_ATTR(rid, UATTR((perm[j] + SHIFT) & 0x7f), 0,
|
||||||
|
BUF(names[perm[j] % 6], 2)))) => 0;
|
||||||
|
}
|
||||||
|
assert(rbyd.weight == N);
|
||||||
|
|
||||||
|
// copy block so we can reset after each remove
|
||||||
|
lfsr_rbyd_t backup_rbyd = rbyd;
|
||||||
|
uint8_t *backup_block = malloc(rbyd.eoff);
|
||||||
|
lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.eoff,
|
||||||
|
rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0;
|
||||||
|
|
||||||
|
// try replacing each tag
|
||||||
|
for (unsigned j = 0; j < N; j++) {
|
||||||
|
// print what we are replacing to help debugging
|
||||||
|
printf("--- replace: %d ---\n", j);
|
||||||
|
|
||||||
|
rbyd = backup_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0;
|
||||||
|
lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false,
|
||||||
|
rbyd.blocks[0], 0, backup_block, rbyd.eoff,
|
||||||
|
NULL) => 0;
|
||||||
|
lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false,
|
||||||
|
NULL) => 0;
|
||||||
|
|
||||||
|
// replace with bitwise inverse
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(
|
||||||
|
LFSR_ATTR(j, SUPWIDE(UATTR(~(j + SHIFT) & 0x7f)), 0,
|
||||||
|
BUF(names[j % 6], 3)))) => 0;
|
||||||
|
|
||||||
|
// try traversing over the tags
|
||||||
|
lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], CFG->block_size) => 0;
|
||||||
|
lfsr_tag_t tag_ = 0;
|
||||||
|
lfs_ssize_t rid_ = -1;
|
||||||
|
lfs_size_t weight_;
|
||||||
|
lfsr_data_t data_;
|
||||||
|
for (unsigned k = 0; k < N; k++) {
|
||||||
|
if (k == j) {
|
||||||
|
lfsr_rbyd_lookupnext(&lfs, &rbyd, rid_, tag_+1,
|
||||||
|
&rid_, &tag_, &weight_, &data_) => 0;
|
||||||
|
assert(rid_ == k);
|
||||||
|
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
||||||
|
assert(weight_ == 1);
|
||||||
|
assert(lfsr_data_size(&data_) == 3);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
lfsr_rbyd_lookupnext(&lfs, &rbyd, rid_, tag_+1,
|
||||||
|
&rid_, &tag_, &weight_, &data_) => 0;
|
||||||
|
assert(rid_ == k);
|
||||||
|
assert(tag_ == LFSR_TAG_REG);
|
||||||
|
assert(weight_ == 1);
|
||||||
|
assert(lfsr_data_size(&data_) == 4);
|
||||||
|
|
||||||
|
lfsr_rbyd_lookupnext(&lfs, &rbyd, rid_, tag_+1,
|
||||||
|
&rid_, &tag_, &weight_, &data_) => 0;
|
||||||
|
assert(rid_ == k);
|
||||||
|
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
||||||
|
assert(weight_ == 0);
|
||||||
|
assert(lfsr_data_size(&data_) == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lfsr_rbyd_lookupnext(&lfs, &rbyd, rid_, tag_+1,
|
||||||
|
&rid_, &tag_, &weight_, &data_) => LFS_ERR_NOENT;
|
||||||
|
|
||||||
|
// also test that we can lookup each tag with a wide lookup
|
||||||
|
for (unsigned k = 0; k < N; k++) {
|
||||||
|
lfsr_rbyd_sublookup(&lfs, &rbyd, k, LFSR_TAG_UATTR,
|
||||||
|
&tag_, &data_) => 0;
|
||||||
|
if (k == j) {
|
||||||
|
assert(tag_ == LFSR_TAG_UATTR(~(k + SHIFT) & 0x7f));
|
||||||
|
assert(lfsr_data_size(&data_) == 3);
|
||||||
|
} else {
|
||||||
|
assert(tag_ == LFSR_TAG_UATTR((k + SHIFT) & 0x7f));
|
||||||
|
assert(lfsr_data_size(&data_) == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
free(backup_block);
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|||||||
Reference in New Issue
Block a user