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:
@@ -159,6 +159,9 @@ enum lfs_type {
|
||||
#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
|
||||
#endif
|
||||
|
||||
#define LFS_F_MTREEONLY 0x00000800 // Only traverse the mtree
|
||||
#define LFS_F_COMPACT 0x00008000 // Compact metadata logs
|
||||
@@ -176,6 +179,9 @@ enum lfs_type {
|
||||
#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
|
||||
#endif
|
||||
|
||||
#define LFS_M_MTREEONLY 0x00000800 // Only traverse the mtree
|
||||
#define LFS_M_MKCONSISTENT \
|
||||
@@ -195,6 +201,9 @@ enum lfs_type {
|
||||
#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
|
||||
#endif
|
||||
|
||||
#define LFS_I_INCONSISTENT \
|
||||
0x01000000 // Filesystem needs mkconsistent to write
|
||||
|
||||
Reference in New Issue
Block a user