From 283b8e84c43d0fea89220df2a6d12fc0702c1a4b Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 23 Apr 2023 10:30:36 -0500 Subject: [PATCH] Some more experimental lfsr_bd_ functions These functions offer more than previous internal bd functions, the idea being that the more functionality we can move into this layer, the less functionality gets duplicated across dependent functions. - lfsr_bd_read - caching read with hint - lfsr_bd_readcsum - read with checksum - lfsr_bd_csum - calculate checksum, don't read data - lfsr_bd_cmp - compare data against a buffer - lfsr_bd_prog - caching prog - lfsr_bd_progcsum - prog with checksum - lfsr_bd_sync - complete an in-flight prog - lfsr_bd_progvalidate - prog with read-back validation - lfsr_bd_progcsumvalidate - prog with checksum and read-back validation - lfsr_bd_syncvalidate - complete an in-flight prog with read-back validation - lfsr_bd_erase - erase a block - lfsr_bd_readtag - read a tag with optional checksum - lfsr_bd_progtag - prog a tag with checksum Of course these are all susceptible to change. --- lfs.c | 547 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 365 insertions(+), 182 deletions(-) diff --git a/lfs.c b/lfs.c index ea68daa8..b6385e74 100644 --- a/lfs.c +++ b/lfs.c @@ -215,7 +215,7 @@ static int lfs_bd_crc32c(lfs_t *lfs, uint8_t dat[8]; diff = lfs_min(size-i, sizeof(dat)); int err = lfs_bd_read(lfs, - pcache, rcache, hint-i, + pcache, rcache, lfs_max32(hint, size)-i, block, off+i, &dat, diff); if (err) { return err; @@ -354,6 +354,139 @@ static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { } #endif +// TODO should these be the only bd APIs? +// simpler APIs if assume file caches are irrelevant +// +// note hint has two convenience: +// 1. 0 = minimal caching +// 2. block_size = maximal caching +// +static int lfsr_bd_read(lfs_t *lfs, + lfs_block_t block, lfs_off_t off, lfs_size_t hint, + void *buffer, lfs_size_t size) { + // check for in-bounds + if (off+size > lfs->cfg->block_size) { + return LFS_ERR_RANGE; + } + + return lfs_bd_read(lfs, &lfs->pcache, &lfs->rcache, hint, + block, off, buffer, size); +} + +// TODO merge lfsr_bd_readcsum/lfsr_bd_csum somehow? +static int lfsr_bd_readcsum(lfs_t *lfs, + lfs_block_t block, lfs_off_t off, lfs_size_t hint, + void *buffer, lfs_size_t size, + uint32_t *csum_) { + int err = lfsr_bd_read(lfs, block, off, hint, buffer, size); + if (err) { + return err; + } + + *csum_ = lfs_crc32c(*csum_, buffer, size); + return 0; +} + +static int lfsr_bd_csum(lfs_t *lfs, + lfs_block_t block, lfs_off_t off, lfs_size_t hint, lfs_size_t size, + uint32_t *crc_) { + // check for in-bounds + if (off+size > lfs->cfg->block_size) { + return LFS_ERR_RANGE; + } + + return lfs_bd_crc32c(lfs, &lfs->pcache, &lfs->rcache, hint, + block, off, size, crc_); +} + +static int lfsr_bd_cmp(lfs_t *lfs, + lfs_block_t block, lfs_off_t off, lfs_size_t hint, + const void *buffer, lfs_size_t size, + int *cmp) { + // check for in-bounds + if (off+size > lfs->cfg->block_size) { + return LFS_ERR_RANGE; + } + + int res = lfs_bd_cmp(lfs, &lfs->pcache, &lfs->rcache, hint, + block, off, buffer, size); + if (res < 0) { + return res; + } + + // TODO this should be eventually flattened away + if (res == LFS_CMP_EQ) { + *cmp = 0; + } else if (res == LFS_CMP_LT) { + *cmp = -1; + } else { + *cmp = +1; + } + + return 0; +} + +static int lfsr_bd_prog(lfs_t *lfs, lfs_block_t block, lfs_off_t off, + const void *buffer, lfs_size_t size) { + // check for in-bounds + if (off+size > lfs->cfg->block_size) { + lfs_cache_zero(lfs, &lfs->pcache); + return LFS_ERR_RANGE; + } + + return lfs_bd_prog(lfs, &lfs->pcache, &lfs->rcache, false, + block, off, buffer, size); +} + +static int lfsr_bd_progcsum(lfs_t *lfs, lfs_block_t block, lfs_off_t off, + const void *buffer, lfs_size_t size, + uint32_t *csum_) { + int err = lfsr_bd_prog(lfs, block, off, buffer, size); + if (err) { + return err; + } + + *csum_ = lfs_crc32c(*csum_, buffer, size); + return 0; +} + +static int lfsr_bd_sync(lfs_t *lfs) { + return lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false); +} + +static int lfsr_bd_progvalidate(lfs_t *lfs, lfs_block_t block, lfs_off_t off, + const void *buffer, lfs_size_t size) { + // check for in-bounds + if (off+size > lfs->cfg->block_size) { + lfs_cache_zero(lfs, &lfs->pcache); + return LFS_ERR_RANGE; + } + + return lfs_bd_prog(lfs, &lfs->pcache, &lfs->rcache, true, + block, off, buffer, size); +} + +static int lfsr_bd_progcsumvalidate(lfs_t *lfs, + lfs_block_t block, lfs_off_t off, + const void *buffer, lfs_size_t size, + uint32_t *csum_) { + int err = lfsr_bd_progvalidate(lfs, block, off, buffer, size); + if (err) { + return err; + } + + *csum_ = lfs_crc32c(*csum_, buffer, size); + return 0; +} + +static int lfsr_bd_syncvalidate(lfs_t *lfs) { + return lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, true); +} + +static int lfsr_bd_erase(lfs_t *lfs, lfs_block_t block) { + return lfs_bd_erase(lfs, block); +} + /// Small type-level utilities /// @@ -706,6 +839,129 @@ static inline void lfsr_tag_trim2( lfsr_tag_trim(alt, weight, lower_id, upper_id, lower_tag, upper_tag); } +// support for encoding/decoding tags on disk + +// each piece of metadata in an rbyd tree is prefixed with a 3-piece tag: +// +// - 16-bit type => 2 byte le16 +// - 32-bit id/weight => 5 byte leb128 (worst case) +// - 32-bit size/jump => 5 byte leb128 (worst case) +// => 12 bytes total +// +#define LFSR_TAG_DSIZE (2+5+5) + +static lfs_ssize_t lfsr_bd_readtag(lfs_t *lfs, + lfs_block_t block, lfs_off_t off, lfs_size_t hint, + lfsr_tag_t *tag_, lfs_size_t *weight_, lfs_size_t *size_, + uint32_t *csum_) { + // decode from an le16 and pair of leb128s + // note we force leb decoding to overflow when truncated + uint8_t buffer[LFSR_TAG_DSIZE] = { + 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, + }; + + int err = lfsr_bd_read(lfs, block, off, hint, + &buffer, lfs_min(LFSR_TAG_DSIZE, lfs->cfg->block_size-off)); + if (err) { + return err; + } + + if (csum_) { + // 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 ((buffer[0] & 1) != (lfs_popc(*csum_) & 1)) { + return LFS_ERR_INVAL; + } + } + + uint16_t tag = lfs_fromle16_(&buffer[0]); + + lfs_size_t weight; + ssize_t d = 2; + lfs_ssize_t d_ = lfs_fromleb128(&weight, &buffer[d], 5); + if (d_ < 0) { + return d_; + } + d += d_; + + if (weight > 0x7fffffff) { + return LFS_ERR_CORRUPT; + } + + lfs_size_t size; + d_ = lfs_fromleb128(&size, &buffer[d], 5); + if (d_ < 0) { + return d_; + } + d += d_; + + if (size > 0x7fffffff) { + return LFS_ERR_CORRUPT; + } + + // optionally crc + if (csum_) { + *csum_ = lfs_crc32c(*csum_, buffer, d); + } + + // save what we found, note we make a few tweaks on-disk => in-device + // - clear the valid bit from tag, we checked this earlier + // - adjust id so reserved id is -1, so we don't have mixed zero/one indexed + // + *tag_ = tag & ~0x1; + *weight_ = weight; + *size_ = size; + + return d; +} + +static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, + lfs_block_t block, lfs_off_t off, + lfsr_tag_t tag, lfs_size_t weight, lfs_size_t size, + uint32_t *crc) { + // check for underflow issues + LFS_ASSERT(weight < 0x80000000); + LFS_ASSERT(size < 0x80000000); + + // make sure to include the parity of the current crc + tag |= lfs_popc(*crc) & 1; + + // encode into an le16 and pair of leb128s + uint8_t buf[LFSR_TAG_DSIZE]; + lfs_tole16_(tag, &buf[0]); + + lfs_size_t d = 2; + ssize_t d_ = lfs_toleb128(weight, &buf[d], 5); + if (d_ < 0) { + return d_; + } + d += d_; + + d_ = lfs_toleb128(size, &buf[d], 5); + if (d_ < 0) { + return d_; + } + d += d_; + + int err = lfsr_bd_progcsum(lfs, block, off, &buf, d, crc); + if (err) { + return err; + } + + return d; +} + + + +/// lfsr_data_t stuff /// + // either an on-disk or in-device data pointer typedef union lfsr_data { // sign(size)=0 => in-device @@ -1159,7 +1415,7 @@ static int lfsr_rbyd_alloc(lfs_t *lfs, lfsr_rbyd_t *rbyd, uint32_t rev) { } // TODO should erase be implicit in alloc eventually? - err = lfs_bd_erase(lfs, rbyd->block); + err = lfsr_bd_erase(lfs, rbyd->block); if (err) { return err; } @@ -1178,11 +1434,11 @@ static int lfsr_rbyd_alloc(lfs_t *lfs, lfsr_rbyd_t *rbyd, uint32_t rev) { // #define LFSR_TAG_DSIZE (2+5+5) -// TODO actually should this be an lfs_bd_ operation? +// TODO actually should this be an lfsr_bd_ operation? static lfs_ssize_t lfsr_rbyd_readtag(lfs_t *lfs, - const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint, - lfs_block_t block, lfs_off_t off, - lfsr_tag_t *tag, lfs_size_t *weight, lfs_size_t *size, uint32_t *crc) { + lfs_block_t block, lfs_off_t off, lfs_size_t hint, + lfsr_tag_t *tag, lfs_size_t *weight, lfs_size_t *size, + uint32_t *crc) { // read a trio of leb128s // // note we force leb decoding to overflow when truncated @@ -1193,11 +1449,9 @@ static lfs_ssize_t lfsr_rbyd_readtag(lfs_t *lfs, }; // TODO allow different hint for lookup? bench this? does our hint work backwards? - // TODO should lfs_bd_read allow a range for reads? - int err = lfs_bd_read(lfs, - pcache, rcache, hint, - block, off, &buffer, - lfs_min(LFSR_TAG_DSIZE, lfs->cfg->block_size-off)); + // TODO should lfsr_bd_read allow a range for reads? + int err = lfsr_bd_read(lfs, block, off, hint, + &buffer, lfs_min(LFSR_TAG_DSIZE, lfs->cfg->block_size-off)); if (err) { return err; } @@ -1269,15 +1523,13 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, // read the revision count and get the crc started uint32_t rev; - int err = lfs_bd_read(lfs, - NULL, &lfs->rcache, lfs->cfg->block_size, - block, 0, &rev, sizeof(uint32_t)); + uint32_t crc = 0; + int err = lfsr_bd_readcsum(lfs, block, 0, lfs->cfg->block_size, + &rev, sizeof(uint32_t), + &crc); if (err) { return err; } - - // calculate crc before endian conversion - uint32_t crc = lfs_crc32c(0, &rev, sizeof(uint32_t)); rev = lfs_fromle32_(&rev); rbyd->block = block; @@ -1302,9 +1554,9 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfsr_tag_t tag; lfs_size_t w; lfs_size_t size; - lfs_ssize_t d = lfsr_rbyd_readtag(lfs, - NULL, &lfs->rcache, lfs->cfg->block_size-off, - block, off, &tag, &w, &size, &crc); + lfs_ssize_t d = lfsr_bd_readtag(lfs, + block, off, lfs->cfg->block_size, + &tag, &w, &size, &crc); if (d < 0) { if (d == LFS_ERR_INVAL || d == LFS_ERR_CORRUPT) { maybeerased = maybeerased && d == LFS_ERR_INVAL; @@ -1322,9 +1574,8 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, // not an end-of-commit crc if (!lfsr_tag_isalt(tag) && lfsr_tag_suptype(tag) != LFSR_TAG_CRC) { // crc the entry, hopefully leaving it in the cache - err = lfs_bd_crc32c(lfs, - NULL, &lfs->rcache, lfs->cfg->block_size-off, - block, off, size, &crc); + err = lfsr_bd_csum(lfs, block, off, lfs->cfg->block_size, size, + &crc); if (err) { if (err == LFS_ERR_CORRUPT) { break; @@ -1335,9 +1586,8 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, // found an fcrc? save for later if (tag == LFSR_TAG_FCRC) { uint8_t fbuf[LFSR_FCRC_DSIZE]; - err = lfs_bd_read(lfs, - NULL, &lfs->rcache, lfs->cfg->block_size-off, - block, off, fbuf, lfs_min(size, LFSR_FCRC_DSIZE)); + err = lfsr_bd_read(lfs, block, off, lfs->cfg->block_size, + fbuf, lfs_min(size, LFSR_FCRC_DSIZE)); if (err) { if (err == LFS_ERR_CORRUPT) { break; @@ -1355,9 +1605,8 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, // is an end-of-commit crc } else if (!lfsr_tag_isalt(tag)) { uint32_t crc_ = 0; - err = lfs_bd_read(lfs, - NULL, &lfs->rcache, lfs->cfg->block_size-off, - block, off, &crc_, sizeof(uint32_t)); + err = lfsr_bd_read(lfs, block, off, lfs->cfg->block_size, + &crc_, sizeof(uint32_t)); if (err) { if (err == LFS_ERR_CORRUPT) { break; @@ -1437,27 +1686,28 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, if (find && lfsr_tag_suptype(tag) == LFSR_TAG_NAME) { // compare with disk lfs_size_t d = lfs_min(size, find->name_size); - int cmp = lfs_bd_cmp(lfs, - NULL, &lfs->rcache, d, - block, off, find->name, d); - if (cmp < 0) { - return cmp; + int cmp; + int err = lfsr_bd_cmp(lfs, block, off, d, + find->name, d, + &cmp); + if (err) { + return err; } - if (cmp == LFS_CMP_EQ) { + if (cmp == 0) { if (size < find->name_size) { - cmp = LFS_CMP_LT; + cmp = -1; } else if (size > find->name_size) { - cmp = LFS_CMP_GT; + cmp = +1; } } // found match? - if (cmp == LFS_CMP_EQ) { + if (cmp == 0) { find->predicted_id = id; find->predicted_tag = tag; // didn't find a match, but found a better insertion point - } else if (cmp == LFS_CMP_LT && id > find->predicted_id) { + } else if (cmp < 0 && id > find->predicted_id) { find->predicted_id = id; find->predicted_tag = 0; } @@ -1485,9 +1735,8 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, // this failed most likely a previous prog was interrupted, we // need a new erase uint32_t fcrc_ = 0; - int err = lfs_bd_crc32c(lfs, - NULL, &lfs->rcache, fcrc.size, - rbyd->block, rbyd->off, fcrc.size, &fcrc_); + int err = lfsr_bd_csum(lfs, rbyd->block, rbyd->off, 0, fcrc.size, + &fcrc_); if (err && err != LFS_ERR_CORRUPT) { return err; } @@ -1526,9 +1775,9 @@ static int lfsr_rbyd_lookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd, lfsr_tag_t alt; lfs_size_t weight; lfs_off_t jump; - lfs_ssize_t d = lfsr_rbyd_readtag(lfs, - &lfs->pcache, &lfs->rcache, 0, - rbyd->block, branch, &alt, &weight, &jump, NULL); + lfs_ssize_t d = lfsr_bd_readtag(lfs, + rbyd->block, branch, 0, + &alt, &weight, &jump, NULL); if (d < 0) { return d; } @@ -1595,9 +1844,7 @@ static lfs_ssize_t lfsr_rbyd_get(lfs_t *lfs, const lfsr_rbyd_t *rbyd, // TODO should this be its own lfsr_data_ function? lfs_size_t d = lfs_min(size, lfsr_data_size(data_)); - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, d, - data_.disk.block, data_.disk.off, buffer, d); + err = lfsr_bd_read(lfs, data_.disk.block, data_.disk.off, 0, buffer, d); if (err) { return err; } @@ -1609,16 +1856,14 @@ static lfs_ssize_t lfsr_rbyd_get(lfs_t *lfs, const lfsr_rbyd_t *rbyd, static int lfsr_rbyd_prog(lfs_t *lfs, lfsr_rbyd_t *rbyd_, const void *buffer, lfs_size_t size, uint32_t *crc) { // check for out-of-bounds here - // TODO should we just move this to lfs_bd_prog? - // TODO actually should we just build crc into lfs_bd_prog as well? + // TODO should we just move this to lfsr_bd_prog? + // TODO actually should we just build crc into lfsr_bd_prog as well? if (rbyd_->off+size > lfs->cfg->block_size) { lfs_cache_zero(lfs, &lfs->pcache); return LFS_ERR_RANGE; } - int err = lfs_bd_prog(lfs, - &lfs->pcache, &lfs->rcache, false, - rbyd_->block, rbyd_->off, buffer, size); + int err = lfsr_bd_prog(lfs, rbyd_->block, rbyd_->off, buffer, size); if (err) { return err; } @@ -1637,100 +1882,54 @@ static int lfsr_rbyd_prog(lfs_t *lfs, lfsr_rbyd_t *rbyd_, } // TODO this should be a bd operation of some sort -static int lfsr_rbyd_progdata(lfs_t *lfs, lfsr_rbyd_t *rbyd_, - lfsr_data_t data, uint32_t *crc) { - // check for out-of-bounds here - // TODO should we just move this to lfs_bd_prog? - // TODO actually should we just build crc into lfs_bd_prog as well? - if (rbyd_->off+lfsr_data_size(data) > lfs->cfg->block_size) { - lfs_cache_zero(lfs, &lfs->pcache); - return LFS_ERR_RANGE; +static int lfsr_rbyd_progtag(lfs_t *lfs, lfsr_rbyd_t *rbyd, + lfsr_tag_t tag, lfs_size_t weight, lfs_size_t size, uint32_t *crc) { + lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->block, rbyd->off, + tag, weight, size, crc); + if (d < 0) { + return d; } + // update rbyd struct + rbyd->off += d; + return 0; +} + +// TODO this should be a bd operation of some sort +static int lfsr_rbyd_progdata(lfs_t *lfs, lfsr_rbyd_t *rbyd, + lfsr_data_t data, uint32_t *crc) { if (lfsr_data_ondisk(data)) { // TODO byte-level copies have been a pain point, works for prototyping // but can this be better? configurable? leverage // rcache/pcache directly? uint8_t dat; for (lfs_size_t i = 0; i < lfsr_data_size(data); i++) { - int err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, lfsr_data_size(data)-i, - data.disk.block, data.disk.off+i, &dat, 1); + int err = lfsr_bd_read(lfs, data.disk.block, data.disk.off+i, + lfsr_data_size(data)-i, + &dat, 1); if (err) { return err; } - err = lfs_bd_prog(lfs, - &lfs->pcache, &lfs->rcache, false, - rbyd_->block, rbyd_->off+i, &dat, 1); + err = lfsr_bd_progcsum(lfs, rbyd->block, rbyd->off+i, + &dat, 1, + crc); if (err) { return err; } - - // TODO should this not be optional? should we move the range check - // into bd_prog? so we can get rid of the one use of this in - // lfsr_rbyd_commit? - // optionally crc - if (crc) { - *crc = lfs_crc32c(*crc, &dat, 1); - } } } else { - int err = lfs_bd_prog(lfs, - &lfs->pcache, &lfs->rcache, false, - rbyd_->block, rbyd_->off, - data.buf.buffer, lfsr_data_size(data)); + int err = lfsr_bd_progcsum(lfs, rbyd->block, rbyd->off, + data.buf.buffer, lfsr_data_size(data), + crc); if (err) { return err; } - - // TODO should this not be optional? should we move the range check - // into bd_prog? so we can get rid of the one use of this in - // lfsr_rbyd_commit? - // optionally crc - if (crc) { - *crc = lfs_crc32c(*crc, data.buf.buffer, lfsr_data_size(data)); - } - } - - // update off - rbyd_->off += lfsr_data_size(data); - - return 0; -} - -static int lfsr_rbyd_progtag(lfs_t *lfs, lfsr_rbyd_t *rbyd_, - lfsr_tag_t tag, lfs_size_t weight, lfs_size_t size, uint32_t *crc) { - // check for underflow issues - LFS_ASSERT(weight < 0x80000000); - LFS_ASSERT(size < 0x80000000); - - // make sure to include the parity of the current crc - tag |= lfs_popc(rbyd_->crc) & 1; - - // compress into an le16 and pair of leb128s - uint8_t buf[LFSR_TAG_DSIZE]; - lfs_tole16_(tag, &buf[0]); - - lfs_size_t d = 2; - ssize_t d_ = lfs_toleb128(weight, &buf[d], 5); - if (d_ < 0) { - return d_; - } - d += d_; - - d_ = lfs_toleb128(size, &buf[d], 5); - if (d_ < 0) { - return d_; - } - d += d_; - - int err = lfsr_rbyd_prog(lfs, rbyd_, &buf, d, crc); - if (err) { - return err; } + // update rbyd struct + rbyd->off += lfsr_data_size(data); return 0; } @@ -1961,9 +2160,9 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfsr_tag_t alt; lfs_size_t weight; lfs_off_t jump; - lfs_ssize_t d = lfsr_rbyd_readtag(lfs, - &lfs->pcache, &lfs->rcache, 0, - rbyd->block, branch, &alt, &weight, &jump, NULL); + lfs_ssize_t d = lfsr_bd_readtag(lfs, + rbyd->block, branch, 0, + &alt, &weight, &jump, NULL); if (d < 0) { err = d; goto failed; @@ -2369,9 +2568,8 @@ static int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd, if (aligned < lfs->cfg->block_size) { // read the leading byte in case we need to change the expected // value of the next tag's valid bit - int err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, lfs->cfg->prog_size, - rbyd_.block, aligned, &perturb, 1); + int err = lfsr_bd_read(lfs, rbyd_.block, aligned, lfs->cfg->prog_size, + &perturb, 1); if (err && err != LFS_ERR_CORRUPT) { rbyd->off = lfs->cfg->block_size; return err; @@ -2380,9 +2578,9 @@ static int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd, // find the expected fcrc, don't bother avoiding a reread of the // perturb byte, as it should still be in our cache lfsr_fcrc_t fcrc = {.size=lfs->cfg->prog_size, .crc=0}; - err = lfs_bd_crc32c(lfs, - &lfs->pcache, &lfs->rcache, lfs->cfg->prog_size, - rbyd_.block, aligned, fcrc.size, &fcrc.crc); + err = lfsr_bd_csum(lfs, rbyd_.block, aligned, lfs->cfg->prog_size, + lfs->cfg->prog_size, + &fcrc.crc); if (err && err != LFS_ERR_CORRUPT) { goto failed; } @@ -2445,16 +2643,16 @@ static int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd, } // flush our caches, finalizing the commit on-disk - err = lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false); + err = lfsr_bd_sync(lfs); if (err) { goto failed; } // succesful commit, check checksum to make sure uint32_t crc_ = rbyd->crc; - err = lfs_bd_crc32c(lfs, - NULL, &lfs->rcache, rbyd_.off-4, - rbyd_.block, rbyd->off, rbyd_.off-4 - rbyd->off, &crc_); + err = lfsr_bd_csum(lfs, rbyd_.block, rbyd->off, 0, + rbyd_.off-4 - rbyd->off, + &crc_); if (err) { goto failed; } @@ -2702,9 +2900,8 @@ static lfs_ssize_t lfsr_btree_lookup(lfs_t *lfs, // fetch the next branch uint8_t buf[LFSR_BRANCH_DSIZE]; lfs_ssize_t d = lfs_min(LFSR_BRANCH_DSIZE, lfsr_data_size(data__)); - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, d, - data__.disk.block, data__.disk.off, buf, d); + err = lfsr_bd_read(lfs, data__.disk.block, data__.disk.off, 0, + buf, d); if (err) { return err; } @@ -2788,9 +2985,8 @@ static int lfsr_btree_parent(lfs_t *lfs, // fetch the next branch uint8_t buf[LFSR_BRANCH_DSIZE]; lfs_ssize_t d = lfs_min(LFSR_BRANCH_DSIZE, lfsr_data_size(data__)); - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, d, - data__.disk.block, data__.disk.off, buf, d); + err = lfsr_bd_read(lfs, data__.disk.block, data__.disk.off, 0, + buf, d); if (err) { return err; } @@ -2835,9 +3031,8 @@ static lfs_ssize_t lfsr_btree_get(lfs_t *lfs, if (!lfsr_data_ondisk(data_)) { memcpy(buffer, data_.buf.buffer, d); } else { - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, d, - data_.disk.block, data_.disk.off, buffer, d); + err = lfsr_bd_read(lfs, data_.disk.block, data_.disk.off, 0, + buffer, d); if (err) { return err; } @@ -2952,9 +3147,8 @@ static lfs_ssize_t lfsr_btree_namelookup(lfs_t *lfs, // fetch the next branch uint8_t buf[LFSR_BRANCH_DSIZE]; lfs_ssize_t d = lfs_min(LFSR_BRANCH_DSIZE, lfsr_data_size(data__)); - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, d, - data__.disk.block, data__.disk.off, buf, d); + err = lfsr_bd_read(lfs, data__.disk.block, data__.disk.off, 0, + buf, d); if (err) { return err; } @@ -3006,9 +3200,8 @@ static lfs_ssize_t lfsr_btree_nameget(lfs_t *lfs, if (!lfsr_data_ondisk(data_)) { memcpy(buffer, data_.buf.buffer, d); } else { - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, d, - data_.disk.block, data_.disk.off, buffer, d); + err = lfsr_bd_read(lfs, data_.disk.block, data_.disk.off, 0, + buffer, d); if (err) { return err; } @@ -3513,9 +3706,8 @@ static int lfsr_btree_commit(lfs_t *lfs, uint8_t buf[LFSR_BRANCH_DSIZE]; d = lfs_min(LFSR_BRANCH_DSIZE, lfsr_data_size(sdata)); - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, d, - sdata.disk.block, sdata.disk.off, buf, d); + err = lfsr_bd_read(lfs, sdata.disk.block, sdata.disk.off, 0, + buf, d); if (err) { return err; } @@ -3871,9 +4063,7 @@ static int lfsr_btree_pop(lfs_t *lfs, lfsr_btree_t *btree, lfs_size_t bid) { btree->inlined.tag = stag; LFS_ASSERT(lfsr_data_size(sdata) <= LFSR_BTREE_INLINESIZE); - err = lfs_bd_read(lfs, - &lfs->pcache, &lfs->rcache, lfsr_data_size(sdata), - sdata.disk.block, sdata.disk.off, + err = lfsr_bd_read(lfs, sdata.disk.block, sdata.disk.off, 0, btree->inlined.buffer, lfsr_data_size(sdata)); if (err) { return err; @@ -4022,9 +4212,8 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, lfsr_mpair_t mpair, // has the most recent revision uint32_t revs[2] = {0, 0}; for (int i = 0; i < 2; i++) { - int err = lfs_bd_read(lfs, - NULL, &lfs->rcache, sizeof(revs[0]), - mpair.blocks[0], 0, &revs[0], sizeof(revs[0])); + int err = lfsr_bd_read(lfs, mpair.blocks[0], 0, 0, + &revs[0], sizeof(revs[0])); if (err && err != LFS_ERR_CORRUPT) { return err; } @@ -4098,7 +4287,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, .trunk=0 }; - int err = lfs_bd_erase(lfs, rbyd_.block); + int err = lfsr_bd_erase(lfs, rbyd_.block); if (err) { return err; } @@ -4268,7 +4457,7 @@ int lfsr_format(lfs_t *lfs, const struct lfs_config *cfg) { // avoid mounting an older filesystem on disk lfsr_rbyd_t rbyd = {.block=i, .rev=1, .off=0, .trunk=0}; - err = lfs_bd_erase(lfs, rbyd.block); + err = lfsr_bd_erase(lfs, rbyd.block); if (err) { goto failed; } @@ -4335,15 +4524,14 @@ int lfsr_mount(lfs_t *lfs, const struct lfs_config *cfg) { // TODO we should have a function for this with lfsr_data_t LFS_ASSERT(lfsr_data_ondisk(data)); - int cmp = lfs_bd_cmp(lfs, - NULL, &lfs->rcache, 8, - data.disk.block, data.disk.off, "littlefs", 8); - if (cmp < 0) { - err = cmp; + int cmp; + err = lfsr_bd_cmp(lfs, data.disk.block, data.disk.off, 0, + "littlefs", 8, &cmp); + if (err) { goto failed; } - if (cmp != LFS_CMP_EQ) { + if (cmp != 0) { LFS_ERROR("No littlefs magic found"); err = LFS_ERR_INVAL; goto failed; @@ -4370,12 +4558,11 @@ int lfsr_mount(lfs_t *lfs, const struct lfs_config *cfg) { // TODO can we do this differently? // force truncated to overflow memset(buf, 0xff, 5); - int err = lfs_bd_read(lfs, - NULL, &lfs->rcache, 5, - data.disk.block, data.disk.off+d, buf, + int err = lfsr_bd_read(lfs, + data.disk.block, data.disk.off+d, 0, // TODO this is a bit gross, and repeated a bunch, // can we simplify this? - lfs_min32(5, lfs_max32(lfsr_data_size(data), d)-d)); + buf, lfs_min32(5, lfs_max32(lfsr_data_size(data), d)-d)); if (err) { goto failed; } @@ -4390,10 +4577,9 @@ int lfsr_mount(lfs_t *lfs, const struct lfs_config *cfg) { // force truncated lebs to overflow memset(buf, 0xff, 5); - err = lfs_bd_read(lfs, - NULL, &lfs->rcache, 5, - data.disk.block, data.disk.off+d, buf, - lfs_min32(5, lfs_max32(lfsr_data_size(data), d)-d)); + err = lfsr_bd_read(lfs, + data.disk.block, data.disk.off+d, 0, + buf, lfs_min32(5, lfs_max32(lfsr_data_size(data), d)-d)); if (err) { goto failed; } @@ -4439,11 +4625,8 @@ int lfsr_mount(lfs_t *lfs, const struct lfs_config *cfg) { LFS_ASSERT(lfsr_data_ondisk(data)); // force truncated lebs to overflow memset(buf_, 0xff, LFSR_MPAIR_DSIZE); - err = lfs_bd_read(lfs, - NULL, &lfs->rcache, - lfs_min32(LFSR_MPAIR_DSIZE, lfsr_data_size(data)), - data.disk.block, data.disk.off, buf_, - lfs_min32(LFSR_MPAIR_DSIZE, lfsr_data_size(data))); + err = lfsr_bd_read(lfs, data.disk.block, data.disk.off, 0, + buf_, lfs_min32(LFSR_MPAIR_DSIZE, lfsr_data_size(data))); if (err) { goto failed; }