diff --git a/lfs.c b/lfs.c index d9875f36..87e2cbf9 100644 --- a/lfs.c +++ b/lfs.c @@ -496,7 +496,7 @@ static inline lfs_rtag_t lfs_rtag_parallel(lfs_rtag_t a, lfs_rtag_t b) { return (a & 0x2) == (b & 0x2); } -// operations on attributes in attribute lists +// operations on attribute lists struct lfs_mattr { lfs_tag_t tag; const void *buffer; @@ -515,7 +515,7 @@ struct lfs_rattr { lfs_rtag_t tag; const void *buffer; lfs_size_t size; - struct lfs_rattr *next; + const struct lfs_rattr *next; }; #define LFS_MKRATTR_(...) \ @@ -524,6 +524,33 @@ struct lfs_rattr { #define LFS_MKRATTR(type1, type2, id, buffer, size, next) \ (&(struct lfs_rattr){LFS_MKRTAG(type1, type2, id), buffer, size, next}) + +// operations on pattern lists +enum lfs_fetchpattern_type { + LFS_FETCHPATTERN_NAME = 0, + LFS_FETCHPATTERN_PAIR = 1, +}; + +struct lfs_fetchpattern { + lfs_rtag_t tag; + const void *buffer; + lfs_size_t size; + struct lfs_fetchpattern *next; +}; + +#define LFS_MKRPATTERN_(...) \ + (&(struct lfs_fetchpattern){__VA_ARGS__}) + +#define LFS_MKRPATTERN(type, type1, type2, buffer, size, next) \ + (&(struct lfs_fetchpattern){ \ + LFS_MKRTAG(LFS_FETCHPATTERN_##type | type1, type2, 0), \ + buffer, size, next}) + +static inline uint8_t lfs_fetchpattern_type( + const struct lfs_fetchpattern *pattern) { + return pattern->tag & 0x1; +} + // operations on global state static inline void lfs_gstate_xor(lfs_gstate_t *a, const lfs_gstate_t *b) { for (int i = 0; i < 3; i++) { @@ -868,7 +895,9 @@ static lfs_ssize_t lfs_rbyd_readtag(lfs_t *lfs, return i; } -static int lfs_rbyd_fetch(lfs_t *lfs, lfs_rbyd_t *rbyd, lfs_block_t block) { +static int lfs_rbyd_fetchmatch(lfs_t *lfs, + lfs_rbyd_t *rbyd, lfs_block_t block, + struct lfs_fetchpattern *patterns) { // read the revision count and get the crc started uint32_t rev; int err = lfs_bd_read(lfs, @@ -900,7 +929,7 @@ static int lfs_rbyd_fetch(lfs_t *lfs, lfs_rbyd_t *rbyd, lfs_block_t block) { lfs_size_t size; lfs_ssize_t delta = lfs_rbyd_readtag(lfs, NULL, &lfs->rcache, lfs->cfg->block_size, - block, 0, &tag, &size, &crc); + block, off, &tag, &size, &crc); if (delta < 0) { if (delta == LFS_ERR_INVAL || delta == LFS_ERR_CORRUPT @@ -997,6 +1026,8 @@ static int lfs_rbyd_fetch(lfs_t *lfs, lfs_rbyd_t *rbyd, lfs_block_t block) { rbyd->noff = off; rbyd->crc = crc; } + + off += size; } // no valid commits at all? @@ -1025,6 +1056,10 @@ static int lfs_rbyd_fetch(lfs_t *lfs, lfs_rbyd_t *rbyd, lfs_block_t block) { return 0; } +static int lfs_rbyd_fetch(lfs_t *lfs, lfs_rbyd_t *rbyd, lfs_block_t block) { + return lfs_rbyd_fetchmatch(lfs, rbyd, block, NULL); +} + //static lfs_ssize_t lfs_rbyd_lookup(lfs_t *lfs, lfs_rbyd_t *rbyd, // lfs_rtag_t tag, lfs_off_t *off, lfs_rtag_t *ntag) { // // TODO @@ -1459,7 +1494,7 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, } // succesful commit, check checksum to make sure - uint32_t crc_ = 0; + uint32_t crc_ = rbyd->crc; err = lfs_bd_crc32c(lfs, NULL, &lfs->rcache, off-4, block, rbyd->noff, off-4 - rbyd->noff, &crc_); @@ -1467,9 +1502,6 @@ static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, return err; } - printf("%08x == %08x\n", crc_, crc); - assert(crc_ == crc); - if (crc_ != crc) { // oh no, something went wrong return LFS_ERR_CORRUPT; diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py index dcb48464..dcc8ca9d 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -151,6 +151,7 @@ def main(disk, block_size, block1, block2=None, **args): while j < (block_size if args.get('all') else off): notes = [] + j_ = j v, tag, size, delta = fromtag(data[j:]) if v != popc(crc) & 1: notes.append('v!=%x' % (popc(crc) & 1)) @@ -168,22 +169,22 @@ def main(disk, block_size, block1, block2=None, **args): j += size print('%08x: %-57s%s' % ( - j-delta-size, + j_, '%-22s%s' % ( - tagrepr(tag, size, j), - ' %s' % next(xxd(data[j-size:j-size+min(size, 8)], 8), '') + tagrepr(tag, size, j_), + ' %s' % next(xxd(data[j_+delta:j_+delta+min(size, 8)], 8), '') if not tag & 1 and not args.get('no_truncate') else ''), ' (%s)' % ', '.join(notes) if notes else '')) if args.get('raw'): - for o, line in enumerate(xxd(data[j-delta-size:j-size])): - print('%8s: %s' % ('%04x' % (j-delta-size + o*16), line)) + for o, line in enumerate(xxd(data[j_:j_+delta])): + print('%8s: %s' % ('%04x' % (j_ + o*16), line)) if not tag & 0x1: if args.get('raw') or args.get('no_truncate'): - for o, line in enumerate(xxd(data[j-size:j])): - print('%8s: %s' % ('%04x' % (j-size + o*16), line)) + for o, line in enumerate(xxd(data[j_+delta:j_+delta+size])): + print('%8s: %s' % ('%04x' % (j_+delta + o*16), line)) if __name__ == "__main__": diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index fcf63027..e07d4766 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -1,8 +1,9 @@ # Test this inner rbyd data-structure -[cases.rbyd_create] +[cases.rbyd_commit_fetch] in = 'lfs.c' +defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; @@ -17,12 +18,100 @@ code = ''' .erased = true, }; - //lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; + // try an empty commit + lfs_rbyd_t rbyd_ = rbyd; + lfs_bd_erase(&lfs, rbyd_.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd_, NULL) => 0; + lfs_rbyd_fetch(&lfs, &rbyd_, rbyd.block) => 0; - uint32_t data = 0xa5dfa5df; - lfs_rbyd_commit(&lfs, &rbyd, - LFS_MKRATTR(UATTR, 1, 0, &data, 4, - LFS_MKRATTR(UATTR, 2, 0, &data, 4, + // commit with one attribute + rbyd_ = 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) => 0; + + // commit with two attributes + rbyd_ = 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_fetch(&lfs, &rbyd_, rbyd.block) => 0; +// // commit with three attributes +// rbyd_ = 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, +// LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, +// NULL)))) => 0; +// lfs_rbyd_fetch(&lfs, &rbyd_, rbyd.block) => 0; + + // TODO more? ''' + +[cases.rbyd_multi_commit_fetch] +in = 'lfs.c' +defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t rbyd = { + .block = 0, + .trunk = 0, + .noff = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + + // try an empty commit + lfs_rbyd_t rbyd_ = rbyd; + lfs_bd_erase(&lfs, rbyd_.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd_, NULL) => 0; + lfs_rbyd_fetch(&lfs, &rbyd_, rbyd.block) => 0; + + // commit with one attribute + rbyd_ = rbyd; + lfs_bd_erase(&lfs, rbyd_.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd_, NULL) => 0; + lfs_rbyd_commit(&lfs, &rbyd_, + LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; + lfs_rbyd_fetch(&lfs, &rbyd_, rbyd.block) => 0; + + // commit with two attributes + rbyd_ = 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_fetch(&lfs, &rbyd_, rbyd.block) => 0; + +// // commit with three attributes +// rbyd_ = 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_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL)) => 0; +// lfs_rbyd_fetch(&lfs, &rbyd_, rbyd.block) => 0; + + // TODO more? +''' + + + +# [cases.rbyd_commit_lookup] +# [cases.rbyd_multi_commit_lookup] +# [cases.rbyd_commit_fetchmatch] +# [cases.rbyd_multi_commit_fetchmatch] +# [cases.rbyd_commit_traverse] +# [cases.rbyd_multi_commit_traverse]