Locked down out-of-order writes, more tests
The main test additions are the test_powerloss tests, intended to be
high-level tests over difficult/weird powerloss environments (such as
out-of-order writes!):
- test_powerloss_dir_many - 2242 pls
- test_powerloss_file_many - 8856 pls
- test_powerloss_file_pl_fuzz - 384508 pls
- test_powerloss_filedir_pl_fuzz - 268339 pls
But there was also a bunch of other test movement in the late-stage/
high-level tests. I'm trying to keep the core of these tests somewhat
consistent so we have a nice template to extend for future testing, in
case we want to test other environmentalish concerns, but not all of
these tests make sense in all of these contexts:
badblocks powerloss relocations exhaustion
dir_many y y y
dir_fuzz y y y
file_many y y y
file_fuzz y y y
fwrite_fuzz y y
orphanzombie_fuzz y y y
orphanzombiedir_fuzz y y y
file_pl_fuzz y y
filedir_pl_fuzz y y
Why not:
- dir/file_many+exhaustion? - Needs to be unbounded
- dir/file_fuzz+powerloss? - Takes O(n^2)
- fwrite_fuzz+powerloss? - Takes O(n^2)
- fwrite_fuzz+relocations? - Doesn't really test anything
- orphanzombie*_fuzz+powerloss? - Powerloss kills zombies
- file*_pl_fuzz+badblocks? - PL + Badblocks currently incompactible
- file*_pl_fuzz+exhaustion? - PL + Badblocks currently incompactible
---
Of course, in order to actually get out-of-order write testing working,
we need to implement out-of-order write syncing.
Fortunately this was a simple exercise in placing lfsr_bd_sync calls
before any mdir commits where we may have unsynced data:
- in lfsr_file_sync, to sync any pending file data
- in lfsr_mdir_commit, to sync any mroot/mtree changes
We also call lfsr_bd_sync _after_ mdir commits in case users expect to
sequence any filesystem-external operations such as network, UI, etc. In
theory this could be optional, but no users have really requested it
yet, so leave that for a potential future improvement:
- in lfsr_mdir_commit
- in lfsr_formatinited (really just because we don't go through
lfsr_mdir_commit)
Note that lfsr_rbyd_commit has been relaxed in the scheme. It only
flushes caches, and does _not_ call lfsr_bd_sync. This is useful for
allowing multiple B-tree nodes to be written out-of-order, also long as
the whole thing is synchronized before any mdir commit.
All of these lfsr_bd_sync calls add a bit of code, but not really an
amount to care about:
code stack
before: 33678 2600
after: 33766 (+0.3%) 2600 (+0.0%)
This commit is contained in:
+15
-23
@@ -1676,7 +1676,7 @@ defines.SIZE = [
|
||||
'4*BLOCK_SIZE',
|
||||
]
|
||||
# chunk is more an upper limit here
|
||||
defines.CHUNK = [32, 8]
|
||||
defines.CHUNK = [64, 16]
|
||||
# INIT=0 => no init
|
||||
# INIT=1 => fill with data
|
||||
# INIT=2 => truncate to size
|
||||
@@ -1736,16 +1736,14 @@ code = '''
|
||||
lfs_off_t off = TEST_PRNG(&prng) % SIZE;
|
||||
// and a random size, up to the chunk size
|
||||
lfs_size_t chunk = lfs_min32(
|
||||
TEST_PRNG(&prng) % CHUNK,
|
||||
(TEST_PRNG(&prng) % (CHUNK+1-1)) + 1,
|
||||
SIZE - off);
|
||||
|
||||
// update sim
|
||||
for (lfs_size_t j = 0; j < chunk; j++) {
|
||||
sim[off+j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||
}
|
||||
if (chunk != 0) {
|
||||
size = lfs_max32(size, off+chunk);
|
||||
}
|
||||
size = lfs_max32(size, off+chunk);
|
||||
|
||||
// update file
|
||||
lfsr_file_seek(&lfs, &file, off, LFS_SEEK_SET) => off;
|
||||
@@ -1828,7 +1826,7 @@ defines.SIZE = [
|
||||
'4*BLOCK_SIZE',
|
||||
]
|
||||
# chunk is more an upper limit here
|
||||
defines.CHUNK = [32, 8]
|
||||
defines.CHUNK = [64, 16]
|
||||
defines.SEED = 'range(10)'
|
||||
fuzz = 'SEED'
|
||||
if = [
|
||||
@@ -1861,7 +1859,7 @@ code = '''
|
||||
lfs_soff_t off = TEST_PRNG(&prng) % SIZE;
|
||||
// and a random size, up to the chunk size
|
||||
lfs_size_t chunk = lfs_min32(
|
||||
TEST_PRNG(&prng) % CHUNK,
|
||||
(TEST_PRNG(&prng) % (CHUNK+1-1)) + 1,
|
||||
SIZE - off);
|
||||
|
||||
// test different seek methods
|
||||
@@ -1907,7 +1905,7 @@ defines.SIZE = [
|
||||
'4*BLOCK_SIZE',
|
||||
]
|
||||
# chunk is more an upper limit here
|
||||
defines.CHUNK = [32, 8]
|
||||
defines.CHUNK = [64, 16]
|
||||
# INIT=0 => no init
|
||||
# INIT=1 => fill with data
|
||||
# INIT=2 => truncate to size
|
||||
@@ -1956,7 +1954,7 @@ code = '''
|
||||
lfs_off_t off = TEST_PRNG(&prng) % SIZE;
|
||||
// and a random size, up to the chunk size
|
||||
lfs_size_t chunk = lfs_min32(
|
||||
TEST_PRNG(&prng) % CHUNK,
|
||||
(TEST_PRNG(&prng) % (CHUNK+1-1)) + 1,
|
||||
SIZE - off);
|
||||
|
||||
// test different seek methods
|
||||
@@ -1975,9 +1973,7 @@ code = '''
|
||||
for (lfs_size_t j = 0; j < chunk; j++) {
|
||||
sim[off+j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||
}
|
||||
if (chunk != 0) {
|
||||
size = lfs_max32(size, off+chunk);
|
||||
}
|
||||
size = lfs_max32(size, off+chunk);
|
||||
|
||||
// update the file
|
||||
lfsr_file_write(&lfs, &file, &sim[off], chunk) => chunk;
|
||||
@@ -2056,7 +2052,7 @@ defines.SIZE = [
|
||||
'4*BLOCK_SIZE',
|
||||
]
|
||||
# chunk is more an upper limit here
|
||||
defines.CHUNK = [32, 8]
|
||||
defines.CHUNK = [64, 16]
|
||||
# INIT=0 => no init
|
||||
# INIT=1 => fill with data
|
||||
# INIT=2 => truncate to size
|
||||
@@ -2105,7 +2101,7 @@ code = '''
|
||||
lfs_off_t off = TEST_PRNG(&prng) % SIZE;
|
||||
// and a random size, up to the chunk size
|
||||
lfs_size_t chunk = lfs_min32(
|
||||
TEST_PRNG(&prng) % CHUNK,
|
||||
(TEST_PRNG(&prng) % (CHUNK+1-1)) + 1,
|
||||
SIZE - off);
|
||||
// and if we are reading or writing
|
||||
uint8_t op = TEST_PRNG(&prng) % 2;
|
||||
@@ -2128,9 +2124,7 @@ code = '''
|
||||
for (lfs_size_t j = 0; j < chunk; j++) {
|
||||
sim[off+j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||
}
|
||||
if (chunk != 0) {
|
||||
size = lfs_max32(size, off+chunk);
|
||||
}
|
||||
size = lfs_max32(size, off+chunk);
|
||||
|
||||
// update the file
|
||||
lfsr_file_write(&lfs, &file, &sim[off], chunk) => chunk;
|
||||
@@ -2336,7 +2330,7 @@ defines.SIZE = [
|
||||
'4*BLOCK_SIZE',
|
||||
]
|
||||
# chunk is more an upper limit here
|
||||
defines.CHUNK = [32, 8]
|
||||
defines.CHUNK = [64, 16]
|
||||
# INIT=0 => no init
|
||||
# INIT=1 => fill with data
|
||||
# INIT=2 => truncate to size
|
||||
@@ -2401,7 +2395,7 @@ code = '''
|
||||
lfs_off_t off = TEST_PRNG(&prng) % SIZE;
|
||||
// and a random size, up to the chunk size
|
||||
lfs_size_t chunk = lfs_min32(
|
||||
TEST_PRNG(&prng) % CHUNK,
|
||||
(TEST_PRNG(&prng) % (CHUNK+1-1)) + 1,
|
||||
SIZE - off);
|
||||
|
||||
// seek
|
||||
@@ -2411,9 +2405,7 @@ code = '''
|
||||
for (lfs_size_t j = 0; j < chunk; j++) {
|
||||
sim[off+j] = 'a' + (TEST_PRNG(&prng) % 26);
|
||||
}
|
||||
if (chunk != 0) {
|
||||
size = lfs_max32(size, off+chunk);
|
||||
}
|
||||
size = lfs_max32(size, off+chunk);
|
||||
|
||||
// update the file
|
||||
lfsr_file_write(&lfs, &file, &sim[off], chunk) => chunk;
|
||||
@@ -2437,7 +2429,7 @@ code = '''
|
||||
lfs_off_t off = TEST_PRNG(&prng) % SIZE;
|
||||
// and a random size, up to the chunk size
|
||||
lfs_size_t chunk = lfs_min32(
|
||||
TEST_PRNG(&prng) % CHUNK,
|
||||
(TEST_PRNG(&prng) % (CHUNK+1-1)) + 1,
|
||||
SIZE - off);
|
||||
|
||||
// seek
|
||||
|
||||
Reference in New Issue
Block a user