Added the ability to remove rbyd tags via tombstoning

It's quite lucky a spare bit is free in the tag encoding, this means we
don't need a reserved length value as originally planned. We end up using
all of the bits that overlap the alt pointer encoding, which is nice and
unexpected.
This commit is contained in:
Christopher Haster
2022-12-28 02:12:32 -06:00
parent 2b475662e9
commit 5cdda57373
4 changed files with 558 additions and 118 deletions
+30 -8
View File
@@ -424,6 +424,8 @@ enum lfs_rtag_type1 {
LFS_TYPE1_CRC1 = 0x03,
LFS_TYPE1_FCRC = 0x0a,
LFS_TYPE1_RM = 0x01,
LFS_TYPE1_ALTBLT = 0x04,
LFS_TYPE1_ALTRLT = 0x05,
LFS_TYPE1_ALTBGT = 0x06,
@@ -444,6 +446,12 @@ enum lfs_rtag_type1 {
#define LFS_MKRTAG(type1, type2, id) \
LFS_MKRTAG_(LFS_TYPE1_##type1, type2, id)
#define LFS_MKRRMTAG_(type1, type2, id) \
LFS_MKRTAG_(LFS_TYPE1_RM | (type1), type2, id)
#define LFS_MKRRMTAG(type1, type2, id) \
LFS_MKRRMTAG_(LFS_TYPE1_##type1, type2, id)
#define LFS_MKRALT_(color, dir, weight) \
(LFS_TYPE1_ALTBLT \
| ((0x1 & (lfs_rtag_t)(color)) << 0) \
@@ -466,6 +474,10 @@ static inline bool lfs_rtag_intree(lfs_rtag_t tag) {
return !(tag & 0x2);
}
static inline bool lfs_rtag_isrm(lfs_rtag_t tag) {
return tag & 0x1;
}
static inline uint8_t lfs_rtag_type1(lfs_rtag_t tag) {
return tag & 0x7f;
}
@@ -599,6 +611,9 @@ struct lfs_rattr {
#define LFS_MKRATTR(type1, type2, id, buffer, size, next) \
(&(struct lfs_rattr){LFS_MKRTAG(type1, type2, id), buffer, size, next})
#define LFS_MKRRMATTR(type1, type2, id, next) \
(&(struct lfs_rattr){LFS_MKRRMTAG(type1, type2, id), NULL, 0, next})
// operations on pattern lists
enum lfs_fetchpattern_type {
@@ -992,7 +1007,7 @@ static int lfs_rbyd_fetch(lfs_t *lfs,
rbyd->block = block;
rbyd->rev = lfs_fromle32_(&rev);
rbyd->trunk = 0;
rbyd->noff = 0;
rbyd->off = 0;
// assume unerased until proven otherwise
bool maybeerased = false;
@@ -1100,7 +1115,7 @@ static int lfs_rbyd_fetch(lfs_t *lfs,
// save what we've found so far
printf("trunk => %x\n", trunk);
rbyd->trunk = trunk;
rbyd->noff = off;
rbyd->off = off;
rbyd->crc = crc;
}
@@ -1108,20 +1123,20 @@ static int lfs_rbyd_fetch(lfs_t *lfs,
}
// no valid commits at all?
if (rbyd->noff == 0) {
if (rbyd->off == 0) {
return LFS_ERR_CORRUPT;
}
// did we end on a valid commit? we may have an erased block
rbyd->erased = false;
if (maybeerased && hasfcrc && rbyd->noff % lfs->cfg->prog_size == 0) {
if (maybeerased && hasfcrc && rbyd->off % lfs->cfg->prog_size == 0) {
// check for an fcrc matching the next prog's erased state, if
// this failed most likely a previous prog was interrupted, we
// need a new erase
uint32_t fcrc_ = 0xffffffff;
int err = lfs_bd_crc32c(lfs,
NULL, &lfs->rcache, lfs->cfg->block_size,
rbyd->block, rbyd->noff, fcrc.size, &fcrc_);
rbyd->block, rbyd->off, fcrc.size, &fcrc_);
if (err && err != LFS_ERR_CORRUPT) {
return err;
}
@@ -1136,6 +1151,7 @@ static int lfs_rbyd_fetch(lfs_t *lfs,
static lfs_srtag_t lfs_rbyd_lookup(lfs_t *lfs, const lfs_rbyd_t *rbyd,
lfs_rtag_t tag, lfs_off_t *off, lfs_size_t *size) {
printf("lookup(%08x)\n", tag);
tryagain:;
// no trunk yet?
lfs_off_t branch = rbyd->trunk;
if (!branch) {
@@ -1174,6 +1190,12 @@ static lfs_srtag_t lfs_rbyd_lookup(lfs_t *lfs, const lfs_rbyd_t *rbyd,
// update the tag id
lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag));
// was removed? go on to the next tag
if (lfs_rtag_isrm(tag_)) {
tag = lfs_rtag_inc(tag_);
goto tryagain;
}
printf("lt, gt = (%x, %x)\n", lt, gt);
printf("lookup %08x => %08x (raw %08x)\n", tag, tag_, alt);
@@ -1362,7 +1384,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd,
const lfs_block_t block = rbyd->block;
lfs_off_t trunk = rbyd->trunk;
uint16_t count = rbyd->count;
lfs_off_t off = rbyd->noff;
lfs_off_t off = rbyd->off;
uint32_t crc = rbyd->crc;
bool erased = false;
@@ -1707,7 +1729,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd,
uint32_t crc_ = rbyd->crc;
err = lfs_bd_crc32c(lfs,
NULL, &lfs->rcache, off-4,
block, rbyd->noff, off-4 - rbyd->noff, &crc_);
block, rbyd->off, off-4 - rbyd->off, &crc_);
if (err) {
return err;
}
@@ -1720,7 +1742,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd,
// ok, everything is good, save what we've committed
rbyd->trunk = trunk;
rbyd->noff = aligned;
rbyd->off = aligned;
rbyd->crc = crc;
rbyd->erased = erased;
+1 -1
View File
@@ -330,7 +330,7 @@ typedef struct lfs_cache {
typedef struct lfs_rbyd {
lfs_block_t block;
lfs_off_t trunk;
lfs_off_t noff;
lfs_off_t off;
uint32_t rev;
uint32_t crc;
uint16_t count;
+41 -23
View File
@@ -45,31 +45,49 @@ def tagrepr(tag, size, off=None):
type2 = (tag >> 7) & 0xff
id = (tag >> 15) & 0xffff
if type1 == 0x40:
return 'create x%02x id%d %d' % (type2, id, size)
elif type1 == 0x48:
return 'delete x%02x id%d %d' % (type2, id, size)
elif type1 == 0x50:
return 'struct x%02x id%d %d' % (type2, id, size)
elif type1 == 0x60:
return 'uattr x%02x id%d %d' % (type2, id, size)
elif type1 == 0x08:
if type2 == 0:
return 'tail %d' % size
else:
return 'tail x%02x %d' % (type2, size)
elif type1 == 0x10:
return 'gstate x%02x %d' % (type2, size)
if (type1 & 0x7e) == 0x40:
return '%screate x%02x id%d%s' % (
'~' if type1 & 0x1 else '',
type2,
id,
' %d' % size if not type1 & 0x1 else '')
elif (type1 & 0x7e) == 0x48:
return '%sdelete x%02x id%d%s' % (
'~' if type1 & 0x1 else '',
type2,
id,
' %d' % size if not type1 & 0x1 else '')
elif (type1 & 0x7e) == 0x50:
return '%sstruct x%02x id%d%s' % (
'~' if type1 & 0x1 else '',
type2,
id,
' %d' % size if not type1 & 0x1 else '')
elif (type1 & 0x7e) == 0x60:
return '%suattr x%02x id%d%s' % (
'~' if type1 & 0x1 else '',
type2,
id,
' %d' % size if not type1 & 0x1 else '')
elif (type1 & 0x7e) == 0x08:
return '%stail%s%s' % (
'~' if type1 & 0x1 else '',
' x%02x' % type2 if type2 else '',
' %d' % size if not type1 & 0x1 else '')
elif (type1 & 0x7e) == 0x10:
return '%sgstate x%02x%s' % (
'~' if type1 & 0x1 else '',
type2,
' %d' % size if not type1 & 0x1 else '')
elif (type1 & 0x7e) == 0x02:
if type2 == 0:
return 'crc%x %d' % (type1 >> 3, size)
else:
return 'crc%x x%02x %d' % (type1 >> 3, type2, size)
return 'crc%x%s %d' % (
type1 >> 3,
' x%02x' % type2 if type2 else '',
size)
elif type1 == 0x0a:
if type2 == 0:
return 'fcrc %d' % (size)
else:
return 'fcrc x%02x %d' % (type2, size)
return 'fcrc%s %d' % (
' x%02x' % type2 if type2 else '',
size)
elif type1 & 0x4:
return 'alt%s%s x%x %s' % (
'r' if type1 & 1 else 'b',
+486 -86
View File
File diff suppressed because it is too large Load Diff