From 006d656da2f6693b601706e91a31c65e4945cb62 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 15 Dec 2023 00:58:24 -0600 Subject: [PATCH] Fixed unaligned data checksumming in two ways (uncrc32c, flcksum) Checksumming unaligned data during block compaction is surprisingly tricky. We don't know if our data will be aligned until after a potentially unbounded number lookups, we need to write data into our pcache as we go to avoid unnecessary lookups, but if we end up unaligned we need to revert our checksum to the checksum of the aligned data. The way I see it there are 4 options: 1. Calculate the checksum after writing data into the block. This is the most expensive option, requiring a full second read of the data to calculate the checksum. It is simple though. 2. Do a pass over the btree to figure out alignment before writing. This at least only reads metadata twice, so is more efficient than the 1st option. 3. Keep track of the aligned checksum on each flush, falling back to the last flushed checksum if we need to correct alignment. This solution is flexible though requires some extra state to track multiple checksums. 4. Leverage the math behind CRCs to run the CRC backwards when we truncate for alignment. This works, though a bit inefficiently, but is strictly tied to CRC-related checksums. By inefficient I mean that we would likely be limited to a bit-level "uncrc32c". It's possible to create nibble/byte tables for uncrc32c, but this adds significant code cost for a relatively uncritical function. I was hopeful that we could leverage the existing tables in both functions, but unfortunately it doesn't work out like that. You could scan the crc32c table to find the constant to reverse, but this requires ~16*2 or ~256 operations vs "naive" ~8 operations per byte. This commit implements both 3 and 4, defaulting to 4 unless LFS_NO_UNCRC32C is defined. The current lfs_uncrc32c implementation is a simple bit-level implementation, but does allow for crc32c truncation without any extra state. code stack before: 32044 2880 uncrc32c: 32108 (+0.2%) 2880 (+0.0%) flcksum: 32132 (+0.3%) 2880 (+0.0%) --- lfs.c | 103 ++++++++++++++++++--------- lfs_util.c | 22 ++++++ lfs_util.h | 7 ++ tests/test_rbyd.toml | 162 ++++++++++++++++++++++++++++--------------- 4 files changed, 208 insertions(+), 86 deletions(-) diff --git a/lfs.c b/lfs.c index 7ea5ca85..7fad1de5 100644 --- a/lfs.c +++ b/lfs.c @@ -241,7 +241,8 @@ static int lfs_bd_crc32c(lfs_t *lfs, #ifndef LFS_READONLY static int lfs_bd_flush(lfs_t *lfs, - lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { + lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate, + uint32_t *flcksum_) { if (pcache->block != LFS_BLOCK_NULL && pcache->block != LFS_BLOCK_INLINE) { LFS_ASSERT(pcache->block < lfs->cfg->block_count); lfs_size_t diff = lfs_alignup(pcache->size, lfs->cfg->prog_size); @@ -267,6 +268,12 @@ static int lfs_bd_flush(lfs_t *lfs, } } + // this is when we update the the flushed checksum if requested + if (flcksum_) { + *flcksum_ = lfs_crc32c(*flcksum_, + pcache->buffer, pcache->size); + } + lfs_cache_zero(lfs, pcache); } @@ -279,7 +286,7 @@ static int lfs_bd_sync(lfs_t *lfs, lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { lfs_cache_drop(lfs, rcache); - int err = lfs_bd_flush(lfs, pcache, rcache, validate); + int err = lfs_bd_flush(lfs, pcache, rcache, validate, NULL); if (err) { return err; } @@ -294,7 +301,8 @@ static int lfs_bd_sync(lfs_t *lfs, static int lfs_bd_prog(lfs_t *lfs, lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate, lfs_block_t block, lfs_size_t off, - const void *buffer, lfs_size_t size) { + const void *buffer, lfs_size_t size, + uint32_t *flcksum_) { const uint8_t *data = buffer; LFS_ASSERT(block == LFS_BLOCK_INLINE || block < lfs->cfg->block_count); LFS_ASSERT(off + size <= lfs->cfg->block_size); @@ -327,7 +335,8 @@ static int lfs_bd_prog(lfs_t *lfs, pcache->size = lfs_max(pcache->size, off - pcache->off); if (pcache->size == lfs->cfg->cache_size) { // eagerly flush out pcache if we fill up - int err = lfs_bd_flush(lfs, pcache, rcache, validate); + int err = lfs_bd_flush(lfs, pcache, rcache, validate, + flcksum_); if (err) { return err; } @@ -422,14 +431,15 @@ static lfs_scmp_t lfsr_bd_cmp(lfs_t *lfs, // program data with optional checksum static int lfsr_bd_prog(lfs_t *lfs, lfs_block_t block, lfs_size_t off, const void *buffer, lfs_size_t size, - uint32_t *cksum_) { + uint32_t *cksum_, uint32_t *flcksum_) { // check for in-bounds if (off+size > lfs->cfg->block_size) { return LFS_ERR_RANGE; } int err = lfs_bd_prog(lfs, &lfs->pcache, &lfs->rcache, false, - block, off, buffer, size); + block, off, buffer, size, + flcksum_); if (err) { return err; } @@ -442,8 +452,10 @@ static int lfsr_bd_prog(lfs_t *lfs, lfs_block_t block, lfs_size_t off, return 0; } -static int lfsr_bd_flush(lfs_t *lfs) { - return lfs_bd_flush(lfs, &lfs->pcache, &lfs->rcache, false); +static int lfsr_bd_flush(lfs_t *lfs, + uint32_t *flcksum_) { + return lfs_bd_flush(lfs, &lfs->pcache, &lfs->rcache, false, + flcksum_); } static int lfsr_bd_sync(lfs_t *lfs) { @@ -454,7 +466,7 @@ static int lfsr_bd_sync(lfs_t *lfs) { // be an optional ifdef? static int lfsr_bd_progvalidate(lfs_t *lfs, lfs_block_t block, lfs_size_t off, const void *buffer, lfs_size_t size, - uint32_t *cksum_) { + uint32_t *cksum_, uint32_t *flcksum_) { // check for in-bounds if (off+size > lfs->cfg->block_size) { lfs_cache_zero(lfs, &lfs->pcache); @@ -462,11 +474,13 @@ static int lfsr_bd_progvalidate(lfs_t *lfs, lfs_block_t block, lfs_size_t off, } int err = lfs_bd_prog(lfs, &lfs->pcache, &lfs->rcache, true, - block, off, buffer, size); + block, off, buffer, size, + flcksum_); if (err) { return err; } + // optional checksum if (cksum_) { *cksum_ = lfs_crc32c(*cksum_, buffer, size); } @@ -974,7 +988,8 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, } d += d_; - int err = lfsr_bd_prog(lfs, block, off, &tag_buf, d, cksum_); + int err = lfsr_bd_prog(lfs, block, off, &tag_buf, d, + cksum_, NULL); if (err) { return err; } @@ -1306,7 +1321,7 @@ static lfs_scmp_t lfsr_data_namecmp(lfs_t *lfs, const lfsr_data_t *data, static int lfsr_bd_progdata_(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfsr_data_t data, - uint32_t *cksum_) { + uint32_t *cksum_, uint32_t *flcksum_) { // on-disk? if (lfsr_data_ondisk(&data)) { // TODO byte-level copies have been a pain point, works for prototyping @@ -1323,7 +1338,7 @@ static int lfsr_bd_progdata_(lfs_t *lfs, } err = lfsr_bd_prog(lfs, block, off+i, &dat, 1, - cksum_); + cksum_, flcksum_); if (err) { return err; } @@ -1333,7 +1348,7 @@ static int lfsr_bd_progdata_(lfs_t *lfs, } else if (lfsr_data_isbuf(&data)) { int err = lfsr_bd_prog(lfs, block, off, data.u.buf.buffer, data.u.buf.size, - cksum_); + cksum_, flcksum_); if (err) { return err; } @@ -1342,7 +1357,7 @@ static int lfsr_bd_progdata_(lfs_t *lfs, } else if (lfsr_data_isimm(&data)) { int err = lfsr_bd_prog(lfs, block, off, data.u.imm.buf, data.u.imm.size, - cksum_); + cksum_, flcksum_); if (err) { return err; } @@ -1357,11 +1372,11 @@ static int lfsr_bd_progdata_(lfs_t *lfs, static int lfsr_bd_progdata(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfsr_data_t data, - uint32_t *cksum_) { + uint32_t *cksum_, uint32_t *flcksum_) { // simple data? if (!lfsr_data_iscat(&data)) { int err = lfsr_bd_progdata_(lfs, block, off, data, - cksum_); + cksum_, flcksum_); if (err) { return err; } @@ -1370,7 +1385,7 @@ static int lfsr_bd_progdata(lfs_t *lfs, } else { for (uint8_t i = 0; i < data.u.cat.count; i++) { int err = lfsr_bd_progdata_(lfs, block, off, data.u.cat.datas[i], - cksum_); + cksum_, flcksum_); if (err) { return err; } @@ -2363,7 +2378,8 @@ static int lfsr_rbyd_appendrev(lfs_t *lfs, lfsr_rbyd_t *rbyd, uint32_t rev) { uint8_t rev_buf[sizeof(uint32_t)]; lfs_tole32_(rev, &rev_buf); int err = lfsr_bd_prog(lfs, rbyd->blocks[0], rbyd->eoff, - &rev_buf, sizeof(uint32_t), &rbyd->cksum); + &rev_buf, sizeof(uint32_t), + &rbyd->cksum, NULL); if (err) { return err; } @@ -2966,7 +2982,7 @@ leaf:; // don't forget the data! err = lfsr_bd_progdata(lfs, rbyd->blocks[0], rbyd->eoff, data, - &rbyd->cksum); + &rbyd->cksum, NULL); if (err) { return err; } @@ -3053,7 +3069,7 @@ static int lfsr_rbyd_appendcksum(lfs_t *lfs, lfsr_rbyd_t *rbyd) { rbyd->eoff += d; err = lfsr_bd_progdata(lfs, rbyd->blocks[0], rbyd->eoff, ecksum_data, - &rbyd->cksum); + &rbyd->cksum, NULL); if (err) { return err; } @@ -3099,7 +3115,7 @@ static int lfsr_rbyd_appendcksum(lfs_t *lfs, lfsr_rbyd_t *rbyd) { int err = lfsr_bd_prog(lfs, rbyd->blocks[0], rbyd->eoff, cksum_buf, 2+1+5+4, - NULL); + NULL, NULL); if (err) { return err; } @@ -3199,7 +3215,7 @@ static int lfsr_rbyd_appendcompactattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, // and the data int err = lfsr_bd_progdata(lfs, rbyd->blocks[0], rbyd->eoff, data, - &rbyd->cksum); + &rbyd->cksum, NULL); if (err) { return err; } @@ -9934,7 +9950,12 @@ static int lfsr_ftree_flush(lfs_t *lfs, err = lfsr_bd_prog(lfs, bptr.data.u.disk.block, bptr.cksize, &buffer[pos_ - pos], d_, - &bptr.cksum); + #ifndef LFS_NO_UNCRC32C + &bptr.cksum, NULL + #else + NULL, &bptr.cksum + #endif + ); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; @@ -9990,7 +10011,12 @@ static int lfsr_ftree_flush(lfs_t *lfs, lfsr_data_slice(bptr_.data, pos_ - (bid_-(weight_-1)), d_), - &bptr.cksum); + #ifndef LFS_NO_UNCRC32C + &bptr.cksum, NULL + #else + NULL, &bptr.cksum + #endif + ); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; @@ -10011,7 +10037,12 @@ static int lfsr_ftree_flush(lfs_t *lfs, err = lfsr_bd_prog(lfs, bptr.data.u.disk.block, bptr.cksize + i, &(uint8_t){0}, 1, - &bptr.cksum); + #ifndef LFS_NO_UNCRC32C + &bptr.cksum, NULL + #else + NULL, &bptr.cksum + #endif + ); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; @@ -10026,17 +10057,25 @@ static int lfsr_ftree_flush(lfs_t *lfs, // alignment to avoid padding issues. Doing this retroactively to // the pcache greatly simplifies the above loop, though we may end // up reading more than is strictly necessary. - // - // TODO how do we handle checksum truncation??? - // TODO lfs_cache_truncate? aligndown? - lfs_ssize_t d = (lfs->pcache.off + lfs->pcache.size) - % lfs->cfg->prog_size; + lfs_ssize_t d = bptr.cksize % lfs->cfg->prog_size; + LFS_ASSERT(d <= lfs->pcache.size); lfs->pcache.size -= d; + #ifndef LFS_NO_UNCRC32C + bptr.cksum = lfs_uncrc32c(bptr.cksum, + &lfs->pcache.buffer[lfs->pcache.size], + d); + #endif bptr.cksize -= d; // TODO validate? // finalize our write - err = lfsr_bd_flush(lfs); + err = lfsr_bd_flush(lfs, + #ifndef LFS_NO_UNCRC32C + NULL + #else + &bptr.cksum + #endif + ); if (err) { return err; } diff --git a/lfs_util.c b/lfs_util.c index 03865d79..e8e75856 100644 --- a/lfs_util.c +++ b/lfs_util.c @@ -195,4 +195,26 @@ uint32_t lfs_crc32c(uint32_t crc, const void *buffer, size_t size) { return crc; } +#ifndef LFS_NO_UNCRC32C +// Undoes a crc32c +// +// like crc32c, but backwards +uint32_t lfs_uncrc32c(uint32_t crc, const void *buffer, size_t size) { + // init with 0xffffffff so prefixed zeros affect the crc + const uint8_t *data = buffer; + crc ^= 0xffffffff; + + for (size_t i = 0; i < size; i++) { + for (size_t j = 0; j < 8; j++) { + crc = (crc << 1) ^ ((crc & 0x80000000) ? 0x05ec76f1 : 0); + } + crc = crc ^ data[size-1-i]; + } + + // fini with 0xffffffff to cancel out init when called incrementally + crc ^= 0xffffffff; + return crc; +} +#endif + #endif diff --git a/lfs_util.h b/lfs_util.h index b816d305..7d677e01 100644 --- a/lfs_util.h +++ b/lfs_util.h @@ -361,6 +361,13 @@ uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size); // uint32_t lfs_crc32c(uint32_t crc, const void *buffer, size_t size); +#ifndef LFS_NO_UNCRC32C +// Undoes a crc32c +// +// like crc32c, but backwards +uint32_t lfs_uncrc32c(uint32_t crc, const void *buffer, size_t size); +#endif + // Allocate memory, only used if buffers are not provided to littlefs // Note, memory must be 64-bit aligned diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index 93dbee99..59e0786c 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -2495,8 +2495,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // update each tag in permutation order for (unsigned j = 0; j < N; j++) { @@ -2783,8 +2785,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(-1, RM(UATTR(j+1)), 0, NULL()))) @@ -2928,8 +2932,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(-1, RM(UATTR(j+1)), 0, NULL()))) => 0; @@ -3494,8 +3500,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // remove each tag in permutation order for (unsigned j = 0; j < N; j++) { @@ -5978,8 +5986,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // update each tag in permutation order for (unsigned j = 0; j < N*M; j++) { @@ -6121,8 +6131,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j/M, RM(UATTR((j%M)+1)), 0, NULL()))) => 0; @@ -6301,8 +6313,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // remove each tag in permutation order for (unsigned j = 0; j < N*M; j++) { @@ -7189,8 +7203,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j, RM, -1, NULL()))) => 0; @@ -7349,8 +7365,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j, RM, -1, NULL()))) => 0; @@ -7532,8 +7550,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j, RM, -1, NULL()))) => 0; @@ -7662,8 +7682,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j, RM, -1, NULL()))) => 0; @@ -8030,8 +8052,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // delete each rid in permutation order for (unsigned j = 0; j < N; j++) { @@ -8178,8 +8202,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // delete each rid in permutation order for (unsigned j = 0; j < N; j++) { @@ -10128,8 +10154,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, RM, +D, NULL()))) => 0; @@ -10255,8 +10283,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, GROW(REG), +D, @@ -10391,8 +10421,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, GROW(UATTR(1)), +D, @@ -10539,8 +10571,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, GROW, -D, NULL()))) => 0; @@ -10666,8 +10700,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, GROW(REG), -D, @@ -10802,8 +10838,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, GROW(UATTR(1)), -D, @@ -10949,8 +10987,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, RM, -W, NULL()))) => 0; @@ -11104,8 +11144,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( LFSR_ATTR(j*W+W-1, UATTR(1), 0, @@ -11712,8 +11754,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // remove with a wide tag lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( @@ -11849,8 +11893,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // replace with bitwise inverse lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( @@ -12079,8 +12125,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // remove with a wide tag lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( @@ -12225,8 +12273,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // replace with bitwise inverse lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( @@ -12456,8 +12506,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // remove with a wide tag lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS( @@ -12595,8 +12647,10 @@ code = ''' rbyd = backup_rbyd; lfs_bd_erase(&lfs, rbyd.blocks[0]) => 0; lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, - rbyd.blocks[0], 0, backup_block, rbyd.eoff) => 0; - lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false) => 0; + rbyd.blocks[0], 0, backup_block, rbyd.eoff, + NULL) => 0; + lfs_bd_flush(&lfs, &lfs.pcache, &lfs.rcache, false, + NULL) => 0; // replace with bitwise inverse lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTRS(