Trying to handle ecksums correctly when erased=>LFS_ERR_CORRUPT

It should be legal for block devices to return LFS_ERR_CORRUPT when
erased, this is common on devices with ECC, where the erased-state is
not valid ECC and results in LFS_ERR_CORRUPT.

If anything this is a better indicator than fixed-value erased-state,
but we need to make sure we track this with our ecksums consistently.
This gets a bit arbitrary.

Normally:

  valid = m[0] & 0x80
  cksum = crc32c(m)

If bd_read returns LFS_ERR_CORRUPT:

  valid = 0 & 0x80
  cksum = crc32c([])

Yeah, implementing this gets a bit funky, but the code cost is trivial:

           code          stack
  before: 33924           2824
  after:  33928 (+0.0%)   2824 (+0.0%)

Note this is only best effort right now, we really need tests over
erased=>LFS_ERR_CORRUPT...
This commit is contained in:
Christopher Haster
2024-05-01 13:49:00 -05:00
parent db85172211
commit b122a50b6c
+8 -3
View File
@@ -2384,7 +2384,6 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
if (lfsr_rbyd_eoff(rbyd) < lfs->cfg->block_size
&& lfsr_rbyd_eoff(rbyd) % lfs->cfg->prog_size == 0
&& ecksum.cksize != -1) {
// TODO is this correct for erased=corrupt?
uint8_t e = 0;
err = lfsr_bd_read(lfs,
rbyd->blocks[0], lfsr_rbyd_eoff(rbyd), ecksum.cksize,
@@ -2397,7 +2396,10 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
if ((e >> 7) != lfsr_rbyd_parity(rbyd)) {
// check that erased-state matches our checksum, if this fails
// most likely a write was interrupted
uint32_t ecksum_ = lfs_crc32c(0, &e, 1);
uint32_t ecksum_ = 0;
if (err != LFS_ERR_CORRUPT) {
ecksum_ = lfs_crc32c(0, &e, 1);
}
int err = lfsr_bd_cksum(lfs,
rbyd->blocks[0], lfsr_rbyd_eoff(rbyd)+1, 0,
ecksum.cksize-1,
@@ -3458,7 +3460,10 @@ static int lfsr_rbyd_appendcksum(lfs_t *lfs, lfsr_rbyd_t *rbyd) {
// calculate the erased-state checksum
lfsr_ecksum_t ecksum;
ecksum.cksize = lfs->cfg->prog_size;
ecksum.cksum = lfs_crc32c(0, &e, 1);
ecksum.cksum = 0;
if (err != LFS_ERR_CORRUPT) {
ecksum.cksum = lfs_crc32c(0, &e, 1);
}
err = lfsr_bd_cksum(lfs,
rbyd->blocks[0], off_+1, ecksum.cksize-1,
ecksum.cksize-1,