From d248f70e6add8a868d068d59651eb1688fb17dfd Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 4 Feb 2025 19:57:20 -0600 Subject: [PATCH] Adopted LFSR_DATA_ISBPTR flag in lfsr_data_t/lfsr_bptr_t This takes advantage of another bit in lfsr_data_t's size field to differentiate between normal lfsr_data_ts, and lfsr_data_ts in a bptr: in-RAM buffer: on-disk data: on-disk bptr: .---+---+---+---. .. .---+---+---+---. .. .---+---+---+---. |00| size | |10| size | |11| size | +---+---+---+---+ .. +---+---+---+---+ +---+---+---+---+ | ptr -------. | block | | block | +---+---+---+---+ | +---+---+---+---+ +---+---+---+---+ | (unused) | | | off | | off | '---+---+---+---' | '---+---+---+---' .. +---+---+---+---+ .---+---+---+---. | | cksize | | data |<' +---+---+---+---+ : : : | cksum | '---+---+---+---' Note this bit is unused even in a theoretical 16/14-bit littlefs mode. This also leaves space for one more encoding (0b01), but I don't have any good use for this yet. Previous ideas around an inlined representation failed to improve anything. This accomplishes a couple things: 1. We no longer need to return the tag in lfsr_file_lookupnext, since these can only be blocks or fragments. 2. We no longer need to rely on cksize=0 to determine checksummed data from non-checksummed data when running with LFS_CKDATACKSUMS. This was supposed to be a relatively free optimization, but our lfsr_data_fromslice implementation is being a bit... funky... It seems we're right on the edge of some inline heuristic, where adding this flag prevents lfsr_data_fromslice from being inlined, missing a number of contextual optimizations and causing things to explode. This can be worked around with __attribute__((always_inline)), but we should probably revisit our data slicing macros to see if this can be solved without a compiler specific hack. Relying on such a sensitive function is not great: code stack ctx always_inline: 36320 2584 640 inline: 36424 (+0.3%) 2664 (+3.1%) 640 (+0.0%) Weird inlining noise aside, this was an overall improvement. Not needing to fetch tags in lfsr_file_lookupnext saves a bit of stack in our hot-path, which is nice: code stack ctx default before: 36460 2608 640 default after: 36320 (-0.4%) 2584 (-0.9%) 640 (+0.0%) Hmmm, though maybe not for ckdatacksums: code stack ctx ckdatacksums before: 37628 3048 640 ckdatacksums after: 38096 (+1.2%) 3072 (+0.8%) 640 (+0.0%) --- lfs.c | 215 ++++++++++++++++++++++++---------------------------------- lfs.h | 16 +++-- 2 files changed, 99 insertions(+), 132 deletions(-) diff --git a/lfs.c b/lfs.c index b24c88d0..6627becf 100644 --- a/lfs.c +++ b/lfs.c @@ -732,8 +732,6 @@ static int lfsr_bd_ckprefix(lfs_t *lfs, lfs_size_t *hint_, uint32_t *cksum__) { (void)cksum; - // checked read with no cksum? - LFS_ASSERT(cksize != 0); // must be in-bounds LFS_ASSERT(block < lfs->block_count); LFS_ASSERT(cksize <= lfs->cfg->block_size); @@ -767,8 +765,6 @@ static int lfsr_bd_cksuffix(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfs_size_t hint, lfs_size_t cksize, uint32_t cksum, uint32_t cksum__) { - // checked read with no cksum? - LFS_ASSERT(cksize != 0); // must be in-bounds LFS_ASSERT(block < lfs->block_count); LFS_ASSERT(cksize <= lfs->cfg->block_size); @@ -810,8 +806,6 @@ static int lfsr_bd_readck(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfs_size_t hint, void *buffer, lfs_size_t size, lfs_size_t cksize, uint32_t cksum) { - // checked read with no cksum? - LFS_ASSERT(cksize != 0); // must be in-bounds LFS_ASSERT(block < lfs->block_count); LFS_ASSERT(cksize <= lfs->cfg->block_size); @@ -862,8 +856,6 @@ static lfs_scmp_t lfsr_bd_cmpck(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfs_size_t hint, const void *buffer, lfs_size_t size, lfs_size_t cksize, uint32_t cksum) { - // checked read with no cksum? - LFS_ASSERT(cksize != 0); // must be in-bounds LFS_ASSERT(block < lfs->block_count); LFS_ASSERT(cksize <= lfs->cfg->block_size); @@ -930,8 +922,6 @@ static int lfsr_bd_cpyck(lfs_t *lfs, lfs_size_t size, lfs_size_t src_cksize, uint32_t src_cksum, uint32_t *cksum, bool align) { - // checked read with no cksum? - LFS_ASSERT(src_cksize != 0); // must be in-bounds LFS_ASSERT(dst_block < lfs->block_count); LFS_ASSERT(dst_off+size <= lfs->cfg->block_size); @@ -1637,6 +1627,7 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, /// lfsr_data_t stuff /// #define LFSR_DATA_ONDISK 0x80000000 +#define LFSR_DATA_ISBPTR 0x40000000 #define LFSR_DATA_NULL() \ ((lfsr_data_t){ \ @@ -1654,22 +1645,6 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs, .u.disk.block=_block, \ .u.disk.off=_off}) -#ifdef LFS_CKDATACKSUMS -#define LFSR_DATA_DISKCKSUM(_block, _off, _size, _cksize, _cksum) \ - ((lfsr_data_t){ \ - .size=LFSR_DATA_ONDISK | (_size), \ - .u.disk.block=_block, \ - .u.disk.off=_off, \ - .u.disk.cksize=_cksize, \ - .u.disk.cksum=_cksum}) -#else -#define LFSR_DATA_DISKCKSUM(_block, _off, _size, _cksize, _cksum) \ - ((lfsr_data_t){ \ - .size=LFSR_DATA_ONDISK | (_size), \ - .u.disk.block=_block, \ - .u.disk.off=_off}) -#endif - // data helpers static inline bool lfsr_data_ondisk(lfsr_data_t data) { return data.size & LFSR_DATA_ONDISK; @@ -1679,11 +1654,17 @@ static inline bool lfsr_data_isbuf(lfsr_data_t data) { return !(data.size & LFSR_DATA_ONDISK); } +static inline bool lfsr_data_isbptr(lfsr_data_t data) { + return data.size & LFSR_DATA_ISBPTR; +} + static inline lfs_size_t lfsr_data_size(lfsr_data_t data) { - return data.size & ~LFSR_DATA_ONDISK; + return data.size & ~(LFSR_DATA_ONDISK | LFSR_DATA_ISBPTR); } // data slicing +// TODO what to do about this inlining situation? +__attribute__((always_inline)) static inline lfsr_data_t lfsr_data_fromslice(lfsr_data_t data, lfs_ssize_t off, lfs_ssize_t size) { // limit our off/size to data range, note the use of unsigned casts @@ -1698,12 +1679,12 @@ static inline lfsr_data_t lfsr_data_fromslice(lfsr_data_t data, // on-disk? if (lfsr_data_ondisk(data)) { data.u.disk.off += off_; - data.size = LFSR_DATA_ONDISK | size_; + data.size -= lfsr_data_size(data) - size_; // buffer? } else { data.u.buffer += off_; - data.size = size_; + data.size -= lfsr_data_size(data) - size_; } return data; @@ -1804,7 +1785,7 @@ static lfs_ssize_t lfsr_data_read(lfs_t *lfs, lfsr_data_t *data, // validating data cksums? if (LFS_IFDEF_CKDATACKSUMS( lfsr_m_isckdatacksums(lfs->flags) - && data->u.disk.cksize != 0, + && lfsr_data_isbptr(*data), false)) { #ifdef LFS_CKDATACKSUMS int err = lfsr_bd_readck(lfs, @@ -1911,7 +1892,7 @@ static lfs_scmp_t lfsr_data_cmp(lfs_t *lfs, lfsr_data_t data, // validating data cksums? if (LFS_IFDEF_CKDATACKSUMS( lfsr_m_isckdatacksums(lfs->flags) - && data.u.disk.cksize != 0, + && lfsr_data_isbptr(data), false)) { #ifdef LFS_CKDATACKSUMS int cmp = lfsr_bd_cmpck(lfs, @@ -1983,7 +1964,7 @@ static int lfsr_bd_progdata(lfs_t *lfs, // validating data cksums? if (LFS_IFDEF_CKDATACKSUMS( lfsr_m_isckdatacksums(lfs->flags) - && data.u.disk.cksize != 0, + && lfsr_data_isbptr(data), false)) { #ifdef LFS_CKDATACKSUMS int err = lfsr_bd_cpyck(lfs, block, off, @@ -2366,23 +2347,25 @@ static int lfsr_data_readecksum(lfs_t *lfs, lfsr_data_t *data, // block pointer things -// bptr encoding: -// .---+- -+- -+- -. size: 1 leb128 <=4 bytes -// | size | block: 1 leb128 <=5 bytes -// +---+- -+- -+- -+- -. off: 1 leb128 <=4 bytes -// | block | cksize: 1 leb128 <=4 bytes -// +---+- -+- -+- -+- -' cksum: 1 le32 4 bytes -// | off | total: <=21 bytes -// +---+- -+- -+- -+ -// | cksize | -// +---+- -+- -+- -+ -// | cksum | -// '---+---+---+---' -// -#define LFSR_BPTR_DSIZE (4+5+4+4+4) +static void lfsr_bptr_init(lfsr_bptr_t *bptr, + lfsr_data_t data, lfs_size_t cksize, uint32_t cksum) { + // make sure the bptr flag is set + LFS_ASSERT(lfsr_data_ondisk(data)); + bptr->data.size = data.size | LFSR_DATA_ISBPTR; + bptr->data.u.disk.block = data.u.disk.block; + bptr->data.u.disk.off = data.u.disk.off; + #ifdef LFS_CKDATACKSUMS + bptr->data.u.disk.cksize = cksize; + bptr->data.u.disk.cksum = cksum; + #else + bptr->cksize = cksize; + bptr->cksum = cksum; + #endif +} -#define LFSR_DATA_BPTR(_bptr, _buffer) \ - ((struct {lfsr_data_t d;}){lfsr_data_frombptr(_bptr, _buffer)}.d) +static inline bool lfsr_bptr_isbptr(const lfsr_bptr_t *bptr) { + return lfsr_data_isbptr(bptr->data); +} // checked reads adds ck info to lfsr_data_t that we don't want to // unnecessarily duplicate, this makes accessing ck info annoyingly @@ -2403,6 +2386,26 @@ static inline uint32_t lfsr_bptr_cksum(const lfsr_bptr_t *bptr) { #endif } +// bptr on-disk encoding + +// bptr encoding: +// .---+- -+- -+- -. size: 1 leb128 <=4 bytes +// | size | block: 1 leb128 <=5 bytes +// +---+- -+- -+- -+- -. off: 1 leb128 <=4 bytes +// | block | cksize: 1 leb128 <=4 bytes +// +---+- -+- -+- -+- -' cksum: 1 le32 4 bytes +// | off | total: <=21 bytes +// +---+- -+- -+- -+ +// | cksize | +// +---+- -+- -+- -+ +// | cksum | +// '---+---+---+---' +// +#define LFSR_BPTR_DSIZE (4+5+4+4+4) + +#define LFSR_DATA_BPTR(_bptr, _buffer) \ + ((struct {lfsr_data_t d;}){lfsr_data_frombptr(_bptr, _buffer)}.d) + static lfsr_data_t lfsr_data_frombptr(const lfsr_bptr_t *bptr, uint8_t buffer[static LFSR_BPTR_DSIZE]) { // size should not exceed 28-bits @@ -2482,9 +2485,8 @@ static int lfsr_data_readbptr(lfs_t *lfs, lfsr_data_t *data, return err; } - // all bptrs have this flag set, this is used to differentiate - // bptrs from btrees in files - bptr->data.size |= LFSR_DATA_ONDISK; + // mark as on-disk + cksum + bptr->data.size |= LFSR_DATA_ONDISK | LFSR_DATA_ISBPTR; return 0; } @@ -11070,8 +11072,7 @@ int lfsr_file_close(lfs_t *lfs, lfsr_file_t *file) { static int lfsr_file_lookupnext(lfs_t *lfs, const lfsr_file_t *file, lfsr_bid_t bid, - lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_, - lfsr_bptr_t *bptr_) { + lfsr_bid_t *bid_, lfsr_bid_t *weight_, lfsr_bptr_t *bptr_) { lfsr_tag_t tag; lfsr_data_t data; int err = lfsr_bshrub_lookupnext(lfs, &file->b, bid, @@ -11083,9 +11084,6 @@ static int lfsr_file_lookupnext(lfs_t *lfs, const lfsr_file_t *file, || tag == LFSR_TAG_BLOCK); // decode bptrs - if (tag_) { - *tag_ = tag; - } if (bptr_) { if (tag == LFSR_TAG_DATA) { bptr_->data = data; @@ -11104,11 +11102,10 @@ static lfs_ssize_t lfsr_file_readnext(lfs_t *lfs, const lfsr_file_t *file, lfs_off_t pos_ = pos; // read one btree entry lfsr_bid_t bid; - lfsr_tag_t tag; lfsr_bid_t weight; lfsr_bptr_t bptr; int err = lfsr_file_lookupnext(lfs, file, pos_, - &bid, &tag, &weight, &bptr); + &bid, &weight, &bptr); if (err) { return err; } @@ -11116,7 +11113,7 @@ static lfs_ssize_t lfsr_file_readnext(lfs_t *lfs, const lfsr_file_t *file, #ifdef LFS_CKFETCHES // checking fetches? if (lfsr_m_isckfetches(lfs->flags) - && tag == LFSR_TAG_BLOCK) { + && lfsr_bptr_isbptr(&bptr)) { err = lfsr_bptr_ck(lfs, &bptr); if (err) { return err; @@ -11321,11 +11318,10 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file, // try to carve any existing data lfsr_rat_t right_rat_ = {.tag=0}; while (pos < file->b.shrub.weight) { - lfsr_tag_t tag_; lfsr_bid_t weight_; lfsr_bptr_t bptr_; int err = lfsr_file_lookupnext(lfs, file, pos, - &bid, &tag_, &weight_, &bptr_); + &bid, &weight_, &bptr_); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -11334,7 +11330,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file, #ifdef LFS_CKFETCHES // checking fetches? if (lfsr_m_isckfetches(lfs->flags) - && tag_ == LFSR_TAG_BLOCK) { + && lfsr_bptr_isbptr(&bptr_)) { err = lfsr_bptr_ck(lfs, &bptr_); if (err) { return err; @@ -11352,7 +11348,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file, // left sibling needs carving but falls underneath our // crystallization threshold? break into fragments - while (tag_ == LFSR_TAG_BLOCK + while (lfsr_bptr_isbptr(&bptr_) && lfsr_data_size(left_slice_) > lfs->cfg->fragment_size && lfsr_data_size(left_slice_) < lfs->cfg->crystal_thresh) { bptr_.data = LFSR_DATA_SLICE(bptr_.data, @@ -11381,7 +11377,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file, // right sibling needs carving but falls underneath our // crystallization threshold? break into fragments - while (tag_ == LFSR_TAG_BLOCK + while (lfsr_bptr_isbptr(&bptr_) && lfsr_data_size(right_slice_) > lfs->cfg->fragment_size && lfsr_data_size(right_slice_) < lfs->cfg->crystal_thresh) { bptr_.data = LFSR_DATA_SLICE(bptr_.data, @@ -11417,7 +11413,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file, LFSR_TAG_GROW, -(bid+1 - pos), LFSR_DATA_NULL()); // carve fragment? - } else if (tag_ == LFSR_TAG_DATA) { + } else if (!lfsr_bptr_isbptr(&bptr_)) { left.data = left_slice_; rats[rat_count++] = LFSR_RAT_CAT_( LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA, @@ -11425,22 +11421,12 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file, &left.data, 1); // carve bptr? - } else if (tag_ == LFSR_TAG_BLOCK) { + } else { + bptr_.data = left_slice_; rats[rat_count++] = LFSR_RAT( LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK, -(bid+1 - pos), - LFSR_DATA_BPTR( - LFS_IFDEF_CKDATACKSUMS( - (&(lfsr_bptr_t){ - .data=left_slice_}), - (&(lfsr_bptr_t){ - .data=left_slice_, - .cksize=bptr_.cksize, - .cksum=bptr_.cksum})), - left.buf)); - - } else { - LFS_UNREACHABLE(); + LFSR_DATA_BPTR(&bptr_, left.buf)); } // completely overwriting this entry? @@ -11474,30 +11460,20 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file, rat.weight += bid+1 - (pos+weight); // carve fragment? - } else if (tag_ == LFSR_TAG_DATA) { + } else if (!lfsr_bptr_isbptr(&bptr_)) { right.data = right_slice_; right_rat_ = LFSR_RAT_CAT_( - tag_, + LFSR_TAG_DATA, bid+1 - (pos+weight), &right.data, 1); // carve bptr? - } else if (tag_ == LFSR_TAG_BLOCK) { - right_rat_ = LFSR_RAT( - tag_, - bid+1 - (pos+weight), - LFSR_DATA_BPTR( - LFS_IFDEF_CKDATACKSUMS( - (&(lfsr_bptr_t){ - .data=right_slice_}), - (&(lfsr_bptr_t){ - .data=right_slice_, - .cksize=bptr_.cksize, - .cksum=bptr_.cksum})), - right.buf)); - } else { - LFS_UNREACHABLE(); + bptr_.data = right_slice_; + right_rat_ = LFSR_RAT( + LFSR_TAG_BLOCK, + bid+1 - (pos+weight), + LFSR_DATA_BPTR(&bptr_, right.buf)); } } @@ -11579,11 +11555,10 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, // don't bother to lookup left after the first block && !aligned) { lfsr_bid_t bid; - lfsr_tag_t tag; lfsr_bid_t weight; int err = lfsr_file_lookupnext(lfs, file, lfs_smax(pos - (lfs->cfg->crystal_thresh-1), 0), - &bid, &tag, &weight, &bptr); + &bid, &weight, &bptr); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -11592,7 +11567,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, // if left crystal neighbor is a fragment and there is no // obvious hole between our own crystal and our neighbor, // include as a part of our crystal - if (tag == LFSR_TAG_DATA + if (!lfsr_bptr_isbptr(&bptr) // hole? holes can be quite large and shouldn't trigger // crystallization && (lfs_soff_t)(bid-(weight-1)+lfsr_data_size(bptr.data)) @@ -11604,7 +11579,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, crystal_start = lfs_min(bid+1, pos); // wait, found erased-state? - if (tag == LFSR_TAG_BLOCK + if (lfsr_bptr_isbptr(&bptr) && bptr.data.u.disk.block == file->eblock && bptr.data.u.disk.off + lfsr_data_size(bptr.data) == file->eoff @@ -11630,13 +11605,12 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, if (crystal_end - crystal_start < lfs->cfg->crystal_thresh && file->b.shrub.weight > 0) { lfsr_bid_t bid; - lfsr_tag_t tag; lfsr_bid_t weight; int err = lfsr_file_lookupnext(lfs, file, lfs_min( crystal_start + (lfs->cfg->crystal_thresh-1), file->b.shrub.weight-1), - &bid, &tag, &weight, &bptr); + &bid, &weight, &bptr); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -11644,7 +11618,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, // if right crystal neighbor is a fragment, include as a part // of our crystal - if (tag == LFSR_TAG_DATA) { + if (!lfsr_bptr_isbptr(&bptr)) { crystal_end = lfs_max( bid-(weight-1)+lfsr_data_size(bptr.data), pos + size); @@ -11675,13 +11649,12 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, // don't bother to lookup left after the first block && !aligned) { lfsr_bid_t bid; - lfsr_tag_t tag; lfsr_bid_t weight; int err = lfsr_file_lookupnext(lfs, file, lfs_min( crystal_start-1, file->b.shrub.weight-1), - &bid, &tag, &weight, &bptr); + &bid, &weight, &bptr); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -11694,7 +11667,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, block_start = bid-(weight-1); // wait, found erased-state? - if (tag == LFSR_TAG_BLOCK + if (lfsr_bptr_isbptr(&bptr) && bptr.data.u.disk.block == file->eblock && bptr.data.u.disk.off + lfsr_data_size(bptr.data) == file->eoff @@ -11728,13 +11701,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, return block; } - bptr.data = LFSR_DATA_DISKCKSUM(block, 0, 0, 0, 0); - LFS_IFDEF_CKDATACKSUMS( - bptr.data.u.disk.cksize, - bptr.cksize) = 0; - LFS_IFDEF_CKDATACKSUMS( - bptr.data.u.disk.cksum, - bptr.cksum) = 0; + lfsr_bptr_init(&bptr, LFSR_DATA_DISK(block, 0, 0), 0, 0); compact:; // compact data into our block @@ -11791,11 +11758,10 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, // any data on disk? if (pos_ < file->b.shrub.weight) { lfsr_bid_t bid_; - lfsr_tag_t tag_; lfsr_bid_t weight_; lfsr_bptr_t bptr_; int err = lfsr_file_lookupnext(lfs, file, pos_, - &bid_, &tag_, &weight_, &bptr_); + &bid_, &weight_, &bptr_); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -11804,7 +11770,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, #ifdef LFS_CKFETCHES // checking fetches? if (lfsr_m_isckfetches(lfs->flags) - && tag_ == LFSR_TAG_BLOCK) { + && lfsr_bptr_isbptr(&bptr_)) { err = lfsr_bptr_ck(lfs, &bptr_); if (err) { return err; @@ -11911,10 +11877,11 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file, // prepare our block pointer LFS_ASSERT(lfsr_bptr_cksize(&bptr) > 0); LFS_ASSERT(lfsr_bptr_cksize(&bptr) <= lfs->cfg->block_size); - bptr.data = LFSR_DATA_DISKCKSUM( - bptr.data.u.disk.block, - bptr.data.u.disk.off, - lfsr_bptr_cksize(&bptr) - bptr.data.u.disk.off, + lfsr_bptr_init(&bptr, + LFSR_DATA_DISK( + bptr.data.u.disk.block, + bptr.data.u.disk.off, + lfsr_bptr_cksize(&bptr) - bptr.data.u.disk.off), lfsr_bptr_cksize(&bptr), lfsr_bptr_cksum(&bptr)); lfs_off_t block_end = block_start + lfsr_data_size(bptr.data); @@ -11963,12 +11930,11 @@ fragment:; // don't bother to lookup left after first fragment && !aligned) { lfsr_bid_t bid; - lfsr_tag_t tag; lfsr_bid_t weight; lfsr_bptr_t bptr; int err = lfsr_file_lookupnext(lfs, file, fragment_start-1, - &bid, &tag, &weight, &bptr); + &bid, &weight, &bptr); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -11977,7 +11943,7 @@ fragment:; #ifdef LFS_CKFETCHES // checking fetches? if (lfsr_m_isckfetches(lfs->flags) - && tag == LFSR_TAG_BLOCK) { + && lfsr_bptr_isbptr(&bptr)) { err = lfsr_bptr_ck(lfs, &bptr); if (err) { return err; @@ -12011,12 +11977,11 @@ fragment:; // don't bother to lookup right if fragment is already full && fragment_end - fragment_start < lfs->cfg->fragment_size) { lfsr_bid_t bid; - lfsr_tag_t tag; lfsr_bid_t weight; lfsr_bptr_t bptr; int err = lfsr_file_lookupnext(lfs, file, fragment_end, - &bid, &tag, &weight, &bptr); + &bid, &weight, &bptr); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); return err; @@ -12025,7 +11990,7 @@ fragment:; #ifdef LFS_CKFETCHES // checking fetches? if (lfsr_m_isckfetches(lfs->flags) - && tag == LFSR_TAG_BLOCK) { + && lfsr_bptr_isbptr(&bptr)) { err = lfsr_bptr_ck(lfs, &bptr); if (err) { return err; diff --git a/lfs.h b/lfs.h index f5b19426..02ef4580 100644 --- a/lfs.h +++ b/lfs.h @@ -595,14 +595,15 @@ struct lfs_file_config { // lfs_block_t tail[2]; //} lfs_mdir_t; -// either an on-disk or in-device data pointer +// either an on-disk or in-RAM data pointer // -// note, it's enticing to make this fancier, but we benefit quite a lot +// note, it's tempting to make this fancier, but we benefit quite a lot // from the compiler being able to aggresively optimize this struct // typedef struct lfsr_data { - // sign(size)=0 => in-RAM buffer - // sign(size)=1 => on-disk reference + // sign2(size)=0b00 => in-RAM buffer + // sign2(size)=0b10 => on-disk data + // sign2(size)=0b11 => on-disk data + cksum lfs_size_t size; union { const uint8_t *buffer; @@ -611,8 +612,6 @@ typedef struct lfsr_data { lfs_size_t off; // optional context for validating data #ifdef LFS_CKDATACKSUMS - // cksize==0 => no checksum - // cksize!=0 => yes checksum lfs_size_t cksize; uint32_t cksum; #endif @@ -620,8 +619,11 @@ typedef struct lfsr_data { } u; } lfsr_data_t; -// a block pointer +// a possible block pointer typedef struct lfsr_bptr { + // sign2(size)=0b00 => in-RAM buffer + // sign2(size)=0b10 => on-disk data + // sign2(size)=0b11 => block pointer lfsr_data_t data; #ifndef LFS_CKDATACKSUMS lfs_size_t cksize;