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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user