From b122a50b6cf150e83c2f668d18b9bf1b41711a37 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 1 May 2024 13:49:00 -0500 Subject: [PATCH] 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... --- lfs.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lfs.c b/lfs.c index 71c3f219..5375da1f 100644 --- a/lfs.c +++ b/lfs.c @@ -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,