Implemented ckfetches
Ckfetches implements what might be your first idea on how to check
checksums in a filesystem: Check each block/mdir on first access
(fetch) to make sure the data is sound.
Unfortunately, there are two problems with this approach, both which
come from the fact that blocks are big and can't fit in RAM:
1. We still have a checksum-read hole.
We can't keep a whole block around in RAM, so reads after a fetch may
need to reread from disk, at which point new bit-errors may slip in
undetected.
This is especially problematic for traversing our rbyds, which
involves a lot of small reads in a block.
2. Ckfetches may have a surprisingly negative performance impact.
Consider the case of reading a large file with a bunch of small
reads. Because we don't cache blocks, each read may need a btree
lookup, and a full block fetch. On paper this can quickly end up
O(b^2), which is not great.
Though this is helped by the file buffer. It will be interesting to
benchmark and see if this theoretical O(b^2) translates to poor
performance in practice.
Note ckreads has this same performance issue.
Still, despite these problems, ckfetches may be useful for cases where
you just want an extra layer of safety, or don't care about the tiny
chance an error is introduced between a fetch an subsequent read.
---
Like ckprogs/ckreads, ckfetches is an opt-in feature, and requires both
1. defining LFS_CKFETCHES, and 2. passing LFS_M_CKFETCHES during mount.
This is a bit of a quick implementation to get testing in place, so the
code cost is probably higher than strictly necessary. If we can refactor
the code internally to avoid all the duplicate lfsr_rbyd_fetchck/
lfsr_bptr_ck calls, we can probably bring this down a bit:
code stack
before: 36428 2680
yes-ckfetches: 36848 (+1.2%) 2680 (+0.0%)
no-ckfetches: 36428 (+0.0%) 2680 (+0.0%)
Oh, and also added lfs_emubd_flipbit to allow tests to manually flip
bits themselves. LFS_EMUBD_BADBLOCK_PROGFLIP is quick to find the above
mentioned checksum-read hole.
This could be done manually with read+erase+prog, but no reason to make
it harder than it needs to be.
This commit is contained in:
@@ -1232,6 +1232,30 @@ int lfs_emubd_markbadbit(const struct lfs_config *cfg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lfs_emubd_flipbit(const struct lfs_config *cfg,
|
||||||
|
lfs_block_t block, lfs_size_t bit) {
|
||||||
|
LFS_EMUBD_TRACE("lfs_emubd_flipbit(%p, %"PRIu32", %"PRIu32")",
|
||||||
|
(void*)cfg, block, bit);
|
||||||
|
lfs_emubd_t *bd = cfg->context;
|
||||||
|
|
||||||
|
// check if block is valid
|
||||||
|
LFS_ASSERT(block < cfg->block_count);
|
||||||
|
|
||||||
|
// mutate the block
|
||||||
|
lfs_emubd_block_t *b = lfs_emubd_mutblock(cfg, bd->blocks[block]);
|
||||||
|
if (!b) {
|
||||||
|
LFS_EMUBD_TRACE("lfs_emubd_flipbit -> %d", LFS_ERR_NOMEM);
|
||||||
|
return LFS_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
bd->blocks[block] = b;
|
||||||
|
|
||||||
|
// flip the bit
|
||||||
|
b->data[bit/8] ^= 1 << (bit%8);
|
||||||
|
|
||||||
|
LFS_EMUBD_TRACE("lfs_emubd_flipbit -> %d", 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
lfs_emubd_spowercycles_t lfs_emubd_powercycles(
|
lfs_emubd_spowercycles_t lfs_emubd_powercycles(
|
||||||
const struct lfs_config *cfg) {
|
const struct lfs_config *cfg) {
|
||||||
LFS_EMUBD_TRACE("lfs_emubd_powercycles(%p)", (void*)cfg);
|
LFS_EMUBD_TRACE("lfs_emubd_powercycles(%p)", (void*)cfg);
|
||||||
|
|||||||
@@ -241,6 +241,10 @@ int lfs_emubd_randomizebadbit(const struct lfs_config *cfg,
|
|||||||
int lfs_emubd_markbadbit(const struct lfs_config *cfg,
|
int lfs_emubd_markbadbit(const struct lfs_config *cfg,
|
||||||
lfs_block_t block, lfs_size_t bit);
|
lfs_block_t block, lfs_size_t bit);
|
||||||
|
|
||||||
|
// Flip a bit in a given block, intended for emulating bit errors
|
||||||
|
int lfs_emubd_flipbit(const struct lfs_config *cfg,
|
||||||
|
lfs_block_t block, lfs_size_t bit);
|
||||||
|
|
||||||
// Get the remaining power-cycles
|
// Get the remaining power-cycles
|
||||||
lfs_emubd_spowercycles_t lfs_emubd_powercycles(
|
lfs_emubd_spowercycles_t lfs_emubd_powercycles(
|
||||||
const struct lfs_config *cfg);
|
const struct lfs_config *cfg);
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ static int lfsr_bd_prog_(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LFS_CKPROGS
|
#ifdef LFS_CKPROGS
|
||||||
// check progs?
|
// checking progs?
|
||||||
if (lfsr_m_isckprogs(lfs->flags)) {
|
if (lfsr_m_isckprogs(lfs->flags)) {
|
||||||
// pcache should have been dropped at this point
|
// pcache should have been dropped at this point
|
||||||
LFS_ASSERT(lfs->pcache.size == 0);
|
LFS_ASSERT(lfs->pcache.size == 0);
|
||||||
@@ -4794,6 +4794,11 @@ static int lfsr_data_readbtree(lfs_t *lfs, lfsr_data_t *data,
|
|||||||
|
|
||||||
// core btree operations
|
// core btree operations
|
||||||
|
|
||||||
|
// needed in lfsr_btree_lookupnext_
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
static inline bool lfsr_m_isckfetches(uint32_t flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree,
|
static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree,
|
||||||
lfsr_bid_t bid,
|
lfsr_bid_t bid,
|
||||||
lfsr_bid_t *bid_, lfsr_rbyd_t *rbyd_, lfsr_srid_t *rid_,
|
lfsr_bid_t *bid_, lfsr_rbyd_t *rbyd_, lfsr_srid_t *rid_,
|
||||||
@@ -4833,6 +4838,18 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &branch,
|
||||||
|
branch.blocks[0], lfsr_rbyd_trunk(&branch),
|
||||||
|
branch.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// found our bid
|
// found our bid
|
||||||
} else {
|
} else {
|
||||||
// TODO how many of these should be conditional?
|
// TODO how many of these should be conditional?
|
||||||
@@ -4946,6 +4963,18 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &branch_,
|
||||||
|
branch_.blocks[0], lfsr_rbyd_trunk(&branch_),
|
||||||
|
branch_.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
branch = branch_;
|
branch = branch_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5117,6 +5146,18 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &sibling,
|
||||||
|
sibling.blocks[0], lfsr_rbyd_trunk(&sibling),
|
||||||
|
sibling.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// estimate if our sibling will fit
|
// estimate if our sibling will fit
|
||||||
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
|
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
|
||||||
&sibling, -1, -1,
|
&sibling, -1, -1,
|
||||||
@@ -5165,6 +5206,18 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &sibling,
|
||||||
|
sibling.blocks[0], lfsr_rbyd_trunk(&sibling),
|
||||||
|
sibling.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// estimate if our sibling will fit
|
// estimate if our sibling will fit
|
||||||
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
|
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimate(lfs,
|
||||||
&sibling, -1, -1,
|
&sibling, -1, -1,
|
||||||
@@ -5607,6 +5660,18 @@ static lfs_scmp_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &branch,
|
||||||
|
branch.blocks[0], lfsr_rbyd_trunk(&branch),
|
||||||
|
branch.cksum);
|
||||||
|
if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// found our rid
|
// found our rid
|
||||||
} else {
|
} else {
|
||||||
// TODO how many of these should be conditional?
|
// TODO how many of these should be conditional?
|
||||||
@@ -5703,6 +5768,19 @@ static int lfsr_btree_traverse(lfs_t *lfs, const lfsr_btree_t *btree,
|
|||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &bt->rbyd,
|
||||||
|
bt->rbyd.blocks[0], lfsr_rbyd_trunk(&bt->rbyd),
|
||||||
|
bt->rbyd.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LFS_ASSERT((lfsr_bid_t)bt->rbyd.weight == weight__);
|
LFS_ASSERT((lfsr_bid_t)bt->rbyd.weight == weight__);
|
||||||
bt->branch = &bt->rbyd;
|
bt->branch = &bt->rbyd;
|
||||||
|
|
||||||
@@ -6697,6 +6775,12 @@ static inline bool lfsr_m_isckreads(uint32_t flags) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
static inline bool lfsr_m_isckfetches(uint32_t flags) {
|
||||||
|
return flags & LFS_M_CKFETCHES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline bool lfsr_m_isflush(uint32_t flags) {
|
static inline bool lfsr_m_isflush(uint32_t flags) {
|
||||||
return flags & LFS_M_FLUSH;
|
return flags & LFS_M_FLUSH;
|
||||||
}
|
}
|
||||||
@@ -9185,6 +9269,19 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &t->o.bshrub.u.btree,
|
||||||
|
t->o.bshrub.u.btree.blocks[0],
|
||||||
|
lfsr_rbyd_trunk(&t->o.bshrub.u.btree),
|
||||||
|
t->o.bshrub.u.btree.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// transition to traversing the mtree
|
// transition to traversing the mtree
|
||||||
t->u.bt = LFSR_BTRAVERSAL();
|
t->u.bt = LFSR_BTRAVERSAL();
|
||||||
t->o.o.flags = lfsr_t_settstate(t->o.o.flags,
|
t->o.o.flags = lfsr_t_settstate(t->o.o.flags,
|
||||||
@@ -9266,6 +9363,19 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &t->o.bshrub.u.btree,
|
||||||
|
t->o.bshrub.u.btree.blocks[0],
|
||||||
|
lfsr_rbyd_trunk(&t->o.bshrub.u.btree),
|
||||||
|
t->o.bshrub.u.btree.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// no? next we need to check any opened files
|
// no? next we need to check any opened files
|
||||||
} else {
|
} else {
|
||||||
t->ot = lfs->omdirs;
|
t->ot = lfs->omdirs;
|
||||||
@@ -10726,6 +10836,19 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)) {
|
||||||
|
err = lfsr_rbyd_fetchck(lfs, &file->o.bshrub.u.btree,
|
||||||
|
file->o.bshrub.u.btree.blocks[0],
|
||||||
|
lfsr_rbyd_trunk(&file->o.bshrub.u.btree),
|
||||||
|
file->o.bshrub.u.btree.cksum);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10847,6 +10970,17 @@ static lfs_ssize_t lfsr_file_readnext(lfs_t *lfs, const lfsr_file_t *file,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
|
&& tag == LFSR_TAG_BLOCK) {
|
||||||
|
err = lfsr_bptr_ck(lfs, &bptr);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// any data on disk?
|
// any data on disk?
|
||||||
if (pos_ < bid-(weight-1) + lfsr_data_size(bptr.data)) {
|
if (pos_ < bid-(weight-1) + lfsr_data_size(bptr.data)) {
|
||||||
// note one important side-effect here is a strict
|
// note one important side-effect here is a strict
|
||||||
@@ -11089,6 +11223,17 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
|
&& tag_ == LFSR_TAG_BLOCK) {
|
||||||
|
err = lfsr_bptr_ck(lfs, &bptr_);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// note, an entry can be both a left and right sibling
|
// note, an entry can be both a left and right sibling
|
||||||
lfsr_data_t left_slice_ = lfsr_data_slice(bptr_.data,
|
lfsr_data_t left_slice_ = lfsr_data_slice(bptr_.data,
|
||||||
-1,
|
-1,
|
||||||
@@ -11556,6 +11701,17 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
|
&& tag_ == LFSR_TAG_BLOCK) {
|
||||||
|
err = lfsr_bptr_ck(lfs, &bptr_);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// make sure to include all of our crystal, or else this
|
// make sure to include all of our crystal, or else this
|
||||||
// loop may never terminate
|
// loop may never terminate
|
||||||
if (bid_-(weight_-1) >= crystal_end
|
if (bid_-(weight_-1) >= crystal_end
|
||||||
@@ -11718,6 +11874,17 @@ fragment:;
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
|
&& tag == LFSR_TAG_BLOCK) {
|
||||||
|
err = lfsr_bptr_ck(lfs, &bptr);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// can we coalesce?
|
// can we coalesce?
|
||||||
if (bid-(weight-1) + lfsr_data_size(bptr.data) >= fragment_start
|
if (bid-(weight-1) + lfsr_data_size(bptr.data) >= fragment_start
|
||||||
&& fragment_end - (bid-(weight-1))
|
&& fragment_end - (bid-(weight-1))
|
||||||
@@ -11756,6 +11923,17 @@ fragment:;
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
// checking fetches?
|
||||||
|
if (lfsr_m_isckfetches(lfs->flags)
|
||||||
|
&& tag == LFSR_TAG_BLOCK) {
|
||||||
|
err = lfsr_bptr_ck(lfs, &bptr);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// can we coalesce?
|
// can we coalesce?
|
||||||
if (fragment_end < bid-(weight-1) + lfsr_data_size(bptr.data)
|
if (fragment_end < bid-(weight-1) + lfsr_data_size(bptr.data)
|
||||||
&& bid-(weight-1) + lfsr_data_size(bptr.data)
|
&& bid-(weight-1) + lfsr_data_size(bptr.data)
|
||||||
@@ -13353,6 +13531,7 @@ int lfsr_mount(lfs_t *lfs, uint32_t flags,
|
|||||||
| LFS_M_RDONLY
|
| LFS_M_RDONLY
|
||||||
| LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, 0)
|
| LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, 0)
|
||||||
| LFS_IFDEF_CKREADS(LFS_M_CKREADS, 0)
|
| LFS_IFDEF_CKREADS(LFS_M_CKREADS, 0)
|
||||||
|
| LFS_IFDEF_CKFETCHES(LFS_M_CKFETCHES, 0)
|
||||||
| LFS_M_FLUSH
|
| LFS_M_FLUSH
|
||||||
| LFS_M_SYNC
|
| LFS_M_SYNC
|
||||||
| LFS_M_MTREEONLY
|
| LFS_M_MTREEONLY
|
||||||
@@ -13509,6 +13688,7 @@ int lfsr_format(lfs_t *lfs, uint32_t flags,
|
|||||||
LFS_F_RDWR
|
LFS_F_RDWR
|
||||||
| LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, 0)
|
| LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, 0)
|
||||||
| LFS_IFDEF_CKREADS(LFS_F_CKREADS, 0)
|
| LFS_IFDEF_CKREADS(LFS_F_CKREADS, 0)
|
||||||
|
| LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, 0)
|
||||||
| LFS_F_MTREEONLY
|
| LFS_F_MTREEONLY
|
||||||
| LFS_F_COMPACT
|
| LFS_F_COMPACT
|
||||||
| LFS_F_CKMETA
|
| LFS_F_CKMETA
|
||||||
@@ -13574,6 +13754,7 @@ int lfsr_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
|
|||||||
LFS_I_RDONLY
|
LFS_I_RDONLY
|
||||||
| LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, 0)
|
| LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, 0)
|
||||||
| LFS_IFDEF_CKREADS(LFS_I_CKREADS, 0)
|
| LFS_IFDEF_CKREADS(LFS_I_CKREADS, 0)
|
||||||
|
| LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, 0)
|
||||||
| LFS_I_FLUSH
|
| LFS_I_FLUSH
|
||||||
| LFS_I_SYNC
|
| LFS_I_SYNC
|
||||||
| LFS_I_UNCOMPACTED);
|
| LFS_I_UNCOMPACTED);
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ enum lfs_type {
|
|||||||
#ifdef LFS_CKREADS
|
#ifdef LFS_CKREADS
|
||||||
#define LFS_F_CKREADS 0x00200000 // Check reads via parity bits/checksums
|
#define LFS_F_CKREADS 0x00200000 // Check reads via parity bits/checksums
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
#define LFS_F_CKFETCHES 0x00400000 // Check checksums before reads
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LFS_F_MTREEONLY 0x00000800 // Only traverse the mtree
|
#define LFS_F_MTREEONLY 0x00000800 // Only traverse the mtree
|
||||||
#define LFS_F_COMPACT 0x00008000 // Compact metadata logs
|
#define LFS_F_COMPACT 0x00008000 // Compact metadata logs
|
||||||
@@ -176,6 +179,9 @@ enum lfs_type {
|
|||||||
#ifdef LFS_CKREADS
|
#ifdef LFS_CKREADS
|
||||||
#define LFS_M_CKREADS 0x00200000 // Check reads via parity bits/checksums
|
#define LFS_M_CKREADS 0x00200000 // Check reads via parity bits/checksums
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
#define LFS_M_CKFETCHES 0x00400000 // Check checksums before reads
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LFS_M_MTREEONLY 0x00000800 // Only traverse the mtree
|
#define LFS_M_MTREEONLY 0x00000800 // Only traverse the mtree
|
||||||
#define LFS_M_MKCONSISTENT \
|
#define LFS_M_MKCONSISTENT \
|
||||||
@@ -195,6 +201,9 @@ enum lfs_type {
|
|||||||
#ifdef LFS_CKREADS
|
#ifdef LFS_CKREADS
|
||||||
#define LFS_I_CKREADS 0x00200000 // Filesystem mounted with LFS_M_CKREADS
|
#define LFS_I_CKREADS 0x00200000 // Filesystem mounted with LFS_M_CKREADS
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
#define LFS_I_CKFETCHES 0x00400000 // Filesystem mounted with LFS_M_CKFETCHES
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LFS_I_INCONSISTENT \
|
#define LFS_I_INCONSISTENT \
|
||||||
0x01000000 // Filesystem needs mkconsistent to write
|
0x01000000 // Filesystem needs mkconsistent to write
|
||||||
|
|||||||
@@ -150,6 +150,12 @@ extern "C"
|
|||||||
#define LFS_IFDEF_CKREADS(a, b) (b)
|
#define LFS_IFDEF_CKREADS(a, b) (b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LFS_CKFETCHES
|
||||||
|
#define LFS_IFDEF_CKFETCHES(a, b) (a)
|
||||||
|
#else
|
||||||
|
#define LFS_IFDEF_CKFETCHES(a, b) (b)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Builtin functions, these may be replaced by more efficient
|
// Builtin functions, these may be replaced by more efficient
|
||||||
// toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more
|
// toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more
|
||||||
|
|||||||
+307
-5
@@ -770,8 +770,6 @@ code = '''
|
|||||||
|
|
||||||
|
|
||||||
# Some simple ckread tests
|
# Some simple ckread tests
|
||||||
#
|
|
||||||
# We test these much more aggressively in test_badblocks
|
|
||||||
|
|
||||||
# These tests were originally intended to test all single-bit
|
# These tests were originally intended to test all single-bit
|
||||||
# metastability errors with ckreads, however they quickly found that
|
# metastability errors with ckreads, however they quickly found that
|
||||||
@@ -883,7 +881,7 @@ code = '''
|
|||||||
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
|
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
|
||||||
assert(!err
|
assert(!err
|
||||||
|| err == LFS_ERR_CORRUPT
|
|| err == LFS_ERR_CORRUPT
|
||||||
// metastability can also cause our fs state to "rollback",
|
// bit errors can also cause our fs state to "rollback",
|
||||||
// which is not great but we can't solve this with ckreads
|
// which is not great but we can't solve this with ckreads
|
||||||
// alone
|
// alone
|
||||||
|| err == LFS_ERR_NOENT);
|
|| err == LFS_ERR_NOENT);
|
||||||
@@ -1015,7 +1013,7 @@ code = '''
|
|||||||
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
|
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
|
||||||
assert(!err
|
assert(!err
|
||||||
|| err == LFS_ERR_CORRUPT
|
|| err == LFS_ERR_CORRUPT
|
||||||
// metastability can also cause our fs state to "rollback",
|
// bit errors can also cause our fs state to "rollback",
|
||||||
// which is not great but we can't solve this with ckreads
|
// which is not great but we can't solve this with ckreads
|
||||||
// alone
|
// alone
|
||||||
|| err == LFS_ERR_NOENT);
|
|| err == LFS_ERR_NOENT);
|
||||||
@@ -1151,7 +1149,7 @@ code = '''
|
|||||||
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
|
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
|
||||||
assert(!err
|
assert(!err
|
||||||
|| err == LFS_ERR_CORRUPT
|
|| err == LFS_ERR_CORRUPT
|
||||||
// metastability can also cause our fs state to "rollback",
|
// bit errors can also cause our fs state to "rollback",
|
||||||
// which is not great but we can't solve this with ckreads
|
// which is not great but we can't solve this with ckreads
|
||||||
// alone
|
// alone
|
||||||
|| err == LFS_ERR_NOENT);
|
|| err == LFS_ERR_NOENT);
|
||||||
@@ -1177,3 +1175,307 @@ code = '''
|
|||||||
lfs_emubd_markgood(CFG, badblock) => 0;
|
lfs_emubd_markgood(CFG, badblock) => 0;
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Some simple ckfetches tests
|
||||||
|
|
||||||
|
# test every single-bit error in block 0/1
|
||||||
|
[cases.test_ck_ckfetches_mroot]
|
||||||
|
defines.BADBLOCK = [0, 1]
|
||||||
|
defines.BADBIT = -1
|
||||||
|
# this should stay inlined
|
||||||
|
defines.SIZE = 'BLOCK_SIZE/16'
|
||||||
|
ifdef = 'LFS_CKFETCHES'
|
||||||
|
code = '''
|
||||||
|
// test all bad bits in the mroot
|
||||||
|
for (lfs_size_t i = 0;
|
||||||
|
i < ((BADBIT == -1) ? 8*BLOCK_SIZE : 1);
|
||||||
|
i++) {
|
||||||
|
lfs_size_t badbit = (BADBIT == -1) ? i : BADBIT;
|
||||||
|
|
||||||
|
printf("--- badblock: 0x%x.%x, badbit: 0x%x (0x%x+%x) ---\n",
|
||||||
|
(lfs_size_t)BADBLOCK, badbit/8, badbit, badbit/8, badbit%8);
|
||||||
|
|
||||||
|
// format
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR | LFS_F_CKFETCHES, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKFETCHES, CFG) => 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
// create a file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "tripedalia",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
uint32_t prng = 42;
|
||||||
|
uint8_t wbuf[SIZE];
|
||||||
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE;
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// try to read our file
|
||||||
|
for (int remount = 0; remount < 2; remount++) {
|
||||||
|
// remount?
|
||||||
|
if (remount) {
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// flip our badbit
|
||||||
|
lfs_emubd_flipbit(CFG, BADBLOCK, badbit) => 0;
|
||||||
|
|
||||||
|
int err = lfsr_mount(&lfs,
|
||||||
|
LFS_M_RDWR | LFS_M_CKFETCHES, CFG);
|
||||||
|
assert(!err || err == LFS_ERR_CORRUPT);
|
||||||
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
|
goto corrupt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// yes reads can fail here
|
||||||
|
int err = lfsr_file_open(&lfs, &file,
|
||||||
|
"tripedalia", LFS_O_RDONLY);
|
||||||
|
assert(!err
|
||||||
|
// bit errors can also cause our fs state to "rollback",
|
||||||
|
// which is not great but we can't solve this with
|
||||||
|
// ckfetches alone
|
||||||
|
|| err == LFS_ERR_NOENT);
|
||||||
|
if (err == LFS_ERR_NOENT) {
|
||||||
|
goto corrupt_mounted;
|
||||||
|
}
|
||||||
|
uint8_t rbuf[SIZE];
|
||||||
|
lfsr_file_read(&lfs, &file, rbuf, SIZE) => SIZE;
|
||||||
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
corrupt_mounted:;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
corrupt:;
|
||||||
|
// reset badbit
|
||||||
|
lfs_emubd_markgood(CFG, BADBLOCK) => 0;
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
# test every single-bit error in a file's data block
|
||||||
|
[cases.test_ck_ckfetches_data]
|
||||||
|
defines.BADBIT = -1
|
||||||
|
# this should create a single block file
|
||||||
|
defines.SIZE = 'BLOCK_SIZE'
|
||||||
|
ifdef = 'LFS_CKFETCHES'
|
||||||
|
code = '''
|
||||||
|
// first we need to figure out where the data block will actually
|
||||||
|
// end up, fortunately our block randomization is intentionally
|
||||||
|
// consistent
|
||||||
|
|
||||||
|
// format
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR | LFS_F_CKFETCHES, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKFETCHES, CFG) => 0;
|
||||||
|
|
||||||
|
// create a file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "tripedalia",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
uint32_t prng = 42;
|
||||||
|
uint8_t wbuf[SIZE];
|
||||||
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE;
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// find the data block
|
||||||
|
lfsr_traversal_t t;
|
||||||
|
lfsr_traversal_open(&lfs, &t, 0) => 0;
|
||||||
|
lfs_block_t badblock;
|
||||||
|
while (true) {
|
||||||
|
struct lfs_tinfo tinfo;
|
||||||
|
lfsr_traversal_read(&lfs, &t, &tinfo) => 0;
|
||||||
|
if (tinfo.btype == LFS_BTYPE_DATA) {
|
||||||
|
badblock = tinfo.block;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lfsr_traversal_close(&lfs, &t) => 0;
|
||||||
|
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// now test all bad bits in the data block
|
||||||
|
for (lfs_size_t i = 0;
|
||||||
|
i < ((BADBIT == -1) ? 8*BLOCK_SIZE : 1);
|
||||||
|
i++) {
|
||||||
|
lfs_size_t badbit = (BADBIT == -1) ? i : BADBIT;
|
||||||
|
|
||||||
|
printf("--- badblock: 0x%x.%x, badbit: 0x%x (0x%x+%x) ---\n",
|
||||||
|
badblock, badbit/8, badbit, badbit/8, badbit%8);
|
||||||
|
|
||||||
|
// format
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR | LFS_F_CKFETCHES, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKFETCHES, CFG) => 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
// create a file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "tripedalia",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
uint32_t prng = 42;
|
||||||
|
uint8_t wbuf[SIZE];
|
||||||
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE;
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// flip our badbit
|
||||||
|
lfs_emubd_flipbit(CFG, badblock, badbit) => 0;
|
||||||
|
|
||||||
|
// try to read our file
|
||||||
|
for (int remount = 0; remount < 2; remount++) {
|
||||||
|
// remount?
|
||||||
|
if (remount) {
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKFETCHES, CFG) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// yes reads can fail here
|
||||||
|
int err = lfsr_file_open(&lfs, &file,
|
||||||
|
"tripedalia", LFS_O_RDONLY);
|
||||||
|
assert(!err || err == LFS_ERR_CORRUPT);
|
||||||
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
|
goto corrupt_mounted;
|
||||||
|
}
|
||||||
|
uint8_t rbuf[SIZE];
|
||||||
|
lfs_ssize_t res = lfsr_file_read(&lfs, &file, rbuf, SIZE);
|
||||||
|
assert(res == SIZE || res == LFS_ERR_CORRUPT);
|
||||||
|
if (res == LFS_ERR_CORRUPT) {
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
goto corrupt_mounted;
|
||||||
|
}
|
||||||
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
corrupt_mounted:;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// reset badbit
|
||||||
|
lfs_emubd_markgood(CFG, badblock) => 0;
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
# test every single-bit error in a file's btree node
|
||||||
|
[cases.test_ck_ckfetches_btree]
|
||||||
|
defines.BADBIT = -1
|
||||||
|
# force the file to create a btree
|
||||||
|
defines.INLINE_SIZE = 0
|
||||||
|
defines.CRYSTAL_THRESH = -1
|
||||||
|
defines.FRAGMENT_SIZE = 'BLOCK_SIZE/8'
|
||||||
|
defines.SIZE = '2*FRAGMENT_SIZE'
|
||||||
|
ifdef = 'LFS_CKFETCHES'
|
||||||
|
code = '''
|
||||||
|
// first we need to figure out where the btree block will actually
|
||||||
|
// end up, fortunately our block randomization is intentionally
|
||||||
|
// consistent
|
||||||
|
|
||||||
|
// format
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR | LFS_F_CKFETCHES, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKFETCHES, CFG) => 0;
|
||||||
|
|
||||||
|
// create a file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "tripedalia",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
uint32_t prng = 42;
|
||||||
|
uint8_t wbuf[SIZE];
|
||||||
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE;
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// find the btree block
|
||||||
|
lfsr_traversal_t t;
|
||||||
|
lfsr_traversal_open(&lfs, &t, 0) => 0;
|
||||||
|
lfs_block_t badblock;
|
||||||
|
while (true) {
|
||||||
|
struct lfs_tinfo tinfo;
|
||||||
|
lfsr_traversal_read(&lfs, &t, &tinfo) => 0;
|
||||||
|
if (tinfo.btype == LFS_BTYPE_BTREE) {
|
||||||
|
badblock = tinfo.block;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lfsr_traversal_close(&lfs, &t) => 0;
|
||||||
|
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// now test all bad bits in the btree block
|
||||||
|
for (lfs_size_t i = 0;
|
||||||
|
i < ((BADBIT == -1) ? 8*BLOCK_SIZE : 1);
|
||||||
|
i++) {
|
||||||
|
lfs_size_t badbit = (BADBIT == -1) ? i : BADBIT;
|
||||||
|
|
||||||
|
printf("--- badblock: 0x%x.%x, badbit: 0x%x (0x%x+%x) ---\n",
|
||||||
|
badblock, badbit/8, badbit, badbit/8, badbit%8);
|
||||||
|
|
||||||
|
// format
|
||||||
|
lfs_t lfs;
|
||||||
|
lfsr_format(&lfs, LFS_F_RDWR | LFS_F_CKFETCHES, CFG) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKFETCHES, CFG) => 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
// create a file
|
||||||
|
lfsr_file_t file;
|
||||||
|
lfsr_file_open(&lfs, &file, "tripedalia",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||||
|
uint32_t prng = 42;
|
||||||
|
uint8_t wbuf[SIZE];
|
||||||
|
for (lfs_size_t j = 0; j < SIZE; j++) {
|
||||||
|
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||||
|
}
|
||||||
|
lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE;
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
|
||||||
|
// flip our badbit
|
||||||
|
lfs_emubd_flipbit(CFG, badblock, badbit) => 0;
|
||||||
|
|
||||||
|
// try to read our file
|
||||||
|
for (int remount = 0; remount < 2; remount++) {
|
||||||
|
// remount?
|
||||||
|
if (remount) {
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKFETCHES, CFG) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// yes reads can fail here
|
||||||
|
int err = lfsr_file_open(&lfs, &file,
|
||||||
|
"tripedalia", LFS_O_RDONLY);
|
||||||
|
assert(!err || err == LFS_ERR_CORRUPT);
|
||||||
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
|
goto corrupt_mounted;
|
||||||
|
}
|
||||||
|
uint8_t rbuf[SIZE];
|
||||||
|
lfs_ssize_t res = lfsr_file_read(&lfs, &file, rbuf, SIZE);
|
||||||
|
assert(res == SIZE || res == LFS_ERR_CORRUPT);
|
||||||
|
if (res == LFS_ERR_CORRUPT) {
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
goto corrupt_mounted;
|
||||||
|
}
|
||||||
|
assert(memcmp(rbuf, wbuf, SIZE) == 0);
|
||||||
|
lfsr_file_close(&lfs, &file) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
corrupt_mounted:;
|
||||||
|
lfsr_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// reset badbit
|
||||||
|
lfs_emubd_markgood(CFG, badblock) => 0;
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ code = '''
|
|||||||
defines.RDONLY = [false, true]
|
defines.RDONLY = [false, true]
|
||||||
defines.CKPROGS = [false, true]
|
defines.CKPROGS = [false, true]
|
||||||
defines.CKREADS = [false, true]
|
defines.CKREADS = [false, true]
|
||||||
|
defines.CKFETCHES = [false, true]
|
||||||
defines.FLUSH = [false, true]
|
defines.FLUSH = [false, true]
|
||||||
defines.SYNC = [false, true]
|
defines.SYNC = [false, true]
|
||||||
defines.MTREEONLY = [false, true]
|
defines.MTREEONLY = [false, true]
|
||||||
@@ -28,6 +29,7 @@ defines.CKDATA = [false, true]
|
|||||||
if = [
|
if = [
|
||||||
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
|
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
|
||||||
'LFS_IFDEF_CKREADS(true, !CKREADS)',
|
'LFS_IFDEF_CKREADS(true, !CKREADS)',
|
||||||
|
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
|
||||||
'!RDONLY || !MKCONSISTENT',
|
'!RDONLY || !MKCONSISTENT',
|
||||||
'!RDONLY || !LOOKAHEAD',
|
'!RDONLY || !LOOKAHEAD',
|
||||||
'!RDONLY || !COMPACT',
|
'!RDONLY || !COMPACT',
|
||||||
@@ -41,6 +43,7 @@ code = '''
|
|||||||
((RDONLY) ? LFS_M_RDONLY : LFS_M_RDWR)
|
((RDONLY) ? LFS_M_RDONLY : LFS_M_RDWR)
|
||||||
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, -1) : 0)
|
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_M_CKPROGS, -1) : 0)
|
||||||
| ((CKREADS) ? LFS_IFDEF_CKREADS(LFS_M_CKREADS, -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)
|
| ((FLUSH) ? LFS_M_FLUSH : 0)
|
||||||
| ((SYNC) ? LFS_M_SYNC : 0)
|
| ((SYNC) ? LFS_M_SYNC : 0)
|
||||||
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
|
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
|
||||||
@@ -58,6 +61,7 @@ code = '''
|
|||||||
((RDONLY) ? LFS_I_RDONLY : 0)
|
((RDONLY) ? LFS_I_RDONLY : 0)
|
||||||
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, -1) : 0)
|
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_I_CKPROGS, -1) : 0)
|
||||||
| ((CKREADS) ? LFS_IFDEF_CKREADS(LFS_I_CKREADS, -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)
|
| ((FLUSH) ? LFS_I_FLUSH : 0)
|
||||||
| ((SYNC) ? LFS_I_SYNC : 0)
|
| ((SYNC) ? LFS_I_SYNC : 0)
|
||||||
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
|
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
|
||||||
@@ -72,6 +76,7 @@ code = '''
|
|||||||
[cases.test_mount_format_flags]
|
[cases.test_mount_format_flags]
|
||||||
defines.CKPROGS = [false, true]
|
defines.CKPROGS = [false, true]
|
||||||
defines.CKREADS = [false, true]
|
defines.CKREADS = [false, true]
|
||||||
|
defines.CKFETCHES = [false, true]
|
||||||
defines.MTREEONLY = [false, true]
|
defines.MTREEONLY = [false, true]
|
||||||
defines.COMPACT = [false, true]
|
defines.COMPACT = [false, true]
|
||||||
defines.CKMETA = [false, true]
|
defines.CKMETA = [false, true]
|
||||||
@@ -79,6 +84,7 @@ defines.CKDATA = [false, true]
|
|||||||
if = [
|
if = [
|
||||||
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
|
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
|
||||||
'LFS_IFDEF_CKREADS(true, !CKREADS)',
|
'LFS_IFDEF_CKREADS(true, !CKREADS)',
|
||||||
|
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
|
||||||
'!MTREEONLY || !CKDATA',
|
'!MTREEONLY || !CKDATA',
|
||||||
]
|
]
|
||||||
code = '''
|
code = '''
|
||||||
@@ -87,6 +93,7 @@ code = '''
|
|||||||
LFS_F_RDWR
|
LFS_F_RDWR
|
||||||
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
|
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
|
||||||
| ((CKREADS) ? LFS_IFDEF_CKREADS(LFS_F_CKREADS, -1) : 0)
|
| ((CKREADS) ? LFS_IFDEF_CKREADS(LFS_F_CKREADS, -1) : 0)
|
||||||
|
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
|
||||||
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
|
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
|
||||||
| ((COMPACT) ? LFS_M_COMPACT : 0)
|
| ((COMPACT) ? LFS_M_COMPACT : 0)
|
||||||
| ((CKMETA) ? LFS_M_CKMETA : 0)
|
| ((CKMETA) ? LFS_M_CKMETA : 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user