Tweaked rbyd deletes, added MKUNR, simplified upper layers

Just like inserting tags (MKBRANCH, MKREG, etc), the interaction with
ids is a bit more intuitive with an implicit +1. To make the internal
implementation consistent, this is can be accomplished by combining
"rm" and "mk" bits into a so-called MKUNR tag.

Describing deletes as "make unreachable" makes a bit of twisted sense,
though I won't argue it's a bit of a stretch.

Worst case, this is device-side only so it can change easily in the
future. We strip the "mk" bits on any tags, so MKUNR turns into a
normal UNR on disk.

Also continued minor refactoring of lfsr_rbyd_append.
This commit is contained in:
Christopher Haster
2023-04-01 16:09:07 -05:00
parent 85bd28951c
commit 9a1675999e
2 changed files with 124 additions and 126 deletions
+61 -63
View File
@@ -450,19 +450,25 @@ static inline lfs_size_t lfs_tag_dsize(lfs_tag_t tag) {
// 16-bit metadata tags
enum lfsr_tag_type {
LFSR_TAG_UNR = 0x0002,
LFSR_TAG_MKUNR = 0x0006, // in-device only
LFSR_TAG_NAME = 0x1000,
LFSR_TAG_BNAME = 0x1000,
LFSR_TAG_MKBNAME = 0x1004, // in-device only
LFSR_TAG_REG = 0x1010,
LFSR_TAG_MKREG = 0x1014, // in-device only
LFSR_TAG_DIR = 0x1020,
LFSR_TAG_MKDIR = 0x1024, // in-device only
LFSR_TAG_STRUCT = 0x3000,
LFSR_TAG_INLINED = 0x3000,
LFSR_TAG_BLOCK = 0x3100,
LFSR_TAG_BRANCH = 0x3200,
LFSR_TAG_MKBRANCH = 0x3204, // in-device only
LFSR_TAG_BTREE = 0x3300,
LFSR_TAG_UATTR = 0x4000,
LFSR_TAG_MKUATTR = 0x4004, // in-device only
LFSR_TAG_RMUATTR = 0x4002,
LFSR_TAG_ALT = 0x0008,
@@ -475,15 +481,9 @@ enum lfsr_tag_type {
LFSR_TAG_FCRC = 0x1004,
// in-device only
LFSR_TAG_MKBNAME = 0x1004,
LFSR_TAG_MKREG = 0x1014,
LFSR_TAG_MKDIR = 0x1024,
LFSR_TAG_MKUATTR = 0x4004,
LFSR_TAG_GROW = 0x0006,
LFSR_TAG_SHRINK = 0x0016,
LFSR_TAG_FROM = 0x0026,
LFSR_TAG_GROW = 0xf000,
LFSR_TAG_SHRINK = 0xf010,
LFSR_TAG_FROM = 0xf020,
};
#define LFSR_TAG_ALT_(color, dir, key) \
@@ -1964,21 +1964,14 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// 0 tags shouldn't be written to disk, use unr if tag is unreachable
LFS_ASSERT(tag != 0);
// we can't do anything if we're not erased
if (!rbyd->erased) {
return LFS_ERR_RANGE;
}
// ignore noops
if (tag == LFSR_TAG_UNR && delta == 0) {
if (lfsr_tag_setnomk(tag) == LFSR_TAG_UNR && delta == 0) {
return 0;
}
// treat weightless mks the same as non-mks, easier to just clear
// the bit here than make sure the following logic works out
if (lfsr_tag_ismk(tag) && delta <= 0) {
LFS_ASSERT(delta >= 0);
tag = lfsr_tag_setnomk(tag);
// we can't do anything if we're not erased
if (!rbyd->erased) {
return LFS_ERR_RANGE;
}
// make sure every rbyd starts with its revision count
@@ -1993,6 +1986,47 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
}
}
// figure out the range of tags we're operating on
lfs_ssize_t id_;
lfs_ssize_t other_id_;
lfsr_tag_t tag_;
lfsr_tag_t other_tag_;
if (lfsr_tag_ismk(tag) && delta > 0) {
LFS_ASSERT(id <= rbyd->weight);
// it's a bit ugly, but adjusting the id here makes the following
// logic work out more consistently
id -= 1;
id_ = id + 1;
other_id_ = id + 1;
tag_ = 0;
other_tag_ = 0;
} else if (lfsr_tag_ismk(tag) && delta < 0) {
LFS_ASSERT(id < rbyd->weight);
// it's a bit ugly, but adjusting the id here makes the following
// logic work out more consistently
id += 1;
id_ = id - lfs_smax32(-delta, 0);
other_id_ = id;
tag_ = 0;
other_tag_ = 0;
} else if (lfsr_tag_isrm(tag)) {
LFS_ASSERT(id < rbyd->weight);
id_ = id - lfs_smax32(-delta, 0);
other_id_ = id;
tag_ = tag & ~0x2;
other_tag_ = (tag & ~0x2) + 0x10;
} else {
LFS_ASSERT(id < rbyd->weight);
id_ = id - lfs_smax32(-delta, 0);
other_id_ = id;
tag_ = tag;
other_tag_ = tag;
}
// keep track of bounds as we descend down the tree
//
// this gets a bit confusing as we also may need to keep
@@ -2004,47 +2038,6 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfsr_tag_t lower_tag = 0;
lfsr_tag_t upper_tag = 0xffff;
// figure out the range of tags we're operating on and go ahead and
// update the rbyd's weight
//
// note lfsr_rbyd_commit will throw out this copy of the rbyd if an
// error occurs
lfs_ssize_t id_;
lfs_ssize_t other_id_;
lfsr_tag_t tag_;
lfsr_tag_t other_tag_;
if (lfsr_tag_ismk(tag) && delta > 0) {
LFS_ASSERT(id < rbyd->weight+delta);
LFS_ASSERT(delta >= -(lfs_ssize_t)rbyd->weight);
rbyd->weight += delta;
// it's a bit ugly, but adjusting the id here makes the following
// logic work out more consistently
id -= delta;
id_ = id + 1;
other_id_ = id + 1;
tag_ = 0;
other_tag_ = 0;
} else if (lfsr_tag_isrm(tag)) {
LFS_ASSERT(id <= rbyd->weight);
LFS_ASSERT(delta >= -(lfs_ssize_t)rbyd->weight);
rbyd->weight += delta;
id_ = id - lfs_smax32(-delta, 0);
other_id_ = id;
tag_ = tag & ~0x2;
other_tag_ = (tag & ~0x2) + 0x10;
} else {
LFS_ASSERT(id < rbyd->weight);
LFS_ASSERT(delta >= -(lfs_ssize_t)rbyd->weight);
rbyd->weight += delta;
id_ = id - lfs_smax32(-delta, 0);
other_id_ = id;
tag_ = tag;
other_tag_ = tag;
}
// diverged state in case we are removing a range from the tree
//
// this is a second copy of the search path state, used to keep track
@@ -2066,6 +2059,11 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfsr_tag_t other_lower_tag = 0;
lfsr_tag_t other_upper_tag = 0;
// go ahead and update the rbyd's weight, note that lfsr_rbyd_commit
// will through out this copy of the rbyd if an error occurs
LFS_ASSERT(delta >= -(lfs_ssize_t)rbyd->weight);
rbyd->weight += delta;
// assume we'll update our trunk
rbyd->trunk = rbyd->off;
@@ -2343,7 +2341,7 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
} else if (id_ < id-lfs_smax32(-delta, 0)
|| (id_ == id-lfs_smax32(-delta, 0)
&& (lfsr_tag_ismk(tag)
&& ((lfsr_tag_ismk(tag) && delta > 0)
|| lfsr_tag_key(tag_) < lfsr_tag_key(tag)))) {
if (lfsr_tag_isrm(tag)) {
// if removed make our tag unreachable
@@ -2357,7 +2355,7 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd,
} else if (id_ > id
|| (id_ == id
&& (lfsr_tag_ismk(tag)
&& ((lfsr_tag_ismk(tag) && delta > 0)
|| lfsr_tag_key(tag_) > lfsr_tag_key(tag)))) {
if (lfsr_tag_isrm(tag)) {
// if removed make our tag unreachable