Implemented unerased-propagation in commit functions

This is a tricky nuance of how rbyd's erased state interacts with
possible errors during commits.

- If an rbyd passes its ecksum during rbyd-fetch, it's erased and we can
  write to it.

- If an rbyd is committed to successfully and still has erased space
  remaining, it's erased and we can write to it.

- But if we fail to commit to the rbyd, we can't be sure the trailing
  data is still erased. It most likely isn't, and we would need to fetch
  again to check the ecksum. And since errors are exceptional here, we
  might as well just mark any failed commits as unerased, triggering a
  compaction on the next write to the rbyd.

To make things more annoying, changing state in all error routes is
tricky to get right, and trickier to test. To keep this relatively
simple and robust, all rbyd/btree/mdir operations mark the original copy
as unerased until the commit succeeds, and then clears the unerased
state. This fits in well with how we make copies of the rbyd/btree/mdir
structs in the relevant functions.

Note this needs to affect _all_ copies of the rbyd, including any opened
mdirs, mroots, etc. This will probably still lead to some bugs in the
future...
This commit is contained in:
Christopher Haster
2023-09-09 22:01:10 -05:00
parent 2b98d62637
commit cced7d66ef
2 changed files with 197 additions and 149 deletions
+1 -2
View File
@@ -377,13 +377,12 @@ typedef struct lfsr_mdir {
struct {
lfs_size_t weight;
lfs_off_t trunk;
lfs_off_t off;
lfs_off_t eoff;
uint32_t cksum;
lfs_block_t blocks[2];
} m;
struct {
lfsr_rbyd_t rbyd;
lfs_block_t redund_block;
} r;
} u;
} lfsr_mdir_t;