Implemented SOMEBITS/MOSTBITS emubd powerloss behavior

These emulate powerloss behavior where only some of the bits being
progged are actually progged if there is a powerloss. This behavior was
the original motivation for our ecksums/fcrcs, so it's good to have this
tested.

As a simplification, these only test the extremes:

- LFS_EMUBD_POWERLOSS_SOMEBITS => one bit progged
- LFS_EMUBD_POWERLOSS_MOSTBITS => all-but-one bit progged

Also they flips bits instead of preserving exact partial prog behavior,
but this is allowed (progs can have any intermediate value), has the
same effect as partial progs, and should encourage failed progs.

This required a number of tweaks in emubd: moved powerloss before prog,
moved mutate after powerloss, etc, but these shouldn't affect other
powerloss behaviors. Handling powerloss after prog was only to avoid
power_cycles=1 being useless, it's not strictly required.

Good news is testing so far suggests our ecksum design is sound.
This commit is contained in:
Christopher Haster
2024-06-06 16:38:26 -05:00
parent e06964269e
commit b4af52bc72
6 changed files with 379 additions and 175 deletions
+9 -2
View File
@@ -46,8 +46,10 @@ typedef enum lfs_emubd_badblock_behavior {
// Mode determining how power-loss behaves during testing. For now this
// only supports a noop behavior, leaving the data on-disk untouched.
typedef enum lfs_emubd_powerloss_behavior {
LFS_EMUBD_POWERLOSS_NOOP = 0, // Progs are atomic
LFS_EMUBD_POWERLOSS_OOO = 1, // Blocks are written out-of-order
LFS_EMUBD_POWERLOSS_NOOP = 0, // Progs are atomic
LFS_EMUBD_POWERLOSS_SOMEBITS = 1, // One bit is progged
LFS_EMUBD_POWERLOSS_MOSTBITS = 2, // All-but-one bit is progged
LFS_EMUBD_POWERLOSS_OOO = 3, // Blocks are written out-of-order
} lfs_emubd_powerloss_behavior_t;
// Type for measuring read/program/erase operations
@@ -94,6 +96,10 @@ struct lfs_emubd_config {
// Data for power-loss callback
void *powerloss_data;
// Seed for prng, which may be used for emulating failed progs. This does
// not affect normal operation.
uint32_t seed;
// Path to file to use as a mirror of the disk. This provides a way to view
// the current state of the block device.
const char *disk_path;
@@ -135,6 +141,7 @@ typedef struct lfs_emubd {
lfs_emubd_io_t readed;
lfs_emubd_io_t proged;
lfs_emubd_io_t erased;
uint32_t prng;
lfs_emubd_powercycles_t power_cycles;
lfs_emubd_block_t **ooo_before;
lfs_emubd_block_t **ooo_after;