diff --git a/lfs.c b/lfs.c index 5b0a4bdc..8c316fe7 100644 --- a/lfs.c +++ b/lfs.c @@ -764,7 +764,8 @@ enum lfsr_tag { // checksum tags LFSR_TAG_CKSUM = 0x3000, - LFSR_TAG_ECKSUM = 0x3100, + LFSR_TAG_PERTURB = 0x3100, + LFSR_TAG_ECKSUM = 0x3200, // in-device only tags, these should never get written to disk LFSR_TAG_INTERNAL = 0x0800, @@ -1046,40 +1047,28 @@ static inline bool lfsr_tag_diverging2( // total: <=11 bytes #define LFSR_TAG_DSIZE (2+5+4) -static lfs_ssize_t lfsr_bd_readtag(lfs_t *lfs, +static lfs_ssize_t lfsr_bd_readtag_(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfs_size_t hint, lfsr_tag_t *tag_, lfsr_rid_t *weight_, lfs_size_t *size_, uint32_t *cksum_) { // read the largest possible tag size uint8_t tag_buf[LFSR_TAG_DSIZE]; lfs_size_t tag_dsize = lfs_min32(LFSR_TAG_DSIZE, lfs->cfg->block_size-off); + if (tag_dsize < 4) { + return LFS_ERR_CORRUPT; + } + int err = lfsr_bd_read(lfs, block, off, hint, &tag_buf, tag_dsize); if (err) { LFS_ASSERT(err < 0); return err; } - if (tag_dsize < 2) { - return LFS_ERR_CORRUPT; - } lfsr_tag_t tag = ((lfsr_tag_t)tag_buf[0] << 8) | ((lfsr_tag_t)tag_buf[1] << 0); lfs_ssize_t d = 2; - if (cksum_) { - // on-disk, the tags valid bit must reflect the parity of the - // preceding data, fortunately for crc32c, this is the same as the - // parity of the crc - // - // note we need to do this before leb128 decoding as we may not have - // valid leb128 if we're erased, but we shouldn't treat a truncated - // leb128 here as corruption - if ((tag >> 15) != (lfs_popc(*cksum_) & 1)) { - return LFS_ERR_INVAL; - } - } - lfsr_rid_t weight; lfs_ssize_t d_ = lfs_fromleb128(&weight, &tag_buf[d], tag_dsize-d); if (d_ < 0) { @@ -1098,19 +1087,36 @@ static lfs_ssize_t lfsr_bd_readtag(lfs_t *lfs, LFS_ASSERT(size <= 0x0fffffff); d += d_; - // optional checksum + // ignore the valid bit when calculating optional checksum + tag_buf[0] &= ~0x80; if (cksum_) { *cksum_ = lfs_crc32c(*cksum_, tag_buf, d); } - // save what we found, clearing the valid bit from the tag, note we - // checked this earlier - *tag_ = tag & 0x7fff; + // save what we found + *tag_ = tag; *weight_ = weight; *size_ = size; return d; } +// clear the valid bit, since most readtag calls don't care +static lfs_ssize_t lfsr_bd_readtag(lfs_t *lfs, + lfs_block_t block, lfs_size_t off, lfs_size_t hint, + lfsr_tag_t *tag_, lfsr_rid_t *weight_, lfs_size_t *size_, + uint32_t *cksum_) { + lfs_ssize_t d = lfsr_bd_readtag_(lfs, block, off, hint, + tag_, weight_, size_, cksum_); + if (d < 0) { + return d; + } + + if (tag_) { + *tag_ &= 0x7fff; + } + return d; +} + static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfsr_tag_t tag, lfsr_rid_t weight, lfs_size_t size, @@ -1122,9 +1128,6 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, // size should not exceed 28-bits LFS_ASSERT(size <= 0x0fffffff); - // make sure to include the parity of the current crc - tag |= (lfs_popc(*cksum_) & 1) << 15; - // encode into a be16 and pair of leb128s uint8_t tag_buf[LFSR_TAG_DSIZE]; tag_buf[0] = (uint8_t)(tag >> 8); @@ -1144,12 +1147,18 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, d += d_; int err = lfsr_bd_prog(lfs, block, off, &tag_buf, d, - cksum_); + NULL); if (err) { LFS_ASSERT(err < 0); return err; } + // ignore the valid bit when calculating optional checksum + tag_buf[0] &= ~0x80; + if (cksum_) { + *cksum_ = lfs_crc32c(*cksum_, tag_buf, d); + } + return d; } @@ -1738,30 +1747,6 @@ typedef struct lfsr_tinfo { //#endif -// erased-state checksum stuff - -static int lfsr_ecksum_validate(lfs_t *lfs, const lfsr_ecksum_t *ecksum, - lfs_block_t block, lfs_size_t off) { - LFS_ASSERT(ecksum->cksize != -1); - LFS_ASSERT(off < lfs->cfg->block_size); - - // check that erased-state matches our checksum, if this fails - // most likely a write was interrupted - uint32_t cksum_ = 0; - int err = lfsr_bd_cksum(lfs, block, off, 0, ecksum->cksize, - &cksum_); - if (err) { - return err; - } - - // ecksum mismatch? - if (cksum_ != ecksum->cksum) { - return LFS_ERR_CORRUPT; - } - - return 0; -} - // erased-state checksum on-disk encoding // ecksum encoding: @@ -2170,6 +2155,7 @@ static void lfs_alloc_ckpoint(lfs_t *lfs); /// Red-black-yellow Dhara tree operations /// #define LFSR_RBYD_ISSHRUB 0x80000000 +#define LFSR_RBYD_PARITY 0x80000000 // helper functions static inline bool lfsr_rbyd_isshrub(const lfsr_rbyd_t *rbyd) { @@ -2188,6 +2174,14 @@ static inline bool lfsr_rbyd_isfetched(const lfsr_rbyd_t *rbyd) { return !(lfsr_rbyd_hastrunk(rbyd) && rbyd->eoff == 0); } +static inline bool lfsr_rbyd_parity(const lfsr_rbyd_t *rbyd) { + return (lfs_size_t)rbyd->eoff >> (8*sizeof(lfs_size_t)-1); +} + +static inline lfs_size_t lfsr_rbyd_eoff(const lfsr_rbyd_t *rbyd) { + return rbyd->eoff & ~LFSR_RBYD_PARITY; +} + static inline int lfsr_rbyd_cmp( const lfsr_rbyd_t *a, const lfsr_rbyd_t *b) { @@ -2212,6 +2206,11 @@ static int lfsr_rbyd_alloc(lfs_t *lfs, lfsr_rbyd_t *rbyd) { static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfs_block_t block, lfs_ssize_t trunk) { + // set up some initial state + rbyd->blocks[0] = block; + rbyd->trunk = (trunk & LFSR_RBYD_ISSHRUB) | 0; + rbyd->eoff = 0; + // ignore the shrub bit here trunk &= ~LFSR_RBYD_ISSHRUB; @@ -2223,15 +2222,12 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, return err; } - rbyd->blocks[0] = block; - rbyd->eoff = 0; - rbyd->trunk = (trunk & LFSR_RBYD_ISSHRUB) | 0; - // temporary state until we validate a cksum + uint32_t cksum_ = cksum; + bool parity_ = lfs_popc(cksum) & 1; lfs_size_t off = sizeof(uint32_t); lfs_size_t trunk_ = 0; lfs_size_t trunk__ = 0; - bool wastrunk = false; lfsr_rid_t weight = 0; lfsr_rid_t weight_ = 0; @@ -2240,96 +2236,110 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, // scan tags, checking valid bits, cksums, etc while (off < lfs->cfg->block_size - && (!trunk || rbyd->eoff <= (lfs_size_t)trunk)) { + && (!trunk || lfsr_rbyd_eoff(rbyd) <= (lfs_size_t)trunk)) { lfsr_tag_t tag; lfsr_rid_t weight__; lfs_size_t size; - lfs_ssize_t d = lfsr_bd_readtag(lfs, block, off, -1, - &tag, &weight__, &size, &cksum); + uint32_t cksum__ = cksum_; + lfs_ssize_t d = lfsr_bd_readtag_(lfs, block, off, -1, + &tag, &weight__, &size, &cksum__); if (d < 0) { - if (d == LFS_ERR_INVAL || d == LFS_ERR_CORRUPT) { - // if we are breaking for any reason other than the tag's - // valid bit, our ecksum must be invalid - if (d != LFS_ERR_INVAL) { - ecksum.cksize = -1; - } + if (d == LFS_ERR_CORRUPT) { break; } return d; } lfs_size_t off_ = off + d; + // parity mismatch? + if ((tag >> 15) != parity_) { + break; + } + tag &= 0x7fff; + parity_ ^= lfs_popc(cksum_ ^ cksum__) & 1; + cksum_ = cksum__; + // tag goes out of range? if (!lfsr_tag_isalt(tag) && off_ + size > lfs->cfg->block_size) { break; } - // not an end-of-commit cksum - if (!lfsr_tag_isalt(tag) && lfsr_tag_suptype(tag) != LFSR_TAG_CKSUM) { - // cksum the entry, hopefully leaving it in the cache - err = lfsr_bd_cksum(lfs, block, off_, -1, size, - &cksum); - if (err) { - if (err == LFS_ERR_CORRUPT) { - break; - } - return err; - } - - // found an ecksum? save for later - if (tag == LFSR_TAG_ECKSUM) { - err = lfsr_data_readecksum(lfs, - &LFSR_DATA_DISK(block, off_, - lfs->cfg->block_size - off_), - &ecksum); - if (err && err != LFS_ERR_CORRUPT) { + // take care of cksum + if (!lfsr_tag_isalt(tag)) { + // not an end-of-commit cksum + if (lfsr_tag_suptype(tag) != LFSR_TAG_CKSUM) { + // cksum the entry, hopefully leaving it in the cache + uint32_t cksum__ = cksum_; + err = lfsr_bd_cksum(lfs, block, off_, -1, size, + &cksum__); + if (err) { + if (err == LFS_ERR_CORRUPT) { + break; + } return err; } + parity_ ^= lfs_popc(cksum_ ^ cksum__) & 1; + cksum_ = cksum__; - // TODO ignore?? why not break? - // ignore malformed ecksums - if (err == LFS_ERR_CORRUPT) { - ecksum.cksize = -1; + // found an ecksum? save for later + if (tag == LFSR_TAG_ECKSUM) { + err = lfsr_data_readecksum(lfs, + &LFSR_DATA_DISK(block, off_, + lfs->cfg->block_size - off_), + &ecksum); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + + // TODO ignore?? why not break? + // ignore malformed ecksums + if (err == LFS_ERR_CORRUPT) { + ecksum.cksize = -1; + } } - } - // is an end-of-commit cksum - } else if (!lfsr_tag_isalt(tag)) { - uint32_t cksum_ = 0; - err = lfsr_bd_read(lfs, block, off_, -1, - &cksum_, sizeof(uint32_t)); - if (err) { - if (err == LFS_ERR_CORRUPT) { + // is an end-of-commit cksum + } else { + uint32_t cksum__ = 0; + err = lfsr_bd_read(lfs, block, off_, -1, + &cksum__, sizeof(uint32_t)); + if (err) { + if (err == LFS_ERR_CORRUPT) { + break; + } + return err; + } + cksum__ = lfs_fromle32_(&cksum__); + + if (cksum_ != cksum__) { + // uh oh, cksums don't match break; } - return err; + + // toss our cksum into the filesystem seed for + // pseudorandom numbers, note we use another cksum here + // as a collection function because it is sufficiently + // random and convenient + lfs->seed = lfs_crc32c(lfs->seed, &cksum, sizeof(uint32_t)); + + // save what we've found so far + rbyd->eoff + = ((lfs_size_t)parity_ << (8*sizeof(lfs_size_t)-1)) + | (off_ + size); + rbyd->cksum = cksum; + rbyd->trunk = (LFSR_RBYD_ISSHRUB & rbyd->trunk) | trunk_; + rbyd->weight = weight; + + // revert to data checksum + cksum_ = cksum; } - cksum_ = lfs_fromle32_(&cksum_); - - if (cksum != cksum_) { - // uh oh, cksums don't match - break; - } - - // toss our cksum into the filesystem seed for - // pseudorandom numbers, note we use another cksum here - // as a collection function because it is sufficiently - // random and convenient - lfs->seed = lfs_crc32c(lfs->seed, &cksum, sizeof(uint32_t)); - - // save what we've found so far - rbyd->eoff = off_ + size; - rbyd->cksum = cksum; - rbyd->trunk = (LFSR_RBYD_ISSHRUB & rbyd->trunk) | trunk_; - rbyd->weight = weight; } // found a trunk of a tree? if (lfsr_tag_istrunk(tag) - && (!trunk || (lfs_size_t)trunk >= off || wastrunk)) { + && (!trunk || off <= (lfs_size_t)trunk || trunk__)) { // start of trunk? - if (!wastrunk) { - wastrunk = true; + if (!trunk__) { // keep track of trunk's entry point trunk__ = off; // reset weight @@ -2346,13 +2356,14 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, // end of trunk? if (!lfsr_tag_isalt(tag)) { - wastrunk = false; - // update most recent trunk and weight, unless we are a - // shrub trunk - if (!lfsr_tag_isshrub(tag)) { + // update data checksum + cksum = cksum_; + // update trunk and weight, unless we are a shrub trunk + if (!lfsr_tag_isshrub(tag) || trunk__ == (lfs_size_t)trunk) { trunk_ = trunk__; weight = weight_; } + trunk__ = 0; } } @@ -2369,17 +2380,36 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, return LFS_ERR_CORRUPT; } - // did we end on a valid commit? we may have an erased state + // did we end on a valid commit? we may have erased-state bool erased = false; - if (rbyd->eoff < lfs->cfg->block_size - && rbyd->eoff % lfs->cfg->prog_size == 0 + if (lfsr_rbyd_eoff(rbyd) < lfs->cfg->block_size + && lfsr_rbyd_eoff(rbyd) % lfs->cfg->prog_size == 0 && ecksum.cksize != -1) { - err = lfsr_ecksum_validate(lfs, &ecksum, rbyd->blocks[0], rbyd->eoff); + // TODO is this correct for erased=corrupt? + uint8_t e = 0; + err = lfsr_bd_read(lfs, + rbyd->blocks[0], lfsr_rbyd_eoff(rbyd), ecksum.cksize, + &e, 1); if (err && err != LFS_ERR_CORRUPT) { return err; } - erased = (err != LFS_ERR_CORRUPT); + // the next valid bit must _not_ match, or a commit was attempted + if ((e >> 7) != lfsr_rbyd_parity(rbyd)) { + // check that erased-state matches our checksum, if this fails + // most likely a write was interrupted + uint32_t ecksum_ = lfs_crc32c(0, &e, 1); + int err = lfsr_bd_cksum(lfs, + rbyd->blocks[0], lfsr_rbyd_eoff(rbyd)+1, 0, + ecksum.cksize-1, + &ecksum_); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + + // found erased-state? + erased = (ecksum_ == ecksum.cksum); + } } if (!erased) { rbyd->eoff = -1; @@ -2585,46 +2615,70 @@ static int lfsr_rbyd_suplookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd, static int lfsr_rbyd_appendrev(lfs_t *lfs, lfsr_rbyd_t *rbyd, uint32_t rev) { // should only be called before any tags are written LFS_ASSERT(rbyd->eoff == 0); + LFS_ASSERT(rbyd->cksum == 0); // revision count stored as le32, we don't use a leb128 encoding as we // intentionally allow the revision count to overflow uint8_t rev_buf[sizeof(uint32_t)]; lfs_tole32_(rev, &rev_buf); - int err = lfsr_bd_prog(lfs, rbyd->blocks[0], rbyd->eoff, + + uint32_t cksum_ = rbyd->cksum; + int err = lfsr_bd_prog(lfs, rbyd->blocks[0], lfsr_rbyd_eoff(rbyd), &rev_buf, sizeof(uint32_t), - &rbyd->cksum); + &cksum_); if (err) { return err; } - rbyd->eoff += sizeof(uint32_t); + // update eoff, xor cksum parity + rbyd->eoff + += ((lfs_popc(rbyd->cksum ^ cksum_) & 1) + << (8*sizeof(lfs_size_t)-1)) + + sizeof(uint32_t); + rbyd->cksum = cksum_; return 0; } // other low-level appends static int lfsr_rbyd_appendtag(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfsr_tag_t tag, lfsr_rid_t weight, lfs_size_t size) { - lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff, + // include the previous tag parity + tag ^= (lfsr_tag_t)lfsr_rbyd_parity(rbyd) << 15; + + uint32_t cksum_ = rbyd->cksum; + lfs_ssize_t d = lfsr_bd_progtag(lfs, + rbyd->blocks[0], lfsr_rbyd_eoff(rbyd), tag, weight, size, - &rbyd->cksum); + &cksum_); if (d < 0) { return d; } - rbyd->eoff += d; + // update eoff, xor cksum parity + rbyd->eoff + += ((lfs_popc(rbyd->cksum ^ cksum_) & 1) + << (8*sizeof(lfs_size_t)-1)) + + d; + rbyd->cksum = cksum_; return 0; } static int lfsr_rbyd_appenddata(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfsr_data_t data) { - int err = lfsr_bd_progdata(lfs, rbyd->blocks[0], rbyd->eoff, + uint32_t cksum_ = rbyd->cksum; + int err = lfsr_bd_progdata(lfs, rbyd->blocks[0], lfsr_rbyd_eoff(rbyd), data, - &rbyd->cksum); + &cksum_); if (err) { return err; } - rbyd->eoff += lfsr_data_size(data); + // update eoff, xor cksum parity + rbyd->eoff + += ((lfs_popc(rbyd->cksum ^ cksum_) & 1) + << (8*sizeof(lfs_size_t)-1)) + + lfsr_data_size(data); + rbyd->cksum = cksum_; return 0; } @@ -2650,7 +2704,7 @@ static int lfsr_rbyd_prepareappend(lfs_t *lfs, lfsr_rbyd_t *rbyd) { LFS_ASSERT(lfsr_rbyd_isfetched(rbyd)); // we can't do anything if we're not erased - if (rbyd->eoff >= lfs->cfg->block_size) { + if (lfsr_rbyd_eoff(rbyd) >= lfs->cfg->block_size) { return LFS_ERR_RANGE; } @@ -2683,7 +2737,7 @@ static int lfsr_rbyd_p_flush(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfsr_tag_t alt = p[3-1-i].alt; lfsr_rid_t weight = p[3-1-i].weight; lfs_size_t jump = (p[3-1-i].jump) - ? rbyd->eoff - p[3-1-i].jump + ? lfsr_rbyd_eoff(rbyd) - p[3-1-i].jump : 0; int err = lfsr_rbyd_appendtag(lfs, rbyd, alt, weight, jump); @@ -2859,7 +2913,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, trunk:; // the new trunk starts here - lfs_size_t trunk_ = rbyd->eoff; + lfs_size_t trunk_ = lfsr_rbyd_eoff(rbyd); // keep track of bounds as we descend down the tree // @@ -3360,6 +3414,9 @@ static int lfsr_rbyd_appendcksum(lfs_t *lfs, lfsr_rbyd_t *rbyd) { return err; } + // save the data checksum + uint32_t cksum = rbyd->cksum; + // align to the next prog unit // // this gets a bit complicated as we have two types of cksums: @@ -3384,45 +3441,43 @@ static int lfsr_rbyd_appendcksum(lfs_t *lfs, lfsr_rbyd_t *rbyd) { // | cksum | cksum cksum: 1 le32 4 bytes // '---+---+---+---' total: <=11 bytes // - lfs_size_t aligned_eoff = lfs_alignup( - rbyd->eoff + 2+1+1+4+4 + 2+1+4+4, + lfs_size_t off_ = lfs_alignup( + lfsr_rbyd_eoff(rbyd) + 2+1+1+4+4 + 2+1+4+4, lfs->cfg->prog_size); // space for ecksum? - uint8_t perturb = 0; - if (aligned_eoff < lfs->cfg->block_size) { - // read the leading byte in case we need to change the expected - // value of the next tag's valid bit + uint8_t e = 0; + if (off_ < lfs->cfg->block_size) { + // read the leading byte in case we need to perturb the next tag err = lfsr_bd_read(lfs, - rbyd->blocks[0], aligned_eoff, lfs->cfg->prog_size, - &perturb, 1); + rbyd->blocks[0], off_, lfs->cfg->prog_size, + &e, 1); if (err && err != LFS_ERR_CORRUPT) { return err; } - // find the expected ecksum, don't bother avoiding a reread of the - // perturb byte, as it should still be in our cache - lfsr_ecksum_t ecksum = {.cksize=lfs->cfg->prog_size}; + // calculate the erased-state checksum + lfsr_ecksum_t ecksum; + ecksum.cksize = lfs->cfg->prog_size; + ecksum.cksum = lfs_crc32c(0, &e, 1); err = lfsr_bd_cksum(lfs, - rbyd->blocks[0], aligned_eoff, ecksum.cksize, - ecksum.cksize, + rbyd->blocks[0], off_+1, ecksum.cksize-1, + ecksum.cksize-1, &ecksum.cksum); if (err && err != LFS_ERR_CORRUPT) { return err; } - uint8_t ecksum_buf[LFSR_ECKSUM_DSIZE]; - lfsr_data_t ecksum_data = lfsr_data_fromecksum(&ecksum, ecksum_buf); err = lfsr_rbyd_appendattr_(lfs, rbyd, - LFSR_TAG_ECKSUM, 0, ecksum_data); + LFSR_TAG_ECKSUM, 0, LFSR_DATA_FROMECKSUM(&ecksum)); if (err) { return err; } // at least space for a cksum? - } else if (rbyd->eoff + 2+1+4+4 <= lfs->cfg->block_size) { + } else if (lfsr_rbyd_eoff(rbyd) + 2+1+4+4 <= lfs->cfg->block_size) { // note this implicitly marks the rbyd as unerased - aligned_eoff = lfs->cfg->block_size; + off_ = lfs->cfg->block_size; // not even space for a cksum? we can't finish the commit } else { @@ -3431,38 +3486,43 @@ static int lfsr_rbyd_appendcksum(lfs_t *lfs, lfsr_rbyd_t *rbyd) { // build end-of-commit cksum // - // note padding-size depends on leb-encoding depends on padding-size, to - // get around this catch-22 we just always write a fully-expanded leb128 - // encoding + // note padding-size depends on leb-encoding depends on padding-size + // depends leb-encoding depends on... to get around this catch-22 we + // just always write a fully-expanded leb128 encoding uint8_t cksum_buf[2+1+4+4]; - cksum_buf[0] = (LFSR_TAG_CKSUM >> 8) | ((lfs_popc(rbyd->cksum) & 1) << 7); - cksum_buf[1] = 0; + cksum_buf[0] = (uint8_t)(LFSR_TAG_CKSUM >> 8); + cksum_buf[1] = (uint8_t)(LFSR_TAG_CKSUM >> 0) + // include tag parity in the perturb bits + | ((uint8_t)lfsr_rbyd_parity(rbyd) << 1); cksum_buf[2] = 0; - lfs_size_t padding = aligned_eoff - (rbyd->eoff + 2+1+4); + lfs_size_t padding = off_ - (lfsr_rbyd_eoff(rbyd) + 2+1+4); cksum_buf[3] = 0x80 | (0x7f & (padding >> 0)); cksum_buf[4] = 0x80 | (0x7f & (padding >> 7)); cksum_buf[5] = 0x80 | (0x7f & (padding >> 14)); cksum_buf[6] = 0x00 | (0x7f & (padding >> 21)); - rbyd->cksum = lfs_crc32c(rbyd->cksum, cksum_buf, 2+1+4); - // we can't let the next tag appear as valid, so intentionally perturb the - // commit if this happens, note parity(crc(m)) == parity(m) with crc32c, - // so we can really change any bit to make this happen, we've reserved a bit - // in cksum tags just for this purpose - if ((lfs_popc(rbyd->cksum) & 1) == (perturb >> 7)) { + // calculate checksum before tag parity + uint32_t cksum_ = lfs_crc32c(rbyd->cksum, cksum_buf, 2+1+4); + // xor in the tag parity + cksum_buf[0] ^= (uint8_t)lfsr_rbyd_parity(rbyd) << 7; + // find the new parity + bool parity_ = lfsr_rbyd_parity(rbyd) + ^ (lfs_popc(rbyd->cksum ^ cksum_) & 1); + // and intentionally perturb the commit so the next tag appears invalid + if ((e >> 7) == parity_) { cksum_buf[1] ^= 0x01; - rbyd->cksum ^= 0xef306b19; // note crc(a ^ b) == crc(a) ^ crc(b) + cksum_ ^= 0xef306b19; + parity_ ^= 0x1; } - lfs_tole32_(rbyd->cksum, &cksum_buf[2+1+4]); + lfs_tole32_(cksum_, &cksum_buf[2+1+4]); - err = lfsr_bd_prog(lfs, rbyd->blocks[0], rbyd->eoff, + err = lfsr_bd_prog(lfs, rbyd->blocks[0], lfsr_rbyd_eoff(rbyd), cksum_buf, 2+1+4+4, NULL); if (err) { return err; } - rbyd->eoff += 2+1+4+4; // flush our caches, finalizing the commit on-disk err = lfsr_bd_sync(lfs); @@ -3470,7 +3530,12 @@ static int lfsr_rbyd_appendcksum(lfs_t *lfs, lfsr_rbyd_t *rbyd) { return err; } - rbyd->eoff = aligned_eoff; + // update the eoff and parity + rbyd->eoff + = ((lfs_size_t)parity_ << (8*sizeof(lfs_size_t)-1)) + | off_; + // revert to data checksum + rbyd->cksum = cksum; return 0; } @@ -3691,7 +3756,7 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs, lfsr_rbyd_t *rbyd, off = lfs_max32(off, sizeof(uint32_t)); // empty rbyd? write a null tag so our trunk can still point to something - if (rbyd->eoff == off) { + if (lfsr_rbyd_eoff(rbyd) == off) { err = lfsr_rbyd_appendtag(lfs, rbyd, // mark as shrub if we are a shrub (lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0) @@ -3712,7 +3777,7 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfs_size_t layer = off; lfsr_rid_t weight = 0; while (true) { - lfs_size_t layer_ = rbyd->eoff; + lfs_size_t layer_ = lfsr_rbyd_eoff(rbyd); off = layer; while (off < layer_) { // connect two trunks together with a new binary trunk @@ -3782,7 +3847,7 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs, lfsr_rbyd_t *rbyd, LFSR_TAG_LE, tag), weight, - rbyd->eoff - trunk); + lfsr_rbyd_eoff(rbyd) - trunk); if (err) { return err; } @@ -3872,7 +3937,7 @@ static int lfsr_rbyd_appendgdelta(lfs_t *lfs, lfsr_rbyd_t *rbyd) { static int lfsr_rbyd_appendshrub(lfs_t *lfs, lfsr_rbyd_t *rbyd, const lfsr_shrub_t *shrub) { // keep track of the start of the new tree - lfs_size_t off = rbyd->eoff; + lfs_size_t off = lfsr_rbyd_eoff(rbyd); // mark as shrub rbyd->trunk |= LFSR_RBYD_ISSHRUB; @@ -10123,7 +10188,7 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file, lfsr_bid_t bid, // does our estimate exceed our shrub_size? need to recalculate an // accurate estimate lfs_ssize_t estimate = (alloc) - ? (lfs_size_t)-1 + ? -1 : file->bshrub.u.bshrub.eoff; // this double condition avoids overflow issues if ((lfs_size_t)estimate > lfs->cfg->shrub_size diff --git a/lfs.h b/lfs.h index 900a1070..109a3ad5 100644 --- a/lfs.h +++ b/lfs.h @@ -341,13 +341,14 @@ typedef struct lfsr_rbyd { // sign(weight)=0 => rbyd lfsr_rid_t weight; lfs_block_t blocks[2]; - // sign(trunk)=0 => normal rbyd - // sign(trunk)=1 => shrub rbyd + // sign(trunk)=0 => normal rbyd + // sign(trunk)=1 => shrub rbyd + lfs_ssize_t trunk; + // sign(eoff) => commit parity // eoff=0, trunk=0 => not yet committed // eoff=0, trunk>0 => not yet fetched // eoff>=block_size => rbyd not erased/needs compaction - lfs_ssize_t trunk; - lfs_size_t eoff; + lfs_ssize_t eoff; uint32_t cksum; } lfsr_rbyd_t; diff --git a/scripts/dbgbmap.py b/scripts/dbgbmap.py index 22041ab3..05387268 100755 --- a/scripts/dbgbmap.py +++ b/scripts/dbgbmap.py @@ -41,7 +41,8 @@ TAG_UATTR = 0x0400 TAG_SATTR = 0x0600 TAG_SHRUB = 0x1000 TAG_CKSUM = 0x3000 -TAG_ECKSUM = 0x3100 +TAG_PERTURB = 0x3100 +TAG_ECKSUM = 0x3200 TAG_ALT = 0x4000 TAG_R = 0x2000 TAG_GT = 0x1000 @@ -133,6 +134,9 @@ def crc32c(data, crc=0): def popc(x): return bin(x).count('1') +def parity(x): + return popc(x) & 1 + def fromle32(data): return struct.unpack(' len(data): break @@ -665,24 +674,27 @@ class Rbyd: # take care of cksums if not tag & TAG_ALT: if (tag & 0xff00) != TAG_CKSUM: - cksum_ = crc32c(data[j_:j_+size], cksum_) + parity__ ^= parity(cksum__) + cksum__ = crc32c(data[j_:j_+size], cksum__) + parity__ ^= parity(cksum__) # found a cksum? else: - cksum__ = fromle32(data[j_:j_+4]) - if cksum_ != cksum__: + cksum___ = fromle32(data[j_:j_+4]) + if cksum__ != cksum___: break # commit what we have - eoff = trunkeoff if trunkeoff else j_ + size + eoff = eoff_ if eoff_ else j_ + size cksum = cksum_ trunk_ = trunk__ weight = weight_ + # revert to data cksum + cksum__ = cksum_ # evaluate trunks if (tag & 0xf000) != TAG_CKSUM and ( - not trunk or trunk >= j_-d or wastrunk): + not trunk or j_-d <= trunk or trunk___): # new trunk? - if not wastrunk: - wastrunk = True + if not trunk___: trunk___ = j_-d weight__ = 0 @@ -691,24 +703,26 @@ class Rbyd: # end of trunk? if not tag & TAG_ALT: - wastrunk = False + # update data checksum + cksum_ = cksum__ # update trunk/weight unless we found a shrub or an # explicit trunk (which may be a shrub) is requested - if not tag & TAG_SHRUB or trunk: + if not tag & TAG_SHRUB or trunk___ == trunk: trunk__ = trunk___ weight_ = weight__ # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: - trunkeoff = j_ + size - eoff = trunkeoff + eoff_ = j_ + size + eoff = eoff_ cksum = cksum_ trunk_ = trunk__ weight = weight_ + trunk___ = 0 if not tag & TAG_ALT: j_ += size - return cls(block, data, rev, eoff, trunk_, weight) + return cls(block, data, rev, eoff, trunk_, weight, cksum) def lookup(self, rid, tag): if not self: diff --git a/scripts/dbgbtree.py b/scripts/dbgbtree.py index 4c8b380a..f63f0fb1 100755 --- a/scripts/dbgbtree.py +++ b/scripts/dbgbtree.py @@ -39,7 +39,8 @@ TAG_UATTR = 0x0400 TAG_SATTR = 0x0600 TAG_SHRUB = 0x1000 TAG_CKSUM = 0x3000 -TAG_ECKSUM = 0x3100 +TAG_PERTURB = 0x3100 +TAG_ECKSUM = 0x3200 TAG_ALT = 0x4000 TAG_R = 0x2000 TAG_GT = 0x1000 @@ -116,6 +117,9 @@ def crc32c(data, crc=0): def popc(x): return bin(x).count('1') +def parity(x): + return popc(x) & 1 + def fromle32(data): return struct.unpack(' len(data): break @@ -331,24 +345,27 @@ class Rbyd: # take care of cksums if not tag & TAG_ALT: if (tag & 0xff00) != TAG_CKSUM: - cksum_ = crc32c(data[j_:j_+size], cksum_) + parity__ ^= parity(cksum__) + cksum__ = crc32c(data[j_:j_+size], cksum__) + parity__ ^= parity(cksum__) # found a cksum? else: - cksum__ = fromle32(data[j_:j_+4]) - if cksum_ != cksum__: + cksum___ = fromle32(data[j_:j_+4]) + if cksum__ != cksum___: break # commit what we have - eoff = trunkeoff if trunkeoff else j_ + size + eoff = eoff_ if eoff_ else j_ + size cksum = cksum_ trunk_ = trunk__ weight = weight_ + # revert to data cksum + cksum__ = cksum_ # evaluate trunks if (tag & 0xf000) != TAG_CKSUM and ( - not trunk or trunk >= j_-d or wastrunk): + not trunk or j_-d <= trunk or trunk___): # new trunk? - if not wastrunk: - wastrunk = True + if not trunk___: trunk___ = j_-d weight__ = 0 @@ -357,24 +374,26 @@ class Rbyd: # end of trunk? if not tag & TAG_ALT: - wastrunk = False + # update data checksum + cksum_ = cksum__ # update trunk/weight unless we found a shrub or an # explicit trunk (which may be a shrub) is requested - if not tag & TAG_SHRUB or trunk: + if not tag & TAG_SHRUB or trunk___ == trunk: trunk__ = trunk___ weight_ = weight__ # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: - trunkeoff = j_ + size - eoff = trunkeoff + eoff_ = j_ + size + eoff = eoff_ cksum = cksum_ trunk_ = trunk__ weight = weight_ + trunk___ = 0 if not tag & TAG_ALT: j_ += size - return cls(block, data, rev, eoff, trunk_, weight) + return cls(block, data, rev, eoff, trunk_, weight, cksum) def lookup(self, rid, tag): if not self: @@ -591,8 +610,8 @@ def main(disk, roots=None, *, # fetch the root btree = Rbyd.fetch(f, block_size, roots, trunk) - print('btree %s, rev %d, weight %d' % ( - btree.addr(), btree.rev, btree.weight)) + print('btree %s, rev %d, weight %d, cksum %08x' % ( + btree.addr(), btree.rev, btree.weight, btree.cksum)) # look up a bid, while keeping track of the search path def btree_lookup(bid, *, diff --git a/scripts/dbglfs.py b/scripts/dbglfs.py index 4781f086..c615ac34 100755 --- a/scripts/dbglfs.py +++ b/scripts/dbglfs.py @@ -40,7 +40,8 @@ TAG_UATTR = 0x0400 TAG_SATTR = 0x0600 TAG_SHRUB = 0x1000 TAG_CKSUM = 0x3000 -TAG_ECKSUM = 0x3100 +TAG_PERTURB = 0x3100 +TAG_ECKSUM = 0x3200 TAG_ALT = 0x4000 TAG_R = 0x2000 TAG_GT = 0x1000 @@ -117,6 +118,9 @@ def crc32c(data, crc=0): def popc(x): return bin(x).count('1') +def parity(x): + return popc(x) & 1 + def fromle32(data): return struct.unpack(' len(data): break @@ -362,24 +376,27 @@ class Rbyd: # take care of cksums if not tag & TAG_ALT: if (tag & 0xff00) != TAG_CKSUM: - cksum_ = crc32c(data[j_:j_+size], cksum_) + parity__ ^= parity(cksum__) + cksum__ = crc32c(data[j_:j_+size], cksum__) + parity__ ^= parity(cksum__) # found a cksum? else: - cksum__ = fromle32(data[j_:j_+4]) - if cksum_ != cksum__: + cksum___ = fromle32(data[j_:j_+4]) + if cksum__ != cksum___: break # commit what we have - eoff = trunkeoff if trunkeoff else j_ + size + eoff = eoff_ if eoff_ else j_ + size cksum = cksum_ trunk_ = trunk__ weight = weight_ + # revert to data cksum + cksum__ = cksum_ # evaluate trunks if (tag & 0xf000) != TAG_CKSUM and ( - not trunk or trunk >= j_-d or wastrunk): + not trunk or j_-d <= trunk or trunk___): # new trunk? - if not wastrunk: - wastrunk = True + if not trunk___: trunk___ = j_-d weight__ = 0 @@ -388,24 +405,26 @@ class Rbyd: # end of trunk? if not tag & TAG_ALT: - wastrunk = False + # update data checksum + cksum_ = cksum__ # update trunk/weight unless we found a shrub or an # explicit trunk (which may be a shrub) is requested - if not tag & TAG_SHRUB or trunk: + if not tag & TAG_SHRUB or trunk___ == trunk: trunk__ = trunk___ weight_ = weight__ # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: - trunkeoff = j_ + size - eoff = trunkeoff + eoff_ = j_ + size + eoff = eoff_ cksum = cksum_ trunk_ = trunk__ weight = weight_ + trunk___ = 0 if not tag & TAG_ALT: j_ += size - return cls(block, data, rev, eoff, trunk_, weight) + return cls(block, data, rev, eoff, trunk_, weight, cksum) def lookup(self, rid, tag): if not self: diff --git a/scripts/dbgmtree.py b/scripts/dbgmtree.py index dfb629e2..010b2c5a 100755 --- a/scripts/dbgmtree.py +++ b/scripts/dbgmtree.py @@ -39,7 +39,8 @@ TAG_UATTR = 0x0400 TAG_SATTR = 0x0600 TAG_SHRUB = 0x1000 TAG_CKSUM = 0x3000 -TAG_ECKSUM = 0x3100 +TAG_PERTURB = 0x3100 +TAG_ECKSUM = 0x3200 TAG_ALT = 0x4000 TAG_R = 0x2000 TAG_GT = 0x1000 @@ -116,6 +117,9 @@ def crc32c(data, crc=0): def popc(x): return bin(x).count('1') +def parity(x): + return popc(x) & 1 + def fromle32(data): return struct.unpack(' len(data): break @@ -346,24 +360,27 @@ class Rbyd: # take care of cksums if not tag & TAG_ALT: if (tag & 0xff00) != TAG_CKSUM: - cksum_ = crc32c(data[j_:j_+size], cksum_) + parity__ ^= parity(cksum__) + cksum__ = crc32c(data[j_:j_+size], cksum__) + parity__ ^= parity(cksum__) # found a cksum? else: - cksum__ = fromle32(data[j_:j_+4]) - if cksum_ != cksum__: + cksum___ = fromle32(data[j_:j_+4]) + if cksum__ != cksum___: break # commit what we have - eoff = trunkeoff if trunkeoff else j_ + size + eoff = eoff_ if eoff_ else j_ + size cksum = cksum_ trunk_ = trunk__ weight = weight_ + # revert to data cksum + cksum__ = cksum_ # evaluate trunks if (tag & 0xf000) != TAG_CKSUM and ( - not trunk or trunk >= j_-d or wastrunk): + not trunk or j_-d <= trunk or trunk___): # new trunk? - if not wastrunk: - wastrunk = True + if not trunk___: trunk___ = j_-d weight__ = 0 @@ -372,24 +389,26 @@ class Rbyd: # end of trunk? if not tag & TAG_ALT: - wastrunk = False + # update data checksum + cksum_ = cksum__ # update trunk/weight unless we found a shrub or an # explicit trunk (which may be a shrub) is requested - if not tag & TAG_SHRUB or trunk: + if not tag & TAG_SHRUB or trunk___ == trunk: trunk__ = trunk___ weight_ = weight__ # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: - trunkeoff = j_ + size - eoff = trunkeoff + eoff_ = j_ + size + eoff = eoff_ cksum = cksum_ trunk_ = trunk__ weight = weight_ + trunk___ = 0 if not tag & TAG_ALT: j_ += size - return cls(block, data, rev, eoff, trunk_, weight) + return cls(block, data, rev, eoff, trunk_, weight, cksum) def lookup(self, rid, tag): if not self: @@ -1481,8 +1500,11 @@ def main(disk, mroots=None, *, #### actual debugging begins here # print some information about the mtree - print('mtree %s, rev %d, weight %d.%d' % ( - mroot.addr(), mroot.rev, bweight//mleaf_weight, 1*mleaf_weight)) + print('mtree %s, rev %d, weight %d.%d, cksum %08x' % ( + mroot.addr(), + mroot.rev, + bweight//mleaf_weight, 1*mleaf_weight, + mroot.cksum)) # dynamically size the id field w_width = max( diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py index a0be4d73..7e7d2651 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -48,7 +48,8 @@ TAG_UATTR = 0x0400 TAG_SATTR = 0x0600 TAG_SHRUB = 0x1000 TAG_CKSUM = 0x3000 -TAG_ECKSUM = 0x3100 +TAG_PERTURB = 0x3100 +TAG_ECKSUM = 0x3200 TAG_ALT = 0x4000 TAG_R = 0x2000 TAG_GT = 0x1000 @@ -125,6 +126,12 @@ def crc32c(data, crc=0): def popc(x): return bin(x).count('1') +def parity(x): + return popc(x) & 1 + +def parity(x): + return popc(x) & 1 + def fromle32(data): return struct.unpack(' len(data): break @@ -927,24 +953,27 @@ def main(disk, blocks=None, *, # take care of cksums if not tag & TAG_ALT: if (tag & 0xff00) != TAG_CKSUM: - cksum_ = crc32c(data[j_:j_+size], cksum_) + parity__ ^= parity(cksum__) + cksum__ = crc32c(data[j_:j_+size], cksum__) + parity__ ^= parity(cksum__) # found a cksum? else: - cksum__ = fromle32(data[j_:j_+4]) - if cksum_ != cksum__: + cksum___ = fromle32(data[j_:j_+4]) + if cksum__ != cksum___: break # commit what we have - eoff = trunkeoff if trunkeoff else j_ + size + eoff = eoff_ if eoff_ else j_ + size cksum = cksum_ trunk_ = trunk__ weight = weight_ + # revert to data cksum + cksum__ = cksum_ # evaluate trunks if (tag & 0xf000) != TAG_CKSUM and ( - not trunk or trunk >= j_-d or wastrunk): + not trunk or j_-d <= trunk or trunk___): # new trunk? - if not wastrunk: - wastrunk = True + if not trunk___: trunk___ = j_-d weight__ = 0 @@ -953,33 +982,36 @@ def main(disk, blocks=None, *, # end of trunk? if not tag & TAG_ALT: - wastrunk = False + # update data checksum + cksum_ = cksum__ # update trunk/weight unless we found a shrub or an # explicit trunk (which may be a shrub) is requested - if not tag & TAG_SHRUB or trunk: + if not tag & TAG_SHRUB or trunk___ == trunk: trunk__ = trunk___ weight_ = weight__ # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: - trunkeoff = j_ + size - eoff = trunkeoff + eoff_ = j_ + size + eoff = eoff_ cksum = cksum_ trunk_ = trunk__ weight = weight_ + trunk___ = 0 if not tag & TAG_ALT: j_ += size - return rev, eoff, trunk_, weight + return rev, eoff, trunk_, weight, cksum - revs, eoffs, trunks_, weights = [], [], [], [] + revs, eoffs, trunks_, weights, cksums = [], [], [], [], [] i = 0 for i_, (data, trunk_) in enumerate(zip(datas, trunks)): - rev, eoff, trunk_, weight = fetch(data, trunk_) + rev, eoff, trunk_, weight, cksum = fetch(data, trunk_) revs.append(rev) eoffs.append(eoff) trunks_.append(trunk_) weights.append(weight) + cksums.append(cksum) # compare with sequence arithmetic if trunk_ and ( @@ -989,10 +1021,16 @@ def main(disk, blocks=None, *, i = i_ # print contents of the winning metadata block - block, data, rev, eoff, trunk_, weight = ( - blocks[i], datas[i], revs[i], eoffs[i], trunks_[i], weights[i]) + block, data, rev, eoff, trunk_, weight, cksum = ( + blocks[i], + datas[i], + revs[i], + eoffs[i], + trunks_[i], + weights[i], + cksums[i]) - print('rbyd %s, rev %d, size %d, weight %d' % ( + print('rbyd %s, rev %d, size %d, weight %d, cksum %08x' % ( '0x%x.%x' % (block, trunk_) if len(blocks) == 1 else '0x{%x,%s}.%x' % ( @@ -1000,7 +1038,7 @@ def main(disk, blocks=None, *, ','.join('%x' % blocks[(i+1+j) % len(blocks)] for j in range(len(blocks)-1)), trunk_), - rev, eoff, weight)) + rev, eoff, weight, cksum)) if args.get('log'): dbg_log(data, block_size, rev, eoff, weight, diff --git a/scripts/dbgtag.py b/scripts/dbgtag.py index a9bc28fa..82e21fb7 100755 --- a/scripts/dbgtag.py +++ b/scripts/dbgtag.py @@ -37,7 +37,8 @@ TAG_UATTR = 0x0400 TAG_SATTR = 0x0600 TAG_SHRUB = 0x1000 TAG_CKSUM = 0x3000 -TAG_ECKSUM = 0x3100 +TAG_PERTURB = 0x3100 +TAG_ECKSUM = 0x3200 TAG_ALT = 0x4000 TAG_R = 0x2000 TAG_GT = 0x1000 @@ -182,6 +183,11 @@ def tagrepr(tag, w=None, size=None, off=None): tag & 0xff, ' w%d' % w if w else '', ' %s' % size if size is not None else '') + elif (tag & 0x7f00) == TAG_PERTURB: + return 'perturb%s%s%s' % ( + ' 0x%02x' % (tag & 0xff) if tag & 0xff else '', + ' w%d' % w if w else '', + ' %s' % size if size is not None else '') elif (tag & 0x7f00) == TAG_ECKSUM: return 'ecksum%s%s%s' % ( ' 0x%02x' % (tag & 0xff) if tag & 0xff else '', diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index cf8975f4..cd308d98 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -2326,8 +2326,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -2414,8 +2414,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -2814,9 +2814,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // test all permutations of a given size size_t perm_count = TEST_FACTORIAL(N); @@ -2840,7 +2840,8 @@ code = ''' // restore backup rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -2864,8 +2865,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -3138,9 +3139,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try removing each tag for (unsigned j = 0; j < N; j++) { @@ -3149,7 +3150,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -3205,8 +3207,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -3287,9 +3289,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try removing each tag for (unsigned j = 0; j < N; j++) { @@ -3298,7 +3300,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -3901,9 +3904,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // test all permutations of a given size size_t perm_count = TEST_FACTORIAL(N); @@ -3927,7 +3930,8 @@ code = ''' // restore backup rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -3965,8 +3969,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -4506,8 +4510,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -5540,8 +5544,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -6048,9 +6052,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // test all permutations of a given size size_t perm_count = TEST_FACTORIAL(N*M); @@ -6074,7 +6078,8 @@ code = ''' // restore backup rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -6103,8 +6108,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -6214,9 +6219,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try removing each tag for (unsigned j = 0; j < N*M; j++) { @@ -6225,7 +6230,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -6310,8 +6316,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -6393,9 +6399,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // test all permutations of a given size size_t perm_count = TEST_FACTORIAL(N*M); @@ -6419,7 +6425,8 @@ code = ''' // restore backup rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -6446,8 +6453,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -6685,8 +6692,8 @@ code = ''' &rid_, &tag_, NULL, &data_) => LFS_ERR_NOENT; // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -6855,8 +6862,8 @@ code = ''' &rid_, &tag_, NULL, &data_) => LFS_ERR_NOENT; // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -10606,9 +10613,9 @@ code = ''' // copy block so we can reset after each delete lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try deleting each rid for (unsigned j = 0; j < N; j++) { @@ -10617,7 +10624,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -10663,8 +10671,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -10774,9 +10782,9 @@ code = ''' // copy block so we can reset after each delete lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try deleting each rid for (unsigned j = 0; j < N; j++) { @@ -10785,7 +10793,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -10864,8 +10873,8 @@ code = ''' } // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -10966,9 +10975,9 @@ code = ''' // copy block so we can reset after each delete lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try deleting each rid for (unsigned j = 0; j < N; j++) { @@ -10977,7 +10986,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -11102,9 +11112,9 @@ code = ''' // copy block so we can reset after each delete lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try deleting each rid for (unsigned j = 0; j < N; j++) { @@ -11113,7 +11123,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -11534,9 +11545,9 @@ code = ''' // copy block so we can reset after each delete lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // test all permutations of a given size size_t perm_count = TEST_FACTORIAL(N); @@ -11560,7 +11571,8 @@ code = ''' // restore backup rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -11606,8 +11618,8 @@ code = ''' &data) => LFS_ERR_NOENT; // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -11689,9 +11701,9 @@ code = ''' // copy block so we can reset after each delete lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // test all permutations of a given size size_t perm_count = TEST_FACTORIAL(N); @@ -11715,7 +11727,8 @@ code = ''' // restore backup rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -11776,8 +11789,8 @@ code = ''' &data) => LFS_ERR_NOENT; // keep track of the worst size - if (rbyd.eoff > worst_size) { - worst_size = rbyd.eoff; + if (lfsr_rbyd_eoff(&rbyd) > worst_size) { + worst_size = lfsr_rbyd_eoff(&rbyd); worst_perm_i = perm_i; } } @@ -13792,9 +13805,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try growing each rid for (unsigned j = 0; j < N; j++) { @@ -13803,7 +13816,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -13923,9 +13937,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try growing each rid for (unsigned j = 0; j < N; j++) { @@ -13934,7 +13948,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -14066,9 +14081,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try growing each rid for (unsigned j = 0; j < N; j++) { @@ -14077,7 +14092,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -14222,9 +14238,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try shrinking each rid for (unsigned j = 0; j < N; j++) { @@ -14233,7 +14249,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -14353,9 +14370,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try shrinking each rid for (unsigned j = 0; j < N; j++) { @@ -14364,7 +14381,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -14496,9 +14514,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try shrinking each rid for (unsigned j = 0; j < N; j++) { @@ -14507,7 +14525,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -14651,9 +14670,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try deleting each rid for (unsigned j = 0; j < N; j++) { @@ -14662,7 +14681,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -14814,9 +14834,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try appending an attr to each rid, this should not affect // weights at all! @@ -14826,7 +14846,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -15445,9 +15466,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try removing each tag for (unsigned j = 0; j < N; j++) { @@ -15456,7 +15477,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -15588,9 +15610,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try replacing each tag for (unsigned j = 0; j < N; j++) { @@ -15599,7 +15621,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -15829,9 +15852,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try removing each tag for (unsigned j = 0; j < N; j++) { @@ -15840,7 +15863,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -15982,9 +16006,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try replacing each tag for (unsigned j = 0; j < N; j++) { @@ -15993,7 +16017,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -16218,9 +16243,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try removing each tag for (unsigned j = 0; j < N; j++) { @@ -16229,7 +16254,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -16361,9 +16387,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try replacing each tag for (unsigned j = 0; j < N; j++) { @@ -16372,7 +16398,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -16590,9 +16617,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try removing each tag for (unsigned j = 0; j < N; j++) { @@ -16601,7 +16628,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0; @@ -16733,9 +16761,9 @@ code = ''' // copy block so we can reset after each remove lfsr_rbyd_t backup_rbyd = rbyd; - uint8_t *backup_block = malloc(rbyd.eoff); - lfsr_bd_read(&lfs, rbyd.blocks[0], 0, rbyd.eoff, - backup_block, rbyd.eoff) => 0; + uint8_t *backup_block = malloc(lfsr_rbyd_eoff(&rbyd)); + lfsr_bd_read(&lfs, rbyd.blocks[0], 0, lfsr_rbyd_eoff(&rbyd), + backup_block, lfsr_rbyd_eoff(&rbyd)) => 0; // try replacing each tag for (unsigned j = 0; j < N; j++) { @@ -16744,7 +16772,8 @@ code = ''' rbyd = backup_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; - lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, backup_block, rbyd.eoff, + lfsr_bd_prog(&lfs, rbyd.blocks[0], 0, + backup_block, lfsr_rbyd_eoff(&rbyd), NULL) => 0; lfsr_bd_flush(&lfs, NULL) => 0;