From 5cdda57373679099e798035b7630b83b612989cf Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 28 Dec 2022 02:12:32 -0600 Subject: [PATCH] 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. --- lfs.c | 38 ++- lfs.h | 2 +- scripts/dbgrbyd.py | 64 +++-- tests/test_rbyd.toml | 572 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 558 insertions(+), 118 deletions(-) diff --git a/lfs.c b/lfs.c index a950ef01..7f60b896 100644 --- a/lfs.c +++ b/lfs.c @@ -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; diff --git a/lfs.h b/lfs.h index 8a60f649..2558fb13 100644 --- a/lfs.h +++ b/lfs.h @@ -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; diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py index cfaa54c6..ff1cce0a 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -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', diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index c07b6270..f92b7f68 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -10,10 +10,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -22,20 +22,20 @@ code = ''' lfs_rbyd_t rbyd; // try an empty commit - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with one attribute - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with two attributes - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -49,10 +49,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -61,13 +61,13 @@ code = ''' lfs_rbyd_t rbyd; // try an empty commit - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with one attribute - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -75,7 +75,7 @@ code = ''' lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with two attributes - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; @@ -93,10 +93,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -107,7 +107,7 @@ code = ''' lfs_size_t size; // try an empty commit - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; @@ -119,7 +119,7 @@ code = ''' => LFS_ERR_NOENT; // commit with one attribute - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; @@ -136,7 +136,7 @@ code = ''' => LFS_ERR_NOENT; // commit with two attributes - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -164,10 +164,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -178,7 +178,7 @@ code = ''' lfs_size_t size; // try an empty commit - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; @@ -190,7 +190,7 @@ code = ''' => LFS_ERR_NOENT; // commit with one attribute - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; @@ -207,7 +207,7 @@ code = ''' => LFS_ERR_NOENT; // commit with two attributes - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; @@ -236,10 +236,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -253,8 +253,8 @@ code = ''' // traverse requires correct biasing of the weights in the rbyd tree // so that lookups return strictly the tag greater than or equal to // the tag requested - rbyd = rbyd_init; - rbyd = rbyd_init; + rbyd = init_rbyd; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -282,10 +282,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -299,8 +299,8 @@ code = ''' // traverse requires correct biasing of the weights in the rbyd tree // so that lookups return strictly the tag greater than or equal to // the tag requested - rbyd = rbyd_init; - rbyd = rbyd_init; + rbyd = init_rbyd; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; @@ -329,10 +329,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -346,7 +346,7 @@ code = ''' // .-'| // 1 1 2 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -362,7 +362,7 @@ code = ''' // >b // => .-'| // 2 2 1 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, @@ -381,10 +381,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -398,7 +398,7 @@ code = ''' // .----'| // 1 2 1 2 2 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -415,7 +415,7 @@ code = ''' // b // .-'| => .-'| // 1 2 1 2 1 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -435,10 +435,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -454,7 +454,7 @@ code = ''' // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -475,7 +475,7 @@ code = ''' // | >b // .-'| .--|-'| // 2 3 2 3 1 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, @@ -498,10 +498,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -517,7 +517,7 @@ code = ''' // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -539,7 +539,7 @@ code = ''' // | | >b // | .-'| | .-'| // 1 2 3 1 2 3 2 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -561,7 +561,7 @@ code = ''' // | | >b // | .-'| .--|-'| // 1 2 3 1 2 3 1 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -583,7 +583,7 @@ code = ''' // | >b => | >b // .--|-'| | .-'| // 3 1 2 3 1 2 1 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, @@ -606,10 +606,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -627,7 +627,7 @@ code = ''' // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -653,7 +653,7 @@ code = ''' // | b | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -679,7 +679,7 @@ code = ''' // | b // | .-'| .--|--|-'| // 2 3 4 2 3 4 1 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, @@ -705,7 +705,7 @@ code = ''' // | >b | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, @@ -730,10 +730,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -751,7 +751,7 @@ code = ''' // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -777,7 +777,7 @@ code = ''' // | b // | .-'| | | .-'| // 1 2 4 1 2 4 3 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -803,7 +803,7 @@ code = ''' // | >b | | b // | .-'| | | .-'| | .--|-'| // 1 4 2 1 4 2 3 1 4 2 3 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -829,7 +829,7 @@ code = ''' // | b // | .-'| | | .-'| .--|--|-'| // 4 1 2 4 1 2 3 4 1 2 3 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -854,10 +854,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -877,7 +877,7 @@ code = ''' // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -906,7 +906,7 @@ code = ''' // | | b // | | .-'| | | .-'| // 1 2 3 4 1 2 3 4 3 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -933,7 +933,7 @@ code = ''' // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -960,7 +960,7 @@ code = ''' // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -986,10 +986,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -1011,7 +1011,7 @@ code = ''' // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1044,7 +1044,7 @@ code = ''' // | | b // | | .-'| | | .--|-'| // 1 2 4 5 1 2 4 5 3 - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1075,7 +1075,7 @@ code = ''' // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1106,7 +1106,7 @@ code = ''' // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, @@ -1134,10 +1134,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -1159,7 +1159,7 @@ code = ''' // | | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1193,7 +1193,7 @@ code = ''' // | | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1227,7 +1227,7 @@ code = ''' // | | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1256,10 +1256,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -1283,7 +1283,7 @@ code = ''' // | | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1319,7 +1319,7 @@ code = ''' // | | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, @@ -1355,7 +1355,7 @@ code = ''' // | | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, @@ -1387,10 +1387,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -1430,7 +1430,7 @@ code = ''' } // test the given permutation - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, attrs) => 0; @@ -1468,10 +1468,10 @@ code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; - lfs_rbyd_t rbyd_init = { + lfs_rbyd_t init_rbyd = { .block = 0, .trunk = 0, - .noff = 0, + .off = 0, .rev = 1, .crc = 0, .count = 0, @@ -1502,7 +1502,7 @@ code = ''' printf("] ---\n"); // test the given permutation with multiple commits - rbyd = rbyd_init; + rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; for (int j = 0; j < N; j++) { @@ -1538,3 +1538,403 @@ code = ''' } } ''' + + +### removal testing ### + +[cases.test_rbyd_remove] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t init_rbyd = { + .block = 0, + .trunk = 0, + .off = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + lfs_rbyd_t rbyd; + lfs_off_t off; + lfs_size_t size; + + // add and remove one attribute + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0; + + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + + // commit with two attributes, remove the first one + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, + LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0; + + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; + + // commit with two attributes, remove the second one + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, + LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, 2, 0, NULL)) => 0; + + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; +''' + +[cases.test_rbyd_multi_remove] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t init_rbyd = { + .block = 0, + .trunk = 0, + .off = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + lfs_rbyd_t rbyd; + lfs_off_t off; + lfs_size_t size; + + // add and remove one attribute + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0; + + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + + // commit with two attributes, remove the first one + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0; + + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_MKRTAG(UATTR, 2, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; + + // commit with two attributes, remove the second one + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, 2, 0, NULL)) => 0; + + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) + => LFS_MKRTAG(UATTR, 1, 0); + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) + => LFS_ERR_NOENT; + lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) + => LFS_ERR_NOENT; +''' + +[cases.test_rbyd_remove_permutations] +defines.N = 'range(1, 7)' +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t init_rbyd = { + .block = 0, + .trunk = 0, + .off = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + lfs_rbyd_t rbyd; + lfs_off_t off; + lfs_size_t size; + + // test all permutations of a given size + uint8_t perm[N]; + uint8_t stack[N]; + for (uint8_t i = 0; i < N; i++) { + perm[i] = i; + stack[i] = 0; + } + + uint8_t i = 1; + while (i < N) { + // print permutation to help debugging + printf("--- permutation: ["); + for (int j = 0; j < N; j++) { + if (j > 0) { + printf(", "); + } + printf("%d", perm[j]+1); + } + printf("] ---\n"); + + // build the attribute list for the current permutation + struct lfs_rattr attrs[N]; + for (int j = 0; j < N; j++) { + attrs[j] = *LFS_MKRATTR( + UATTR, perm[j]+1, 0, + &(uint32_t){0xaaaaaaaa}, 4, + (j+1 < N) ? &attrs[j+1] : NULL); + } + + // create the given permutation + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, attrs) => 0; + + // copy block so we can reset after each remove + lfs_rbyd_t backup_rbyd = rbyd; + uint8_t backup_block[BLOCK_SIZE]; + lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + // try removing each tag + for (int j = 0; j < N; j++) { + // print what we are removing to help debugging + printf("--- remove: %d ---\n", j+1); + + rbyd = backup_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, j+1, 0, NULL)) => 0; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + for (int k = 0; k < N; k++) { + lfs_srtag_t tag = lfs_rbyd_lookup(&lfs, &rbyd, + LFS_MKRTAG(UATTR, k+1, 0), &off, &size); + if (k == j) { + if (j == N-1) { + assert(tag == LFS_ERR_NOENT); + } else { + assert(tag == LFS_MKRTAG(UATTR, j+1+1, 0)); + } + } else { + assert(tag == LFS_MKRTAG(UATTR, k+1, 0)); + } + } + } + + // next permutation using Heap's algorithm + if (stack[i] < i) { + if (i % 2 == 0) { + uint8_t t = perm[0]; + perm[0] = perm[i]; + perm[i] = t; + } else { + uint8_t t = perm[stack[i]]; + perm[stack[i]] = perm[i]; + perm[i] = t; + } + stack[i] += 1; + i = 1; + } else { + stack[i] = 0; + i += 1; + } + } +''' + +[cases.test_rbyd_multi_remove_permutations] +defines.N = 'range(1, 7)' +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t init_rbyd = { + .block = 0, + .trunk = 0, + .off = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + lfs_rbyd_t rbyd; + lfs_off_t off; + lfs_size_t size; + + // test all permutations of a given size + uint8_t perm[N]; + uint8_t stack[N]; + for (uint8_t i = 0; i < N; i++) { + perm[i] = i; + stack[i] = 0; + } + + uint8_t i = 1; + while (i < N) { + // print permutation to help debugging + printf("--- permutation: ["); + for (int j = 0; j < N; j++) { + if (j > 0) { + printf(", "); + } + printf("%d", perm[j]+1); + } + printf("] ---\n"); + + // create given permutation with multiple commits + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + + for (int j = 0; j < N; j++) { + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR( + UATTR, perm[j]+1, 0, + &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; + } + + // copy block so we can reset after each remove + lfs_rbyd_t backup_rbyd = rbyd; + uint8_t backup_block[BLOCK_SIZE]; + lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + // try removing each tag + for (int j = 0; j < N; j++) { + // print what we are removing to help debugging + printf("--- remove: %d ---\n", j+1); + + rbyd = backup_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRRMATTR(UATTR, j+1, 0, NULL)) => 0; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + for (int k = 0; k < N; k++) { + lfs_srtag_t tag = lfs_rbyd_lookup(&lfs, &rbyd, + LFS_MKRTAG(UATTR, k+1, 0), &off, &size); + if (k == j) { + if (j == N-1) { + assert(tag == LFS_ERR_NOENT); + } else { + assert(tag == LFS_MKRTAG(UATTR, j+1+1, 0)); + } + } else { + assert(tag == LFS_MKRTAG(UATTR, k+1, 0)); + } + } + } + + // next permutation using Heap's algorithm + if (stack[i] < i) { + if (i % 2 == 0) { + uint8_t t = perm[0]; + perm[0] = perm[i]; + perm[i] = t; + } else { + uint8_t t = perm[stack[i]]; + perm[stack[i]] = perm[i]; + perm[i] = t; + } + stack[i] += 1; + i = 1; + } else { + stack[i] = 0; + i += 1; + } + } +'''