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%)
This commit is contained in:
@@ -732,8 +732,6 @@ static int lfsr_bd_ckprefix(lfs_t *lfs,
|
|||||||
lfs_size_t *hint_,
|
lfs_size_t *hint_,
|
||||||
uint32_t *cksum__) {
|
uint32_t *cksum__) {
|
||||||
(void)cksum;
|
(void)cksum;
|
||||||
// checked read with no cksum?
|
|
||||||
LFS_ASSERT(cksize != 0);
|
|
||||||
// must be in-bounds
|
// must be in-bounds
|
||||||
LFS_ASSERT(block < lfs->block_count);
|
LFS_ASSERT(block < lfs->block_count);
|
||||||
LFS_ASSERT(cksize <= lfs->cfg->block_size);
|
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_block_t block, lfs_size_t off, lfs_size_t hint,
|
||||||
lfs_size_t cksize, uint32_t cksum,
|
lfs_size_t cksize, uint32_t cksum,
|
||||||
uint32_t cksum__) {
|
uint32_t cksum__) {
|
||||||
// checked read with no cksum?
|
|
||||||
LFS_ASSERT(cksize != 0);
|
|
||||||
// must be in-bounds
|
// must be in-bounds
|
||||||
LFS_ASSERT(block < lfs->block_count);
|
LFS_ASSERT(block < lfs->block_count);
|
||||||
LFS_ASSERT(cksize <= lfs->cfg->block_size);
|
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,
|
lfs_block_t block, lfs_size_t off, lfs_size_t hint,
|
||||||
void *buffer, lfs_size_t size,
|
void *buffer, lfs_size_t size,
|
||||||
lfs_size_t cksize, uint32_t cksum) {
|
lfs_size_t cksize, uint32_t cksum) {
|
||||||
// checked read with no cksum?
|
|
||||||
LFS_ASSERT(cksize != 0);
|
|
||||||
// must be in-bounds
|
// must be in-bounds
|
||||||
LFS_ASSERT(block < lfs->block_count);
|
LFS_ASSERT(block < lfs->block_count);
|
||||||
LFS_ASSERT(cksize <= lfs->cfg->block_size);
|
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,
|
lfs_block_t block, lfs_size_t off, lfs_size_t hint,
|
||||||
const void *buffer, lfs_size_t size,
|
const void *buffer, lfs_size_t size,
|
||||||
lfs_size_t cksize, uint32_t cksum) {
|
lfs_size_t cksize, uint32_t cksum) {
|
||||||
// checked read with no cksum?
|
|
||||||
LFS_ASSERT(cksize != 0);
|
|
||||||
// must be in-bounds
|
// must be in-bounds
|
||||||
LFS_ASSERT(block < lfs->block_count);
|
LFS_ASSERT(block < lfs->block_count);
|
||||||
LFS_ASSERT(cksize <= lfs->cfg->block_size);
|
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 size,
|
||||||
lfs_size_t src_cksize, uint32_t src_cksum,
|
lfs_size_t src_cksize, uint32_t src_cksum,
|
||||||
uint32_t *cksum, bool align) {
|
uint32_t *cksum, bool align) {
|
||||||
// checked read with no cksum?
|
|
||||||
LFS_ASSERT(src_cksize != 0);
|
|
||||||
// must be in-bounds
|
// must be in-bounds
|
||||||
LFS_ASSERT(dst_block < lfs->block_count);
|
LFS_ASSERT(dst_block < lfs->block_count);
|
||||||
LFS_ASSERT(dst_off+size <= lfs->cfg->block_size);
|
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 ///
|
/// lfsr_data_t stuff ///
|
||||||
|
|
||||||
#define LFSR_DATA_ONDISK 0x80000000
|
#define LFSR_DATA_ONDISK 0x80000000
|
||||||
|
#define LFSR_DATA_ISBPTR 0x40000000
|
||||||
|
|
||||||
#define LFSR_DATA_NULL() \
|
#define LFSR_DATA_NULL() \
|
||||||
((lfsr_data_t){ \
|
((lfsr_data_t){ \
|
||||||
@@ -1654,22 +1645,6 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs,
|
|||||||
.u.disk.block=_block, \
|
.u.disk.block=_block, \
|
||||||
.u.disk.off=_off})
|
.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
|
// data helpers
|
||||||
static inline bool lfsr_data_ondisk(lfsr_data_t data) {
|
static inline bool lfsr_data_ondisk(lfsr_data_t data) {
|
||||||
return data.size & LFSR_DATA_ONDISK;
|
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);
|
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) {
|
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
|
// 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,
|
static inline lfsr_data_t lfsr_data_fromslice(lfsr_data_t data,
|
||||||
lfs_ssize_t off, lfs_ssize_t size) {
|
lfs_ssize_t off, lfs_ssize_t size) {
|
||||||
// limit our off/size to data range, note the use of unsigned casts
|
// 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?
|
// on-disk?
|
||||||
if (lfsr_data_ondisk(data)) {
|
if (lfsr_data_ondisk(data)) {
|
||||||
data.u.disk.off += off_;
|
data.u.disk.off += off_;
|
||||||
data.size = LFSR_DATA_ONDISK | size_;
|
data.size -= lfsr_data_size(data) - size_;
|
||||||
|
|
||||||
// buffer?
|
// buffer?
|
||||||
} else {
|
} else {
|
||||||
data.u.buffer += off_;
|
data.u.buffer += off_;
|
||||||
data.size = size_;
|
data.size -= lfsr_data_size(data) - size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -1804,7 +1785,7 @@ static lfs_ssize_t lfsr_data_read(lfs_t *lfs, lfsr_data_t *data,
|
|||||||
// validating data cksums?
|
// validating data cksums?
|
||||||
if (LFS_IFDEF_CKDATACKSUMS(
|
if (LFS_IFDEF_CKDATACKSUMS(
|
||||||
lfsr_m_isckdatacksums(lfs->flags)
|
lfsr_m_isckdatacksums(lfs->flags)
|
||||||
&& data->u.disk.cksize != 0,
|
&& lfsr_data_isbptr(*data),
|
||||||
false)) {
|
false)) {
|
||||||
#ifdef LFS_CKDATACKSUMS
|
#ifdef LFS_CKDATACKSUMS
|
||||||
int err = lfsr_bd_readck(lfs,
|
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?
|
// validating data cksums?
|
||||||
if (LFS_IFDEF_CKDATACKSUMS(
|
if (LFS_IFDEF_CKDATACKSUMS(
|
||||||
lfsr_m_isckdatacksums(lfs->flags)
|
lfsr_m_isckdatacksums(lfs->flags)
|
||||||
&& data.u.disk.cksize != 0,
|
&& lfsr_data_isbptr(data),
|
||||||
false)) {
|
false)) {
|
||||||
#ifdef LFS_CKDATACKSUMS
|
#ifdef LFS_CKDATACKSUMS
|
||||||
int cmp = lfsr_bd_cmpck(lfs,
|
int cmp = lfsr_bd_cmpck(lfs,
|
||||||
@@ -1983,7 +1964,7 @@ static int lfsr_bd_progdata(lfs_t *lfs,
|
|||||||
// validating data cksums?
|
// validating data cksums?
|
||||||
if (LFS_IFDEF_CKDATACKSUMS(
|
if (LFS_IFDEF_CKDATACKSUMS(
|
||||||
lfsr_m_isckdatacksums(lfs->flags)
|
lfsr_m_isckdatacksums(lfs->flags)
|
||||||
&& data.u.disk.cksize != 0,
|
&& lfsr_data_isbptr(data),
|
||||||
false)) {
|
false)) {
|
||||||
#ifdef LFS_CKDATACKSUMS
|
#ifdef LFS_CKDATACKSUMS
|
||||||
int err = lfsr_bd_cpyck(lfs, block, off,
|
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
|
// block pointer things
|
||||||
|
|
||||||
// bptr encoding:
|
static void lfsr_bptr_init(lfsr_bptr_t *bptr,
|
||||||
// .---+- -+- -+- -. size: 1 leb128 <=4 bytes
|
lfsr_data_t data, lfs_size_t cksize, uint32_t cksum) {
|
||||||
// | size | block: 1 leb128 <=5 bytes
|
// make sure the bptr flag is set
|
||||||
// +---+- -+- -+- -+- -. off: 1 leb128 <=4 bytes
|
LFS_ASSERT(lfsr_data_ondisk(data));
|
||||||
// | block | cksize: 1 leb128 <=4 bytes
|
bptr->data.size = data.size | LFSR_DATA_ISBPTR;
|
||||||
// +---+- -+- -+- -+- -' cksum: 1 le32 4 bytes
|
bptr->data.u.disk.block = data.u.disk.block;
|
||||||
// | off | total: <=21 bytes
|
bptr->data.u.disk.off = data.u.disk.off;
|
||||||
// +---+- -+- -+- -+
|
#ifdef LFS_CKDATACKSUMS
|
||||||
// | cksize |
|
bptr->data.u.disk.cksize = cksize;
|
||||||
// +---+- -+- -+- -+
|
bptr->data.u.disk.cksum = cksum;
|
||||||
// | cksum |
|
#else
|
||||||
// '---+---+---+---'
|
bptr->cksize = cksize;
|
||||||
//
|
bptr->cksum = cksum;
|
||||||
#define LFSR_BPTR_DSIZE (4+5+4+4+4)
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define LFSR_DATA_BPTR(_bptr, _buffer) \
|
static inline bool lfsr_bptr_isbptr(const lfsr_bptr_t *bptr) {
|
||||||
((struct {lfsr_data_t d;}){lfsr_data_frombptr(_bptr, _buffer)}.d)
|
return lfsr_data_isbptr(bptr->data);
|
||||||
|
}
|
||||||
|
|
||||||
// checked reads adds ck info to lfsr_data_t that we don't want to
|
// checked reads adds ck info to lfsr_data_t that we don't want to
|
||||||
// unnecessarily duplicate, this makes accessing ck info annoyingly
|
// 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
|
#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,
|
static lfsr_data_t lfsr_data_frombptr(const lfsr_bptr_t *bptr,
|
||||||
uint8_t buffer[static LFSR_BPTR_DSIZE]) {
|
uint8_t buffer[static LFSR_BPTR_DSIZE]) {
|
||||||
// size should not exceed 28-bits
|
// size should not exceed 28-bits
|
||||||
@@ -2482,9 +2485,8 @@ static int lfsr_data_readbptr(lfs_t *lfs, lfsr_data_t *data,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all bptrs have this flag set, this is used to differentiate
|
// mark as on-disk + cksum
|
||||||
// bptrs from btrees in files
|
bptr->data.size |= LFSR_DATA_ONDISK | LFSR_DATA_ISBPTR;
|
||||||
bptr->data.size |= LFSR_DATA_ONDISK;
|
|
||||||
return 0;
|
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,
|
static int lfsr_file_lookupnext(lfs_t *lfs, const lfsr_file_t *file,
|
||||||
lfsr_bid_t bid,
|
lfsr_bid_t bid,
|
||||||
lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_,
|
lfsr_bid_t *bid_, lfsr_bid_t *weight_, lfsr_bptr_t *bptr_) {
|
||||||
lfsr_bptr_t *bptr_) {
|
|
||||||
lfsr_tag_t tag;
|
lfsr_tag_t tag;
|
||||||
lfsr_data_t data;
|
lfsr_data_t data;
|
||||||
int err = lfsr_bshrub_lookupnext(lfs, &file->b, bid,
|
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);
|
|| tag == LFSR_TAG_BLOCK);
|
||||||
|
|
||||||
// decode bptrs
|
// decode bptrs
|
||||||
if (tag_) {
|
|
||||||
*tag_ = tag;
|
|
||||||
}
|
|
||||||
if (bptr_) {
|
if (bptr_) {
|
||||||
if (tag == LFSR_TAG_DATA) {
|
if (tag == LFSR_TAG_DATA) {
|
||||||
bptr_->data = 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;
|
lfs_off_t pos_ = pos;
|
||||||
// read one btree entry
|
// read one btree entry
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
lfsr_bptr_t bptr;
|
lfsr_bptr_t bptr;
|
||||||
int err = lfsr_file_lookupnext(lfs, file, pos_,
|
int err = lfsr_file_lookupnext(lfs, file, pos_,
|
||||||
&bid, &tag, &weight, &bptr);
|
&bid, &weight, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return 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
|
#ifdef LFS_CKFETCHES
|
||||||
// checking fetches?
|
// checking fetches?
|
||||||
if (lfsr_m_isckfetches(lfs->flags)
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
&& tag == LFSR_TAG_BLOCK) {
|
&& lfsr_bptr_isbptr(&bptr)) {
|
||||||
err = lfsr_bptr_ck(lfs, &bptr);
|
err = lfsr_bptr_ck(lfs, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return 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
|
// try to carve any existing data
|
||||||
lfsr_rat_t right_rat_ = {.tag=0};
|
lfsr_rat_t right_rat_ = {.tag=0};
|
||||||
while (pos < file->b.shrub.weight) {
|
while (pos < file->b.shrub.weight) {
|
||||||
lfsr_tag_t tag_;
|
|
||||||
lfsr_bid_t weight_;
|
lfsr_bid_t weight_;
|
||||||
lfsr_bptr_t bptr_;
|
lfsr_bptr_t bptr_;
|
||||||
int err = lfsr_file_lookupnext(lfs, file, pos,
|
int err = lfsr_file_lookupnext(lfs, file, pos,
|
||||||
&bid, &tag_, &weight_, &bptr_);
|
&bid, &weight_, &bptr_);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
return err;
|
||||||
@@ -11334,7 +11330,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
#ifdef LFS_CKFETCHES
|
#ifdef LFS_CKFETCHES
|
||||||
// checking fetches?
|
// checking fetches?
|
||||||
if (lfsr_m_isckfetches(lfs->flags)
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
&& tag_ == LFSR_TAG_BLOCK) {
|
&& lfsr_bptr_isbptr(&bptr_)) {
|
||||||
err = lfsr_bptr_ck(lfs, &bptr_);
|
err = lfsr_bptr_ck(lfs, &bptr_);
|
||||||
if (err) {
|
if (err) {
|
||||||
return 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
|
// left sibling needs carving but falls underneath our
|
||||||
// crystallization threshold? break into fragments
|
// 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->fragment_size
|
||||||
&& lfsr_data_size(left_slice_) < lfs->cfg->crystal_thresh) {
|
&& lfsr_data_size(left_slice_) < lfs->cfg->crystal_thresh) {
|
||||||
bptr_.data = LFSR_DATA_SLICE(bptr_.data,
|
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
|
// right sibling needs carving but falls underneath our
|
||||||
// crystallization threshold? break into fragments
|
// 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->fragment_size
|
||||||
&& lfsr_data_size(right_slice_) < lfs->cfg->crystal_thresh) {
|
&& lfsr_data_size(right_slice_) < lfs->cfg->crystal_thresh) {
|
||||||
bptr_.data = LFSR_DATA_SLICE(bptr_.data,
|
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());
|
LFSR_TAG_GROW, -(bid+1 - pos), LFSR_DATA_NULL());
|
||||||
|
|
||||||
// carve fragment?
|
// carve fragment?
|
||||||
} else if (tag_ == LFSR_TAG_DATA) {
|
} else if (!lfsr_bptr_isbptr(&bptr_)) {
|
||||||
left.data = left_slice_;
|
left.data = left_slice_;
|
||||||
rats[rat_count++] = LFSR_RAT_CAT_(
|
rats[rat_count++] = LFSR_RAT_CAT_(
|
||||||
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
|
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);
|
&left.data, 1);
|
||||||
|
|
||||||
// carve bptr?
|
// carve bptr?
|
||||||
} else if (tag_ == LFSR_TAG_BLOCK) {
|
} else {
|
||||||
|
bptr_.data = left_slice_;
|
||||||
rats[rat_count++] = LFSR_RAT(
|
rats[rat_count++] = LFSR_RAT(
|
||||||
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
|
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
|
||||||
-(bid+1 - pos),
|
-(bid+1 - pos),
|
||||||
LFSR_DATA_BPTR(
|
LFSR_DATA_BPTR(&bptr_, left.buf));
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// completely overwriting this entry?
|
// 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);
|
rat.weight += bid+1 - (pos+weight);
|
||||||
|
|
||||||
// carve fragment?
|
// carve fragment?
|
||||||
} else if (tag_ == LFSR_TAG_DATA) {
|
} else if (!lfsr_bptr_isbptr(&bptr_)) {
|
||||||
right.data = right_slice_;
|
right.data = right_slice_;
|
||||||
right_rat_ = LFSR_RAT_CAT_(
|
right_rat_ = LFSR_RAT_CAT_(
|
||||||
tag_,
|
LFSR_TAG_DATA,
|
||||||
bid+1 - (pos+weight),
|
bid+1 - (pos+weight),
|
||||||
&right.data, 1);
|
&right.data, 1);
|
||||||
|
|
||||||
// carve bptr?
|
// 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 {
|
} 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
|
// don't bother to lookup left after the first block
|
||||||
&& !aligned) {
|
&& !aligned) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
int err = lfsr_file_lookupnext(lfs, file,
|
int err = lfsr_file_lookupnext(lfs, file,
|
||||||
lfs_smax(pos - (lfs->cfg->crystal_thresh-1), 0),
|
lfs_smax(pos - (lfs->cfg->crystal_thresh-1), 0),
|
||||||
&bid, &tag, &weight, &bptr);
|
&bid, &weight, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
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
|
// if left crystal neighbor is a fragment and there is no
|
||||||
// obvious hole between our own crystal and our neighbor,
|
// obvious hole between our own crystal and our neighbor,
|
||||||
// include as a part of our crystal
|
// 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
|
// hole? holes can be quite large and shouldn't trigger
|
||||||
// crystallization
|
// crystallization
|
||||||
&& (lfs_soff_t)(bid-(weight-1)+lfsr_data_size(bptr.data))
|
&& (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);
|
crystal_start = lfs_min(bid+1, pos);
|
||||||
|
|
||||||
// wait, found erased-state?
|
// 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.block == file->eblock
|
||||||
&& bptr.data.u.disk.off + lfsr_data_size(bptr.data)
|
&& bptr.data.u.disk.off + lfsr_data_size(bptr.data)
|
||||||
== file->eoff
|
== 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
|
if (crystal_end - crystal_start < lfs->cfg->crystal_thresh
|
||||||
&& file->b.shrub.weight > 0) {
|
&& file->b.shrub.weight > 0) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
int err = lfsr_file_lookupnext(lfs, file,
|
int err = lfsr_file_lookupnext(lfs, file,
|
||||||
lfs_min(
|
lfs_min(
|
||||||
crystal_start + (lfs->cfg->crystal_thresh-1),
|
crystal_start + (lfs->cfg->crystal_thresh-1),
|
||||||
file->b.shrub.weight-1),
|
file->b.shrub.weight-1),
|
||||||
&bid, &tag, &weight, &bptr);
|
&bid, &weight, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
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
|
// if right crystal neighbor is a fragment, include as a part
|
||||||
// of our crystal
|
// of our crystal
|
||||||
if (tag == LFSR_TAG_DATA) {
|
if (!lfsr_bptr_isbptr(&bptr)) {
|
||||||
crystal_end = lfs_max(
|
crystal_end = lfs_max(
|
||||||
bid-(weight-1)+lfsr_data_size(bptr.data),
|
bid-(weight-1)+lfsr_data_size(bptr.data),
|
||||||
pos + size);
|
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
|
// don't bother to lookup left after the first block
|
||||||
&& !aligned) {
|
&& !aligned) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
int err = lfsr_file_lookupnext(lfs, file,
|
int err = lfsr_file_lookupnext(lfs, file,
|
||||||
lfs_min(
|
lfs_min(
|
||||||
crystal_start-1,
|
crystal_start-1,
|
||||||
file->b.shrub.weight-1),
|
file->b.shrub.weight-1),
|
||||||
&bid, &tag, &weight, &bptr);
|
&bid, &weight, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
return err;
|
||||||
@@ -11694,7 +11667,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
block_start = bid-(weight-1);
|
block_start = bid-(weight-1);
|
||||||
|
|
||||||
// wait, found erased-state?
|
// 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.block == file->eblock
|
||||||
&& bptr.data.u.disk.off + lfsr_data_size(bptr.data)
|
&& bptr.data.u.disk.off + lfsr_data_size(bptr.data)
|
||||||
== file->eoff
|
== file->eoff
|
||||||
@@ -11728,13 +11701,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
bptr.data = LFSR_DATA_DISKCKSUM(block, 0, 0, 0, 0);
|
lfsr_bptr_init(&bptr, LFSR_DATA_DISK(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;
|
|
||||||
|
|
||||||
compact:;
|
compact:;
|
||||||
// compact data into our block
|
// 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?
|
// any data on disk?
|
||||||
if (pos_ < file->b.shrub.weight) {
|
if (pos_ < file->b.shrub.weight) {
|
||||||
lfsr_bid_t bid_;
|
lfsr_bid_t bid_;
|
||||||
lfsr_tag_t tag_;
|
|
||||||
lfsr_bid_t weight_;
|
lfsr_bid_t weight_;
|
||||||
lfsr_bptr_t bptr_;
|
lfsr_bptr_t bptr_;
|
||||||
int err = lfsr_file_lookupnext(lfs, file, pos_,
|
int err = lfsr_file_lookupnext(lfs, file, pos_,
|
||||||
&bid_, &tag_, &weight_, &bptr_);
|
&bid_, &weight_, &bptr_);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
return err;
|
||||||
@@ -11804,7 +11770,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
#ifdef LFS_CKFETCHES
|
#ifdef LFS_CKFETCHES
|
||||||
// checking fetches?
|
// checking fetches?
|
||||||
if (lfsr_m_isckfetches(lfs->flags)
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
&& tag_ == LFSR_TAG_BLOCK) {
|
&& lfsr_bptr_isbptr(&bptr_)) {
|
||||||
err = lfsr_bptr_ck(lfs, &bptr_);
|
err = lfsr_bptr_ck(lfs, &bptr_);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -11911,10 +11877,11 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
// prepare our block pointer
|
// prepare our block pointer
|
||||||
LFS_ASSERT(lfsr_bptr_cksize(&bptr) > 0);
|
LFS_ASSERT(lfsr_bptr_cksize(&bptr) > 0);
|
||||||
LFS_ASSERT(lfsr_bptr_cksize(&bptr) <= lfs->cfg->block_size);
|
LFS_ASSERT(lfsr_bptr_cksize(&bptr) <= lfs->cfg->block_size);
|
||||||
bptr.data = LFSR_DATA_DISKCKSUM(
|
lfsr_bptr_init(&bptr,
|
||||||
bptr.data.u.disk.block,
|
LFSR_DATA_DISK(
|
||||||
bptr.data.u.disk.off,
|
bptr.data.u.disk.block,
|
||||||
lfsr_bptr_cksize(&bptr) - bptr.data.u.disk.off,
|
bptr.data.u.disk.off,
|
||||||
|
lfsr_bptr_cksize(&bptr) - bptr.data.u.disk.off),
|
||||||
lfsr_bptr_cksize(&bptr),
|
lfsr_bptr_cksize(&bptr),
|
||||||
lfsr_bptr_cksum(&bptr));
|
lfsr_bptr_cksum(&bptr));
|
||||||
lfs_off_t block_end = block_start + lfsr_data_size(bptr.data);
|
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
|
// don't bother to lookup left after first fragment
|
||||||
&& !aligned) {
|
&& !aligned) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
lfsr_bptr_t bptr;
|
lfsr_bptr_t bptr;
|
||||||
int err = lfsr_file_lookupnext(lfs, file,
|
int err = lfsr_file_lookupnext(lfs, file,
|
||||||
fragment_start-1,
|
fragment_start-1,
|
||||||
&bid, &tag, &weight, &bptr);
|
&bid, &weight, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
return err;
|
||||||
@@ -11977,7 +11943,7 @@ fragment:;
|
|||||||
#ifdef LFS_CKFETCHES
|
#ifdef LFS_CKFETCHES
|
||||||
// checking fetches?
|
// checking fetches?
|
||||||
if (lfsr_m_isckfetches(lfs->flags)
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
&& tag == LFSR_TAG_BLOCK) {
|
&& lfsr_bptr_isbptr(&bptr)) {
|
||||||
err = lfsr_bptr_ck(lfs, &bptr);
|
err = lfsr_bptr_ck(lfs, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -12011,12 +11977,11 @@ fragment:;
|
|||||||
// don't bother to lookup right if fragment is already full
|
// don't bother to lookup right if fragment is already full
|
||||||
&& fragment_end - fragment_start < lfs->cfg->fragment_size) {
|
&& fragment_end - fragment_start < lfs->cfg->fragment_size) {
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
lfsr_bptr_t bptr;
|
lfsr_bptr_t bptr;
|
||||||
int err = lfsr_file_lookupnext(lfs, file,
|
int err = lfsr_file_lookupnext(lfs, file,
|
||||||
fragment_end,
|
fragment_end,
|
||||||
&bid, &tag, &weight, &bptr);
|
&bid, &weight, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
return err;
|
||||||
@@ -12025,7 +11990,7 @@ fragment:;
|
|||||||
#ifdef LFS_CKFETCHES
|
#ifdef LFS_CKFETCHES
|
||||||
// checking fetches?
|
// checking fetches?
|
||||||
if (lfsr_m_isckfetches(lfs->flags)
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
&& tag == LFSR_TAG_BLOCK) {
|
&& lfsr_bptr_isbptr(&bptr)) {
|
||||||
err = lfsr_bptr_ck(lfs, &bptr);
|
err = lfsr_bptr_ck(lfs, &bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -595,14 +595,15 @@ struct lfs_file_config {
|
|||||||
// lfs_block_t tail[2];
|
// lfs_block_t tail[2];
|
||||||
//} lfs_mdir_t;
|
//} 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
|
// from the compiler being able to aggresively optimize this struct
|
||||||
//
|
//
|
||||||
typedef struct lfsr_data {
|
typedef struct lfsr_data {
|
||||||
// sign(size)=0 => in-RAM buffer
|
// sign2(size)=0b00 => in-RAM buffer
|
||||||
// sign(size)=1 => on-disk reference
|
// sign2(size)=0b10 => on-disk data
|
||||||
|
// sign2(size)=0b11 => on-disk data + cksum
|
||||||
lfs_size_t size;
|
lfs_size_t size;
|
||||||
union {
|
union {
|
||||||
const uint8_t *buffer;
|
const uint8_t *buffer;
|
||||||
@@ -611,8 +612,6 @@ typedef struct lfsr_data {
|
|||||||
lfs_size_t off;
|
lfs_size_t off;
|
||||||
// optional context for validating data
|
// optional context for validating data
|
||||||
#ifdef LFS_CKDATACKSUMS
|
#ifdef LFS_CKDATACKSUMS
|
||||||
// cksize==0 => no checksum
|
|
||||||
// cksize!=0 => yes checksum
|
|
||||||
lfs_size_t cksize;
|
lfs_size_t cksize;
|
||||||
uint32_t cksum;
|
uint32_t cksum;
|
||||||
#endif
|
#endif
|
||||||
@@ -620,8 +619,11 @@ typedef struct lfsr_data {
|
|||||||
} u;
|
} u;
|
||||||
} lfsr_data_t;
|
} lfsr_data_t;
|
||||||
|
|
||||||
// a block pointer
|
// a possible block pointer
|
||||||
typedef struct lfsr_bptr {
|
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;
|
lfsr_data_t data;
|
||||||
#ifndef LFS_CKDATACKSUMS
|
#ifndef LFS_CKDATACKSUMS
|
||||||
lfs_size_t cksize;
|
lfs_size_t cksize;
|
||||||
|
|||||||
Reference in New Issue
Block a user