Relegated ckreads -> ckparity

Ckparity is pretty flawed in littlefs, for several reasons. The biggest
one being that we can't even reliably detect single-bit errors.

But! It can still provide an extra layer of safety in a system where you
don't care about the extra code/stack cost.

And, for ckreads, performance cost...

Performance isn't a big problem for parity-checking. We can assume
metadata tags are going to relatively small (and can be controlled by
fragment_size). But for data checksums, ckreads risks O(b^2) when
performing many small reads, which can be a bit of a problem.

And since ckreads doesn't really prove anything interesting about the
system anymore, it makes sense to unbundle these two checks, rename
ckreads -> ckparity, and limit it to only checking parity bits.

This way, you can enable ckparity for a bit of extra safety, with a
code/stack cost hit, but without sacrificing performance.

---

I was hoping more code/stack savings, but since we still need to track
parity context in lfsr_data_t, and still need to intercept bd_read/cmp/
cpy calls that reference metadata, we end up needing to keep most of
the ck circuitry around:

                    code          stack
  default before:  36464           2672
  default after:   36464 (+0.0%)   2672 (+0.0%)

                    code          stack
  ckparity before: 38036           3080
  ckparity after:  38024 (-0.0%)   3080 (+0.0%)

We even end up still tracking checksum context for bptrs! Maybe we
should just go ahead and add ckcksums as a joke...
This commit is contained in:
Christopher Haster
2024-08-16 14:51:59 -05:00
parent fa04c41f5c
commit 2d121c8d19
5 changed files with 475 additions and 611 deletions
+91 -96
View File
@@ -699,18 +699,18 @@ static int lfsr_bd_set(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
/// lfsr_ck_t stuff ///
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_CK_ISPARITY 0x80000000
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_CK_CKSUM(_cksize, _cksum) \
((lfsr_ck_t){ \
.cksize=_cksize, \
.u.cksum=_cksum})
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_CK_PARITY(_ckoff, _cksize) \
((lfsr_ck_t){ \
.cksize=LFSR_CK_ISPARITY | (_cksize), \
@@ -718,25 +718,25 @@ static int lfsr_bd_set(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
#endif
// ck helpers
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static inline bool lfsr_ck_isparity(lfsr_ck_t ck) {
return ck.cksize & LFSR_CK_ISPARITY;
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static inline bool lfsr_ck_iscksum(lfsr_ck_t ck) {
return !(ck.cksize & LFSR_CK_ISPARITY);
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static inline lfs_size_t lfsr_ck_cksize(lfsr_ck_t ck) {
return ck.cksize & ~LFSR_CK_ISPARITY;
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static inline lfs_size_t lfsr_ck_ckoff(lfsr_ck_t ck) {
if (lfsr_ck_isparity(ck)) {
return ck.u.ckoff;
@@ -751,23 +751,23 @@ static inline lfs_size_t lfsr_ck_ckoff(lfsr_ck_t ck) {
// tailck tracks the most recent trunk's parity so we can parity-check
// if it hasn't been written to disk yet
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_TAILCK_PARITY 0x80000000
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static inline bool lfsr_tailck_parity(const lfsr_tailck_t *tailck) {
return tailck->ckoff & LFSR_TAILCK_PARITY;
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static inline lfs_size_t lfsr_tailck_ckoff(const lfsr_tailck_t *tailck) {
return tailck->ckoff & ~LFSR_TAILCK_PARITY;
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// read the pesky parity byte from disk
static lfs_sbool_t lfsr_bd_readparity(lfs_t *lfs,
lfs_block_t block, lfs_size_t off, lfs_size_t hint) {
@@ -801,7 +801,7 @@ static lfs_sbool_t lfsr_bd_readparity(lfs_t *lfs,
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static lfs_ssize_t lfsr_bd_ckprefix(lfs_t *lfs,
lfs_block_t block, lfs_size_t off, lfs_size_t hint,
lfsr_ck_t ck,
@@ -809,6 +809,8 @@ static lfs_ssize_t lfsr_bd_ckprefix(lfs_t *lfs,
// must be in-bounds
LFS_ASSERT(block < lfs->block_count);
LFS_ASSERT(lfsr_ck_ckoff(ck)+lfsr_ck_cksize(ck) <= lfs->cfg->block_size);
// only parity checking is currently supported
LFS_ASSERT(lfsr_ck_isparity(ck));
// make sure hint includes our prefix/suffix/pesky parity byte
lfs_size_t hint_ = lfs_max(
@@ -816,7 +818,7 @@ static lfs_ssize_t lfsr_bd_ckprefix(lfs_t *lfs,
(off-lfsr_ck_ckoff(ck)) + lfs_min(
hint,
lfs->cfg->block_size - off),
lfsr_ck_cksize(ck) + ((lfsr_ck_isparity(ck)) ? 1 : 0));
lfsr_ck_cksize(ck) + 1);
// checksum any prefixed data
int err = lfsr_bd_cksum(lfs,
@@ -833,7 +835,7 @@ static lfs_ssize_t lfsr_bd_ckprefix(lfs_t *lfs,
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static int lfsr_bd_cksuffix(lfs_t *lfs,
lfs_block_t block, lfs_size_t off, lfs_size_t hint,
lfsr_ck_t ck,
@@ -841,6 +843,8 @@ static int lfsr_bd_cksuffix(lfs_t *lfs,
// must be in-bounds
LFS_ASSERT(block < lfs->block_count);
LFS_ASSERT(lfsr_ck_ckoff(ck)+lfsr_ck_cksize(ck) <= lfs->cfg->block_size);
// only parity checking is currently supported
LFS_ASSERT(lfsr_ck_isparity(ck));
// make sure hint includes our pesky parity byte
lfs_size_t hint_ = lfs_max(
@@ -856,46 +860,34 @@ static int lfsr_bd_cksuffix(lfs_t *lfs,
return err;
}
if (lfsr_ck_isparity(ck)) {
// need to read the next byte, which should contain our parity
LFS_ASSERT(lfsr_ck_ckoff(ck)+lfsr_ck_cksize(ck)
< lfs->cfg->block_size);
lfs_sbool_t parity = lfsr_bd_readparity(lfs,
block, lfsr_ck_ckoff(ck)+lfsr_ck_cksize(ck),
hint_ - (lfsr_ck_cksize(ck)-off));
if (parity < 0) {
return parity;
}
// need to read the next byte, which should contain our parity
LFS_ASSERT(lfsr_ck_ckoff(ck)+lfsr_ck_cksize(ck)
< lfs->cfg->block_size);
lfs_sbool_t parity = lfsr_bd_readparity(lfs,
block, lfsr_ck_ckoff(ck)+lfsr_ck_cksize(ck),
hint_ - (lfsr_ck_cksize(ck)-off));
if (parity < 0) {
return parity;
}
// does parity match?
if (lfs_parity(cksum) != parity) {
LFS_ERROR("Found ckread parity mismatch "
"0x%"PRIx32".%"PRIx32" %"PRId32", "
"parity %01"PRIx32" (!= %01"PRIx32")",
block, lfsr_ck_ckoff(ck), lfsr_ck_cksize(ck),
lfs_parity(cksum), parity);
return LFS_ERR_CORRUPT;
}
} else {
// do checksums match?
if (cksum != ck.u.cksum) {
LFS_ERROR("Found ckread cksum mismatch "
"0x%"PRIx32".%"PRIx32" %"PRId32", "
"cksum %08"PRIx32" (!= %08"PRIx32")",
block, lfsr_ck_ckoff(ck), lfsr_ck_cksize(ck),
cksum, ck.u.cksum);
return LFS_ERR_CORRUPT;
}
// does parity match?
if (lfs_parity(cksum) != parity) {
LFS_ERROR("Found ckparity mismatch "
"0x%"PRIx32".%"PRIx32" %"PRId32", "
"parity %01"PRIx32" (!= %01"PRIx32")",
block, lfsr_ck_ckoff(ck), lfsr_ck_cksize(ck),
lfs_parity(cksum), parity);
return LFS_ERR_CORRUPT;
}
return 0;
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// caching read with parity/checksum checks
//
// the main downside of ckreads is we need to read all data that
// the main downside of checking reads is we need to read all data that
// contributes to the relevant parity/checksum, this may be
// significantly more than the data we actually end up using
//
@@ -939,16 +931,17 @@ static int lfsr_bd_readck_(lfs_t *lfs,
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// needed in lfsr_bd_readck
static inline bool lfsr_m_isckreads(uint32_t flags);
static inline bool lfsr_m_isckparity(uint32_t flags);
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,
lfsr_ck_t ck) {
// are we actually checking reads?
if (lfsr_m_isckreads(lfs->flags)) {
// check this read?
if (lfsr_m_isckparity(lfs->flags)
&& lfsr_ck_isparity(ck)) {
return lfsr_bd_readck_(lfs,
block, off, hint,
buffer, size,
@@ -962,7 +955,7 @@ static int lfsr_bd_readck(lfs_t *lfs,
#endif
// redirect to lfsr_bd_read if not checking reads
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_BD_READCK(_lfs, _block, _off, _hint, _buffer, _size, _ck) \
lfsr_bd_readck(_lfs, _block, _off, _hint, _buffer, _size, _ck)
#else
@@ -976,7 +969,7 @@ static int lfsr_bd_readck(lfs_t *lfs,
//
// we'd also need to worry about early termination in lfsr_bd_cmp/cmpck
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
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,
@@ -1037,13 +1030,14 @@ static lfs_scmp_t lfsr_bd_cmpck_(lfs_t *lfs,
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
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,
lfsr_ck_t ck) {
// are we actually checking reads?
if (lfsr_m_isckreads(lfs->flags)) {
// check this read?
if (lfsr_m_isckparity(lfs->flags)
&& lfsr_ck_isparity(ck)) {
return lfsr_bd_cmpck_(lfs,
block, off, hint,
buffer, size,
@@ -1057,7 +1051,7 @@ static lfs_scmp_t lfsr_bd_cmpck(lfs_t *lfs,
#endif
// redirect to lfsr_bd_cmp if not checking reads
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_BD_CMPCK(_lfs, _block, _off, _hint, _buffer, _size, _ck) \
lfsr_bd_cmpck(_lfs, _block, _off, _hint, _buffer, _size, _ck)
#else
@@ -1065,7 +1059,7 @@ static lfs_scmp_t lfsr_bd_cmpck(lfs_t *lfs,
lfsr_bd_cmp(_lfs, _block, _off, _hint, _buffer, _size)
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static int lfsr_bd_cpyck_(lfs_t *lfs,
lfs_block_t dst_block, lfs_size_t dst_off,
lfs_block_t src_block, lfs_size_t src_off, lfs_size_t hint,
@@ -1137,15 +1131,16 @@ static int lfsr_bd_cpyck_(lfs_t *lfs,
}
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
static int lfsr_bd_cpyck(lfs_t *lfs,
lfs_block_t dst_block, lfs_size_t dst_off,
lfs_block_t src_block, lfs_size_t src_off, lfs_size_t hint,
lfs_size_t size,
lfsr_ck_t ck,
uint32_t *cksum, bool align) {
// are we actually checking reads?
if (lfsr_m_isckreads(lfs->flags)) {
// check this read?
if (lfsr_m_isckparity(lfs->flags)
&& lfsr_ck_isparity(ck)) {
return lfsr_bd_cpyck_(lfs,
dst_block, dst_off,
src_block, src_off, hint,
@@ -1163,7 +1158,7 @@ static int lfsr_bd_cpyck(lfs_t *lfs,
#endif
// redirect to lfsr_bd_cpy if not checking reads
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_BD_CPYCK(_lfs, \
_dst_block, _dst_off, \
_src_block, _src_off, _hint, \
@@ -1711,13 +1706,13 @@ static lfs_ssize_t lfsr_bd_readtag(lfs_t *lfs,
*cksum = lfs_crc32c(*cksum, tag_buf, d);
}
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// check the parity if we're checking reads and not already
// calculating a checksum
//
// this requires reading all of the data as well, but with any luck
// the data will stick around in the cache
if (lfsr_m_isckreads(lfs->flags) && !cksum) {
if (lfsr_m_isckparity(lfs->flags) && !cksum) {
// pesky parity byte
lfs_size_t size__ = (!lfsr_tag_isalt(tag)) ? size : 0;
if (off+d+size__ >= lfs->cfg->block_size) {
@@ -1808,7 +1803,7 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs,
.size=_size, \
.u.buffer=(const void*)(_buffer)})
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_DATA_DISKCKSUM(_block, _off, _size, _cksize, _cksum) \
((lfsr_data_t){ \
.size=LFSR_DATA_ONDISK | (_size), \
@@ -1823,7 +1818,7 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs,
.u.disk.off=_off})
#endif
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
#define LFSR_DATA_DISKPARITY(_block, _off, _size, _ckoff, _cksize) \
((lfsr_data_t){ \
.size=LFSR_DATA_ONDISK | (_size), \
@@ -2481,11 +2476,11 @@ static int lfsr_data_readecksum(lfs_t *lfs, lfsr_data_t *data,
#define LFSR_DATA_BPTR(_bptr) \
LFSR_DATA_BPTR_(_bptr, (uint8_t[LFSR_BPTR_DSIZE]){0})
// checked reads introduces ck info into lfsr_data_t that we don't want
// to unnecessarily duplicate, so accessing ck info gets annoyingly
// messy...
// checked reads adds ck info to lfsr_data_t that we don't want to
// unnecessarily duplicate, long story short accessing ck info gets
// annoyingly messy...
static inline lfs_size_t lfsr_bptr_cksize(const lfsr_bptr_t *bptr) {
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
return bptr->data.u.disk.ck.cksize;
#else
return bptr->cksize;
@@ -2493,7 +2488,7 @@ static inline lfs_size_t lfsr_bptr_cksize(const lfsr_bptr_t *bptr) {
}
static inline uint32_t lfsr_bptr_cksum(const lfsr_bptr_t *bptr) {
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
return bptr->data.u.disk.ck.u.cksum;
#else
return bptr->cksum;
@@ -2564,7 +2559,7 @@ static int lfsr_data_readbptr(lfs_t *lfs, lfsr_data_t *data,
// read the cksize, cksum
err = lfsr_data_readlleb128(lfs, data,
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
&bptr->data.u.disk.ck.cksize,
&bptr->cksize));
if (err) {
@@ -2572,7 +2567,7 @@ static int lfsr_data_readbptr(lfs_t *lfs, lfsr_data_t *data,
}
err = lfsr_data_readle32(lfs, data,
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
&bptr->data.u.disk.ck.u.cksum,
&bptr->cksum));
if (err) {
@@ -3245,7 +3240,7 @@ static int lfsr_rbyd_appendtag(lfs_t *lfs, lfsr_rbyd_t *rbyd,
rbyd->eoff += d;
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// keep track of most recent parity
lfs->tailck.ckblock = rbyd->blocks[0];
lfs->tailck.ckoff
@@ -3276,7 +3271,7 @@ static int lfsr_rbyd_appendcat(lfs_t *lfs, lfsr_rbyd_t *rbyd,
rbyd->eoff += lfsr_cat_size(cat, count);
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// keep track of most recent parity
lfs->tailck.ckblock = rbyd->blocks[0];
lfs->tailck.ckoff
@@ -6766,9 +6761,9 @@ static inline bool lfsr_m_isckprogs(uint32_t flags) {
}
#endif
#ifdef LFS_CKREADS
static inline bool lfsr_m_isckreads(uint32_t flags) {
return flags & LFS_M_CKREADS;
#ifdef LFS_CKPARITY
static inline bool lfsr_m_isckparity(uint32_t flags) {
return flags & LFS_M_CKPARITY;
}
#endif
@@ -11291,7 +11286,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
-(bid+1 - pos),
LFSR_DATA_BPTR_(
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
(&(lfsr_bptr_t){
.data=left_slice_}),
(&(lfsr_bptr_t){
@@ -11349,7 +11344,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
tag_,
bid+1 - (pos+weight),
LFSR_DATA_BPTR_(
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
(&(lfsr_bptr_t){
.data=right_slice_}),
(&(lfsr_bptr_t){
@@ -11595,10 +11590,10 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
}
bptr.data = LFSR_DATA_DISKCKSUM(block, 0, 0, 0, 0);
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
bptr.data.u.disk.ck.cksize,
bptr.cksize) = 0;
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
bptr.data.u.disk.ck.u.cksum,
bptr.cksum) = 0;
@@ -11631,7 +11626,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
int err = lfsr_bd_prog(lfs, bptr.data.u.disk.block,
lfsr_bptr_cksize(&bptr),
&buffer[pos_ - pos], d_,
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
&bptr.data.u.disk.ck.u.cksum,
&bptr.cksum), true);
if (err) {
@@ -11644,7 +11639,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
}
pos_ += d_;
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
bptr.data.u.disk.ck.cksize,
bptr.cksize) += d_;
d -= d_;
@@ -11707,7 +11702,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
lfsr_data_slice(bptr_.data,
pos_ - (bid_-(weight_-1)),
d_),
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
&bptr.data.u.disk.ck.u.cksum,
&bptr.cksum), true);
if (err) {
@@ -11720,7 +11715,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
}
pos_ += d_;
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
bptr.data.u.disk.ck.cksize,
bptr.cksize) += d_;
d -= d_;
@@ -11734,7 +11729,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
int err = lfsr_bd_set(lfs,
bptr.data.u.disk.block, lfsr_bptr_cksize(&bptr),
0, d,
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
&bptr.data.u.disk.ck.u.cksum,
&bptr.cksum), true);
if (err) {
@@ -11747,7 +11742,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
}
pos_ += d;
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
bptr.data.u.disk.ck.cksize,
bptr.cksize) += d;
}
@@ -11758,12 +11753,12 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
// up reading more than is strictly necessary.
lfs_ssize_t d = lfsr_bptr_cksize(&bptr) % lfs->cfg->prog_size;
lfs->pcache.size -= d;
LFS_IFDEF_CKREADS(
LFS_IFDEF_CKPARITY(
bptr.data.u.disk.ck.cksize,
bptr.cksize) -= d;
// finalize our write
int err = lfsr_bd_flush(lfs, LFS_IFDEF_CKREADS(
int err = lfsr_bd_flush(lfs, LFS_IFDEF_CKPARITY(
&bptr.data.u.disk.ck.u.cksum,
&bptr.cksum), true);
if (err) {
@@ -12791,7 +12786,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags,
}
}
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// setup tailck, nothing should actually check off=0
lfs->tailck.ckblock = 0;
lfs->tailck.ckoff = 0;
@@ -13501,11 +13496,11 @@ int lfsr_mount(lfs_t *lfs, uint32_t flags,
LFS_ASSERT((flags & ~(
LFS_M_RDWR
| LFS_M_RDONLY
| LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, 0)
| LFS_IFDEF_CKREADS(LFS_M_CKREADS, 0)
| LFS_IFDEF_CKFETCHES(LFS_M_CKFETCHES, 0)
| LFS_M_FLUSH
| LFS_M_SYNC
| LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, 0)
| LFS_IFDEF_CKFETCHES(LFS_M_CKFETCHES, 0)
| LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, 0)
| LFS_M_MTREEONLY
| LFS_M_MKCONSISTENT
| LFS_M_LOOKAHEAD
@@ -13659,8 +13654,8 @@ int lfsr_format(lfs_t *lfs, uint32_t flags,
LFS_ASSERT((flags & ~(
LFS_F_RDWR
| LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, 0)
| LFS_IFDEF_CKREADS(LFS_F_CKREADS, 0)
| LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, 0)
| LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, 0)
| LFS_F_MTREEONLY
| LFS_F_COMPACT
| LFS_F_CKMETA
@@ -13724,11 +13719,11 @@ int lfsr_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
// return various filesystem flags
fsinfo->flags = lfs->flags & (
LFS_I_RDONLY
| LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, 0)
| LFS_IFDEF_CKREADS(LFS_I_CKREADS, 0)
| LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, 0)
| LFS_I_FLUSH
| LFS_I_SYNC
| LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, 0)
| LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, 0)
| LFS_IFDEF_CKPARITY(LFS_I_CKPARITY, 0)
| LFS_I_UNCOMPACTED);
// some flags we calculate on demand
fsinfo->flags |= (lfsr_fs_isinconsistent(lfs)) ? LFS_I_INCONSISTENT : 0;
+17 -17
View File
@@ -156,11 +156,11 @@ enum lfs_type {
#ifdef LFS_CKPROGS
#define LFS_F_CKPROGS 0x00100000 // Check progs by reading back progged data
#endif
#ifdef LFS_CKREADS
#define LFS_F_CKREADS 0x00200000 // Check reads via parity bits/checksums
#endif
#ifdef LFS_CKFETCHES
#define LFS_F_CKFETCHES 0x00400000 // Check checksums before reads
#define LFS_F_CKFETCHES 0x00200000 // Check block checksums before first use
#endif
#ifdef LFS_CKPARITY
#define LFS_F_CKPARITY 0x00400000 // Check tag parity bits on reads
#endif
#define LFS_F_MTREEONLY 0x00000800 // Only traverse the mtree
@@ -176,11 +176,11 @@ enum lfs_type {
#ifdef LFS_CKPROGS
#define LFS_M_CKPROGS 0x00100000 // Check progs by reading back progged data
#endif
#ifdef LFS_CKREADS
#define LFS_M_CKREADS 0x00200000 // Check reads via parity bits/checksums
#endif
#ifdef LFS_CKFETCHES
#define LFS_M_CKFETCHES 0x00400000 // Check checksums before reads
#define LFS_M_CKFETCHES 0x00200000 // Check block checksums before first use
#endif
#ifdef LFS_CKPARITY
#define LFS_M_CKPARITY 0x00400000 // Check tag parity bits on reads
#endif
#define LFS_M_MTREEONLY 0x00000800 // Only traverse the mtree
@@ -198,11 +198,11 @@ enum lfs_type {
#ifdef LFS_CKPROGS
#define LFS_I_CKPROGS 0x00100000 // Filesystem mounted with LFS_M_CKPROGS
#endif
#ifdef LFS_CKREADS
#define LFS_I_CKREADS 0x00200000 // Filesystem mounted with LFS_M_CKREADS
#endif
#ifdef LFS_CKFETCHES
#define LFS_I_CKFETCHES 0x00400000 // Filesystem mounted with LFS_M_CKFETCHES
#define LFS_I_CKFETCHES 0x00200000 // Filesystem mounted with LFS_M_CKFETCHES
#endif
#ifdef LFS_CKPARITY
#define LFS_I_CKPARITY 0x00400000 // Filesystem mounted with LFS_M_CKPARITY
#endif
#define LFS_I_INCONSISTENT \
@@ -559,7 +559,7 @@ typedef struct lfsr_omdir {
// lfs_block_t tail[2];
//} lfs_mdir_t;
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
// context for validating data
typedef struct lfsr_ck {
// sign(cksize)=0 => cksum check
@@ -582,7 +582,7 @@ typedef struct lfsr_data {
struct {
lfs_block_t block;
lfs_size_t off;
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
lfsr_ck_t ck;
#endif
} disk;
@@ -615,7 +615,7 @@ typedef lfsr_data_t lfsr_sprout_t;
typedef struct lfsr_bptr {
lfsr_data_t data;
#ifndef LFS_CKREADS
#ifndef LFS_CKPARITY
lfs_size_t cksize;
uint32_t cksum;
#endif
@@ -757,7 +757,7 @@ typedef struct lfsr_grm {
lfsr_smid_t mids[2];
} lfsr_grm_t;
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
typedef struct lfsr_tailck {
lfs_block_t ckblock;
// sign(ckoff) => tail parity
@@ -797,7 +797,7 @@ typedef struct lfs {
uint8_t *buffer;
} pcache;
#ifdef LFS_CKREADS
#ifdef LFS_CKPARITY
lfsr_tailck_t tailck;
#endif
+6 -6
View File
@@ -144,18 +144,18 @@ extern "C"
#define LFS_IFDEF_CKPROGS(a, b) (b)
#endif
#ifdef LFS_CKREADS
#define LFS_IFDEF_CKREADS(a, b) (a)
#else
#define LFS_IFDEF_CKREADS(a, b) (b)
#endif
#ifdef LFS_CKFETCHES
#define LFS_IFDEF_CKFETCHES(a, b) (a)
#else
#define LFS_IFDEF_CKFETCHES(a, b) (b)
#endif
#ifdef LFS_CKPARITY
#define LFS_IFDEF_CKPARITY(a, b) (a)
#else
#define LFS_IFDEF_CKPARITY(a, b) (b)
#endif
// Builtin functions, these may be replaced by more efficient
// toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more
+348 -479
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -15,11 +15,11 @@ code = '''
# lfsr_fs_stat
[cases.test_mount_flags]
defines.RDONLY = [false, true]
defines.CKPROGS = [false, true]
defines.CKREADS = [false, true]
defines.CKFETCHES = [false, true]
defines.FLUSH = [false, true]
defines.SYNC = [false, true]
defines.CKPROGS = [false, true]
defines.CKFETCHES = [false, true]
defines.CKPARITY = [false, true]
defines.MTREEONLY = [false, true]
defines.MKCONSISTENT = [false, true]
defines.LOOKAHEAD = [false, true]
@@ -28,8 +28,8 @@ defines.CKMETA = [false, true]
defines.CKDATA = [false, true]
if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKREADS(true, !CKREADS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'!RDONLY || !MKCONSISTENT',
'!RDONLY || !LOOKAHEAD',
'!RDONLY || !COMPACT',
@@ -41,11 +41,11 @@ code = '''
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
lfsr_mount(&lfs,
((RDONLY) ? LFS_M_RDONLY : LFS_M_RDWR)
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, -1) : 0)
| ((CKREADS) ? LFS_IFDEF_CKREADS(LFS_M_CKREADS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_M_CKFETCHES, -1) : 0)
| ((FLUSH) ? LFS_M_FLUSH : 0)
| ((SYNC) ? LFS_M_SYNC : 0)
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_M_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1) : 0)
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
| ((MKCONSISTENT) ? LFS_M_MKCONSISTENT : 0)
| ((LOOKAHEAD) ? LFS_M_LOOKAHEAD : 0)
@@ -59,11 +59,11 @@ code = '''
lfsr_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.flags == (
((RDONLY) ? LFS_I_RDONLY : 0)
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, -1) : 0)
| ((CKREADS) ? LFS_IFDEF_CKREADS(LFS_I_CKREADS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, -1) : 0)
| ((FLUSH) ? LFS_I_FLUSH : 0)
| ((SYNC) ? LFS_I_SYNC : 0)
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_I_CKPARITY, -1) : 0)
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)));
@@ -75,16 +75,16 @@ code = '''
# these end up passed to mount internally
[cases.test_mount_format_flags]
defines.CKPROGS = [false, true]
defines.CKREADS = [false, true]
defines.CKFETCHES = [false, true]
defines.CKPARITY = [false, true]
defines.MTREEONLY = [false, true]
defines.COMPACT = [false, true]
defines.CKMETA = [false, true]
defines.CKDATA = [false, true]
if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKREADS(true, !CKREADS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'!MTREEONLY || !CKDATA',
]
code = '''
@@ -92,8 +92,8 @@ code = '''
lfsr_format(&lfs,
LFS_F_RDWR
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
| ((CKREADS) ? LFS_IFDEF_CKREADS(LFS_F_CKREADS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0)
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
| ((COMPACT) ? LFS_M_COMPACT : 0)
| ((CKMETA) ? LFS_M_CKMETA : 0)