Implemented ckcksums

Since we already need all the machinery to track ck info for ckparity, I
figured we might as well implement a full ckcksums option as well.

Ckcksums closes the checksum-read-hole by reading enough data to check a
relevant checksum on ever read, even if this ends up being significantly
more data than the initial request. This should always detect detectable
bit-errors, even if they occur between consecutive reads.

If this sounds naive, that's because it is. Performance will be awful.

To be clear, ckcksums should probably never be used in production. I
can't think of a use case that isn't better handled by either ECC in the
block device or the future-planned ckredund feature. Just look at the
runtime complexities:

                  small-reads  rbyd-lookup  rbyd-compaction
  ckcksums:            O(b^2)   O(b log b)     O(b^2 log b)
  ckredund*: O(log_b(n) + xb)     O(log b)       O(b log b)
  eccbd*:                O(b)     O(log b)       O(b log b)

  * theoretical

We've already seen that O(b^2) compactions turns a performance problem
into a tractability problem, so I think O(b^2 log b) compactions will be
a bit too much for most applications.

We can already seen this in our test_ck_ckcksums_* tests (which do pass
by the way!). Compare to test_ck_ckprogs_*, which is basically the same
set of tests:

  test_ck_ckprogs_*:   6.08s
  test_ck_ckcksums_*: 64.88s

Or consider test_rbyd with/without ckcksums:

  test_rbyd:           12.21s
  test_rbyd+ckcksums: 389.94s

Still, ckcksums is an interesting proof-of-concept, and does manage to
close the checksum-read-hole.

---

Like ckprogs/ckfetches/ckparity/etc, ckcksums is an opt-in feature,
requiring both 1. defining LFS_CKCKSUMS and 2. passing LFS_M_CKCKSUMS at
mount time.

Like ckparity, ckcksums requires a significant code and stack increase
to track ck info in lfsr_data_t:

                 code          stack
  before:       36416           2616
  yes-ckcksums: 38872 (+6.7%)   3176 (+21.4%)
  no-ckcksums:  36416 (+0.0%)   2616 (+0.0%)

It's interesting to note how this compares to all of the current
ck-modes, though each has their own set of tradeoffs:

                 code          stack
  default:      36416           2616
  ckprogs:      36468 (+0.1%)   2616 (+0.0%)
  ckfetches:    36666 (+0.7%)   2648 (+1.2%)
  ckparity:     37996 (+4.3%)   3040 (+16.2%)
  ckcksums:     38872 (+6.7%)   3176 (+21.4%)

---

Note that even though ckcksums is opt-in, it may still be worth removing
from the codebase in the future, for a couple reasons:

- Every feature, even if unused, adds developer/maintenance burden.

- Ck info is particularly messy with how it interacts with all
  lfsr_data_t APIs. Though getting rid of ck info would also require
  getting rid of ckparity.

- It's possible for a user to see ckcksums in the codebase,
  misunderstand its tradeoffs, enable it, and get the impression that
  littlefs itself is just unusably slow.
This commit is contained in:
Christopher Haster
2024-08-19 15:12:22 -05:00
parent 4515f4811a
commit 2f11fa71f4
5 changed files with 1001 additions and 143 deletions
+538 -116
View File
File diff suppressed because it is too large Load Diff
+14 -5
View File
@@ -162,6 +162,9 @@ enum lfs_type {
#ifdef LFS_CKPARITY
#define LFS_F_CKPARITY 0x00400000 // Check tag parity bits on reads
#endif
#ifdef LFS_CKCKSUMS
#define LFS_F_CKCKSUMS 0x00800000 // Check checksums on reads (expensive!)
#endif
#define LFS_F_MTREEONLY 0x00000800 // Only traverse the mtree
#define LFS_F_COMPACT 0x00008000 // Compact metadata logs
@@ -182,6 +185,9 @@ enum lfs_type {
#ifdef LFS_CKPARITY
#define LFS_M_CKPARITY 0x00400000 // Check tag parity bits on reads
#endif
#ifdef LFS_CKCKSUMS
#define LFS_M_CKCKSUMS 0x00800000 // Check checksums on reads (expensive!)
#endif
#define LFS_M_MTREEONLY 0x00000800 // Only traverse the mtree
#define LFS_M_MKCONSISTENT \
@@ -204,6 +210,9 @@ enum lfs_type {
#ifdef LFS_CKPARITY
#define LFS_I_CKPARITY 0x00400000 // Filesystem mounted with LFS_M_CKPARITY
#endif
#ifdef LFS_CKCKSUMS
#define LFS_I_CKCKSUMS 0x00800000 // Filesystem mounted with LFS_M_CKCKSUMS
#endif
#define LFS_I_INCONSISTENT \
0x01000000 // Filesystem needs mkconsistent to write
@@ -559,7 +568,7 @@ typedef struct lfsr_omdir {
// lfs_block_t tail[2];
//} lfs_mdir_t;
#ifdef LFS_CKPARITY
#if defined(LFS_CKPARITY) || defined(LFS_CKCKSUMS)
// context for validating data
typedef struct lfsr_ck {
// sign(cksize)=0 => cksum check
@@ -583,7 +592,7 @@ typedef struct lfsr_data {
struct {
lfs_block_t block;
lfs_size_t off;
#ifdef LFS_CKPARITY
#if defined(LFS_CKPARITY) || defined(LFS_CKCKSUMS)
lfsr_ck_t ck;
#endif
} disk;
@@ -758,11 +767,11 @@ typedef struct lfsr_grm {
lfsr_smid_t mids[2];
} lfsr_grm_t;
#ifdef LFS_CKPARITY
#if defined(LFS_CKPARITY) || defined(LFS_CKCKSUMS)
typedef struct lfsr_tailck {
lfs_block_t ckblock;
// sign(ckoff) => tail parity
lfs_size_t ckoff;
uint32_t cksum;
} lfsr_tailck_t;
#endif
@@ -798,7 +807,7 @@ typedef struct lfs {
uint8_t *buffer;
} pcache;
#ifdef LFS_CKPARITY
#if defined(LFS_CKPARITY) || defined(LFS_CKCKSUMS)
lfsr_tailck_t tailck;
#endif
+6
View File
@@ -156,6 +156,12 @@ extern "C"
#define LFS_IFDEF_CKPARITY(a, b) (b)
#endif
#ifdef LFS_CKCKSUMS
#define LFS_IFDEF_CKCKSUMS(a, b) (a)
#else
#define LFS_IFDEF_CKCKSUMS(a, b) (b)
#endif
// Builtin functions, these may be replaced by more efficient
// toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more
+436 -22
View File
@@ -1095,7 +1095,7 @@ code = '''
# will make them more useful.
#
# test every single-bit error in block 0/1
# test some single-bit errors in block 0/1
[cases.test_ck_ckparity_mroot]
defines.BADBLOCK = [0, 1]
defines.BADBIT = -1
@@ -1208,7 +1208,7 @@ code = '''
}
'''
# test every single-bit error in a file's btree node
# test some single-bit errors in a file's btree node
[cases.test_ck_ckparity_btree]
defines.BADBIT = -1
defines.BADBLOCK_BEHAVIOR = [
@@ -1346,6 +1346,386 @@ code = '''
# Some simple ckcksums tests
# test every single-bit error in block 0/1
[cases.test_ck_ckcksums_mroot]
defines.BADBLOCK = [0, 1]
defines.BADBIT = -1
defines.BADBLOCK_BEHAVIOR = [
'LFS_EMUBD_BADBLOCK_PROGFLIP',
'LFS_EMUBD_BADBLOCK_READFLIP',
]
# this should stay inlined
defines.SIZE = 'BLOCK_SIZE/16'
ifdef = 'LFS_CKCKSUMS'
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;
// reset the bd prng every run for reproducibility
lfs_emubd_seed(CFG, 42);
printf("--- badblock: 0x%x.%x, badbit: 0x%x (0x%x+%x) ---\n",
(lfs_size_t)BADBLOCK, badbit/8, badbit, badbit/8, badbit%8);
// mark our badbit as bad
lfs_emubd_markbadbit(CFG, BADBLOCK, badbit) => 0;
// With metastability, basically any filesystem operation can
// return LFS_ERR_CORRUPT. This is ok, what we're really testing
// for is no internal/external asserts failing.
// format
lfs_t lfs;
int err = lfsr_format(&lfs, LFS_M_RDWR | LFS_M_CKCKSUMS, CFG);
assert(!err || err == LFS_ERR_CORRUPT);
if (err == LFS_ERR_CORRUPT) {
goto corrupt;
}
err = lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKCKSUMS, CFG);
assert(!err || err == LFS_ERR_CORRUPT);
if (err == LFS_ERR_CORRUPT) {
goto corrupt;
}
{
// create a file
lfsr_file_t file;
err = lfsr_file_open(&lfs, &file, "bathykorus",
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL);
assert(!err || err == LFS_ERR_CORRUPT);
if (err == LFS_ERR_CORRUPT) {
goto corrupt_mounted;
}
uint32_t prng = 42;
uint8_t wbuf[SIZE];
for (lfs_size_t j = 0; j < SIZE; j++) {
wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26);
}
lfs_ssize_t res = lfsr_file_write(&lfs, &file, wbuf, SIZE);
assert(res == SIZE || res == LFS_ERR_CORRUPT);
if (res == LFS_ERR_CORRUPT) {
lfsr_file_close(&lfs, &file) => 0;
goto corrupt_mounted;
}
err = lfsr_file_close(&lfs, &file);
if (err == LFS_ERR_CORRUPT) {
goto corrupt_mounted;
}
// try to read our file
for (int remount = 0; remount < 2; remount++) {
// remount?
if (remount) {
lfsr_unmount(&lfs) => 0;
err = lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKCKSUMS, CFG);
if (err == LFS_ERR_CORRUPT) {
goto corrupt;
}
}
// yes reads can fail here
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
assert(!err
|| err == LFS_ERR_CORRUPT
// bit errors can also cause our fs state to "rollback",
// which is not great but we can't solve this with ckreads
// alone
|| err == LFS_ERR_NOENT);
if (err == LFS_ERR_CORRUPT || err == LFS_ERR_NOENT) {
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;
corrupt:;
// reset badbit
lfs_emubd_markgood(CFG, BADBLOCK) => 0;
}
'''
# test every single-bit error in a file's data block
[cases.test_ck_ckcksums_data]
defines.BADBIT = -1
defines.BADBLOCK_BEHAVIOR = [
'LFS_EMUBD_BADBLOCK_PROGFLIP',
'LFS_EMUBD_BADBLOCK_READFLIP',
]
# this should create a single block file
defines.SIZE = 'BLOCK_SIZE'
ifdef = 'LFS_CKCKSUMS'
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_CKCKSUMS, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKCKSUMS, CFG) => 0;
// create a file
lfsr_file_t file;
lfsr_file_open(&lfs, &file, "bathykorus",
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;
// reset the bd prng every run for reproducibility
lfs_emubd_seed(CFG, 42);
printf("--- badblock: 0x%x.%x, badbit: 0x%x (0x%x+%x) ---\n",
badblock, badbit/8, badbit, badbit/8, badbit%8);
// mark our badbit as bad
lfs_emubd_markbadbit(CFG, badblock, badbit) => 0;
// With metastability, basically any filesystem operation can
// return LFS_ERR_CORRUPT. This is ok, what we're really testing
// for is no internal/external asserts failing.
// format
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR | LFS_F_CKCKSUMS, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKCKSUMS, CFG) => 0;
{
// create a file
lfsr_file_t file;
lfsr_file_open(&lfs, &file, "bathykorus",
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);
}
lfs_ssize_t res = lfsr_file_write(&lfs, &file, wbuf, SIZE);
assert(res == SIZE || res == LFS_ERR_CORRUPT);
if (res == LFS_ERR_CORRUPT) {
lfsr_file_close(&lfs, &file) => 0;
goto corrupt_mounted;
}
int err = lfsr_file_close(&lfs, &file);
if (err == LFS_ERR_CORRUPT) {
goto corrupt_mounted;
}
// 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_CKCKSUMS, CFG) => 0;
}
// yes reads can fail here
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
assert(!err
|| err == LFS_ERR_CORRUPT
// bit errors can also cause our fs state to "rollback",
// which is not great but we can't solve this with ckreads
// alone
|| err == LFS_ERR_NOENT);
if (err == LFS_ERR_CORRUPT || err == LFS_ERR_NOENT) {
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_ckcksums_btree]
defines.BADBIT = -1
defines.BADBLOCK_BEHAVIOR = [
'LFS_EMUBD_BADBLOCK_PROGFLIP',
'LFS_EMUBD_BADBLOCK_READFLIP',
]
# 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_CKCKSUMS'
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_CKCKSUMS, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKCKSUMS, CFG) => 0;
// create a file
lfsr_file_t file;
lfsr_file_open(&lfs, &file, "bathykorus",
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;
// reset the bd prng every run for reproducibility
lfs_emubd_seed(CFG, 42);
printf("--- badblock: 0x%x.%x, badbit: 0x%x (0x%x+%x) ---\n",
badblock, badbit/8, badbit, badbit/8, badbit%8);
// mark our badbit as bad
lfs_emubd_markbadbit(CFG, badblock, badbit) => 0;
// With metastability, basically any filesystem operation can
// return LFS_ERR_CORRUPT. This is ok, what we're really testing
// for is no internal/external asserts failing.
// format
lfs_t lfs;
lfsr_format(&lfs, LFS_F_RDWR | LFS_F_CKCKSUMS, CFG) => 0;
lfsr_mount(&lfs, LFS_M_RDWR | LFS_M_CKCKSUMS, CFG) => 0;
{
// create a file
lfsr_file_t file;
lfsr_file_open(&lfs, &file, "bathykorus",
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);
}
lfs_ssize_t res = lfsr_file_write(&lfs, &file, wbuf, SIZE);
assert(res == SIZE || res == LFS_ERR_CORRUPT);
if (res == LFS_ERR_CORRUPT) {
lfsr_file_close(&lfs, &file) => 0;
goto corrupt_mounted;
}
int err = lfsr_file_close(&lfs, &file);
if (err == LFS_ERR_CORRUPT) {
goto corrupt_mounted;
}
// 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_CKCKSUMS, CFG) => 0;
}
// yes reads can fail here
err = lfsr_file_open(&lfs, &file, "bathykorus", LFS_O_RDONLY);
assert(!err
|| err == LFS_ERR_CORRUPT
// bit errors can also cause our fs state to "rollback",
// which is not great but we can't solve this with ckreads
// alone
|| err == LFS_ERR_NOENT);
if (err == LFS_ERR_CORRUPT || err == LFS_ERR_NOENT) {
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;
}
'''
## High-level error spam tests
#
@@ -1360,6 +1740,7 @@ code = '''
# METHOD=0 => ckprogs
# METHOD=1 => ckfetches
# METHOD=2 => ckparity
# METHOD=3 => ckcksums
defines.METHOD = [0]
defines.PERIOD = 10
defines.PROTECTED_MROOTANCHOR = [false, true]
@@ -1367,6 +1748,7 @@ defines.BADBLOCK_BEHAVIOR = 'LFS_EMUBD_BADBLOCK_PROGFLIP'
defines.CKPROGS = 'METHOD == 0'
defines.CKFETCHES = 'METHOD == 1'
defines.CKPARITY = 'METHOD == 2'
defines.CKCKSUMS = 'METHOD == 3'
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
defines.SEED = 'range(10)'
fuzz = 'SEED'
@@ -1374,6 +1756,7 @@ if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'LFS_IFDEF_CKCKSUMS(true, !CKCKSUMS)',
]
code = '''
// seed our block device with our seed so we have different error
@@ -1394,13 +1777,15 @@ code = '''
LFS_F_RDWR
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_F_CKCKSUMS, -1) : 0),
CFG) => 0;
lfsr_mount(&lfs,
LFS_M_RDWR
| ((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),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1) : 0),
CFG) => 0;
// set up a simulation to compare against
@@ -1421,8 +1806,8 @@ code = '''
// types of errors, so we implement errors for each one a
// bit differently
// ckprogs? ckparity?
if (METHOD == 0 || METHOD == 2) {
// ckprogs? ckparity? ckcksums?
if (METHOD == 0 || METHOD == 2 || METHOD == 3) {
// mark our badblock as bad
lfs_emubd_markbad(CFG, badblock) => 0;
@@ -1543,6 +1928,9 @@ code = '''
: 0)
| ((CKPARITY)
? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1)
: 0)
| ((CKCKSUMS)
? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1)
: 0),
CFG) => 0;
}
@@ -1601,6 +1989,7 @@ corrupt_mounted:;
# METHOD=0 => ckprogs
# METHOD=1 => ckfetches
# METHOD=2 => ckparity
# METHOD=3 => ckcksums
defines.METHOD = [0]
defines.PERIOD = 10
defines.PROTECTED_MROOTANCHOR = [false, true]
@@ -1608,6 +1997,7 @@ defines.BADBLOCK_BEHAVIOR = 'LFS_EMUBD_BADBLOCK_PROGFLIP'
defines.CKPROGS = 'METHOD == 0'
defines.CKFETCHES = 'METHOD == 1'
defines.CKPARITY = 'METHOD == 2'
defines.CKCKSUMS = 'METHOD == 3'
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [
'0',
@@ -1624,6 +2014,7 @@ if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'LFS_IFDEF_CKCKSUMS(true, !CKCKSUMS)',
'(SIZE*N)/BLOCK_SIZE <= 16',
]
code = '''
@@ -1645,13 +2036,15 @@ code = '''
LFS_F_RDWR
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_F_CKCKSUMS, -1) : 0),
CFG) => 0;
lfsr_mount(&lfs,
LFS_M_RDWR
| ((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),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1) : 0),
CFG) => 0;
// set up a simulation to compare against
@@ -1673,8 +2066,8 @@ code = '''
// types of errors, so we implement errors for each one a
// bit differently
// ckprogs? ckparity?
if (METHOD == 0 || METHOD == 2) {
// ckprogs? ckparity? ckcksums?
if (METHOD == 0 || METHOD == 2 || METHOD == 3) {
// mark our badblock as bad
lfs_emubd_markbad(CFG, badblock) => 0;
@@ -1841,6 +2234,9 @@ code = '''
: 0)
| ((CKPARITY)
? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1)
: 0)
| ((CKCKSUMS)
? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1)
: 0),
CFG) => 0;
}
@@ -1914,6 +2310,7 @@ corrupt_mounted:;
# METHOD=0 => ckprogs
# METHOD=1 => ckfetches
# METHOD=2 => ckparity
# METHOD=3 => ckcksums
defines.METHOD = [0]
defines.PERIOD = 10
defines.PROTECTED_MROOTANCHOR = [false, true]
@@ -1921,6 +2318,7 @@ defines.BADBLOCK_BEHAVIOR = 'LFS_EMUBD_BADBLOCK_PROGFLIP'
defines.CKPROGS = 'METHOD == 0'
defines.CKFETCHES = 'METHOD == 1'
defines.CKPARITY = 'METHOD == 2'
defines.CKCKSUMS = 'METHOD == 3'
defines.SIZE = [
'FILE_BUFFER_SIZE/2',
'2*FILE_BUFFER_SIZE',
@@ -1942,6 +2340,7 @@ if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'LFS_IFDEF_CKCKSUMS(true, !CKCKSUMS)',
'CHUNK <= SIZE',
# this just saves testing time
'SIZE <= 4*1024*FRAGMENT_SIZE',
@@ -1965,13 +2364,15 @@ code = '''
LFS_F_RDWR
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_F_CKCKSUMS, -1) : 0),
CFG) => 0;
lfsr_mount(&lfs,
LFS_M_RDWR
| ((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),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1) : 0),
CFG) => 0;
// create a file
@@ -2015,8 +2416,8 @@ code = '''
// types of errors, so we implement errors for each one a
// bit differently
// ckprogs? ckparity?
if (METHOD == 0 || METHOD == 2) {
// ckprogs? ckparity? ckcksums?
if (METHOD == 0 || METHOD == 2 || METHOD == 3) {
// mark our badblock as bad
lfs_emubd_markbad(CFG, badblock) => 0;
@@ -2083,6 +2484,9 @@ code = '''
: 0)
| ((CKPARITY)
? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1)
: 0)
| ((CKCKSUMS)
? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1)
: 0),
CFG) => 0;
}
@@ -2142,6 +2546,7 @@ defines.BADBLOCK = -1
# METHOD=0 => ckprogs
# METHOD=1 => ckfetches
# METHOD=2 => ckparity
# METHOD=3 => ckcksums
defines.METHOD = [0]
defines.PERIOD = 10
defines.PROTECTED_MROOTANCHOR = [false, true]
@@ -2149,6 +2554,7 @@ defines.BADBLOCK_BEHAVIOR = 'LFS_EMUBD_BADBLOCK_PROGFLIP'
defines.CKPROGS = 'METHOD == 0'
defines.CKFETCHES = 'METHOD == 1'
defines.CKPARITY = 'METHOD == 2'
defines.CKCKSUMS = 'METHOD == 3'
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [
'0',
@@ -2165,6 +2571,7 @@ if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'LFS_IFDEF_CKCKSUMS(true, !CKCKSUMS)',
'(SIZE*N)/BLOCK_SIZE <= 16',
]
code = '''
@@ -2186,13 +2593,15 @@ code = '''
LFS_F_RDWR
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_F_CKCKSUMS, -1) : 0),
CFG) => 0;
lfsr_mount(&lfs,
LFS_M_RDWR
| ((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),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1) : 0),
CFG) => 0;
// set up a simulation to compare against
@@ -2224,8 +2633,8 @@ code = '''
// types of errors, so we implement errors for each one a
// bit differently
// ckprogs? ckparity?
if (METHOD == 0 || METHOD == 2) {
// ckprogs? ckparity? ckcksums?
if (METHOD == 0 || METHOD == 2 || METHOD == 3) {
// mark our badblock as bad
lfs_emubd_markbad(CFG, badblock) => 0;
@@ -2576,6 +2985,7 @@ corrupt_mounted:;
# METHOD=0 => ckprogs
# METHOD=1 => ckfetches
# METHOD=2 => ckparity
# METHOD=3 => ckcksums
defines.METHOD = [0]
defines.PERIOD = 10
defines.PROTECTED_MROOTANCHOR = [false, true]
@@ -2583,6 +2993,7 @@ defines.BADBLOCK_BEHAVIOR = 'LFS_EMUBD_BADBLOCK_PROGFLIP'
defines.CKPROGS = 'METHOD == 0'
defines.CKFETCHES = 'METHOD == 1'
defines.CKPARITY = 'METHOD == 2'
defines.CKCKSUMS = 'METHOD == 3'
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [
'0',
@@ -2599,6 +3010,7 @@ if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'LFS_IFDEF_CKCKSUMS(true, !CKCKSUMS)',
'(SIZE*N)/BLOCK_SIZE <= 16',
]
code = '''
@@ -2620,13 +3032,15 @@ code = '''
LFS_F_RDWR
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_F_CKCKSUMS, -1) : 0),
CFG) => 0;
lfsr_mount(&lfs,
LFS_M_RDWR
| ((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),
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_M_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1) : 0),
CFG) => 0;
// set up a simulation to compare against
@@ -2659,8 +3073,8 @@ code = '''
// types of errors, so we implement errors for each one a
// bit differently
// ckprogs? ckparity?
if (METHOD == 0 || METHOD == 2) {
// ckprogs? ckparity? ckcksums?
if (METHOD == 0 || METHOD == 2 || METHOD == 3) {
// mark our badblock as bad
lfs_emubd_markbad(CFG, badblock) => 0;
+7
View File
@@ -20,6 +20,7 @@ defines.SYNC = [false, true]
defines.CKPROGS = [false, true]
defines.CKFETCHES = [false, true]
defines.CKPARITY = [false, true]
defines.CKCKSUMS = [false, true]
defines.MTREEONLY = [false, true]
defines.MKCONSISTENT = [false, true]
defines.LOOKAHEAD = [false, true]
@@ -30,6 +31,7 @@ if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'LFS_IFDEF_CKCKSUMS(true, !CKCKSUMS)',
'!RDONLY || !MKCONSISTENT',
'!RDONLY || !LOOKAHEAD',
'!RDONLY || !COMPACT',
@@ -46,6 +48,7 @@ code = '''
| ((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)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_M_CKCKSUMS, -1) : 0)
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
| ((MKCONSISTENT) ? LFS_M_MKCONSISTENT : 0)
| ((LOOKAHEAD) ? LFS_M_LOOKAHEAD : 0)
@@ -64,6 +67,7 @@ code = '''
| ((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)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_I_CKCKSUMS, -1) : 0)
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)));
@@ -77,6 +81,7 @@ code = '''
defines.CKPROGS = [false, true]
defines.CKFETCHES = [false, true]
defines.CKPARITY = [false, true]
defines.CKCKSUMS = [false, true]
defines.MTREEONLY = [false, true]
defines.COMPACT = [false, true]
defines.CKMETA = [false, true]
@@ -85,6 +90,7 @@ if = [
'LFS_IFDEF_CKPROGS(true, !CKPROGS)',
'LFS_IFDEF_CKFETCHES(true, !CKFETCHES)',
'LFS_IFDEF_CKPARITY(true, !CKPARITY)',
'LFS_IFDEF_CKCKSUMS(true, !CKCKSUMS)',
'!MTREEONLY || !CKDATA',
]
code = '''
@@ -94,6 +100,7 @@ code = '''
| ((CKPROGS) ? LFS_IFDEF_CKPROGS(LFS_F_CKPROGS, -1) : 0)
| ((CKFETCHES) ? LFS_IFDEF_CKFETCHES(LFS_F_CKFETCHES, -1) : 0)
| ((CKPARITY) ? LFS_IFDEF_CKPARITY(LFS_F_CKPARITY, -1) : 0)
| ((CKCKSUMS) ? LFS_IFDEF_CKCKSUMS(LFS_F_CKCKSUMS, -1) : 0)
| ((MTREEONLY) ? LFS_M_MTREEONLY : 0)
| ((COMPACT) ? LFS_M_COMPACT : 0)
| ((CKMETA) ? LFS_M_CKMETA : 0)