Upped attribute size to the full 32-bits

This increases the leb128 size from 4 bytes to 5 bytes for very little
gain, but 1 byte of RAM is not worth sweating over and this means fewer
surprises for a "32-bit" littlefs implementation.

If that 1 byte is worth saving, this should be configurable in the
future.
This commit is contained in:
Christopher Haster
2023-02-02 12:31:44 -06:00
parent 86bafaee27
commit 9b414e448c
+34 -30
View File
@@ -831,14 +831,14 @@ struct lfsr_fcrc {
lfs_size_t size;
};
#define LFSR_FCRC_DSIZE 8
#define LFSR_FCRC_DSIZE (4+5)
static lfs_ssize_t lfsr_fcrc_todisk(
const struct lfsr_fcrc *fcrc,
uint8_t buf[static LFSR_FCRC_DSIZE]) {
lfs_tole32_(fcrc->crc, &buf[0]);
lfs_ssize_t delta = lfs_toleb128(fcrc->size, &buf[4], 4);
lfs_ssize_t delta = lfs_toleb128(fcrc->size, &buf[4], 5);
if (delta < 0) {
return delta;
}
@@ -851,7 +851,7 @@ static lfs_ssize_t lfsr_fcrc_fromdisk(
const uint8_t buf[static LFSR_FCRC_DSIZE]) {
fcrc->crc = lfs_fromle32_(&buf[0]);
lfs_ssize_t delta = lfs_fromleb128(&fcrc->size, &buf[4], 4);
lfs_ssize_t delta = lfs_fromleb128(&fcrc->size, &buf[4], 5);
if (delta < 0) {
return delta;
}
@@ -1110,10 +1110,10 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
//
// - 14-bit type => 2 byte leb128 (worst case)
// - 32-bit id/weight => 5 byte leb128 (worst case)
// - 28-bit size/jump => 4 byte leb128 (worst case)
// => 11 bytes total
// - 32-bit size/jump => 5 byte leb128 (worst case)
// => 12 bytes total
//
#define LFSR_TAG_DSIZE (2+5+4)
#define LFSR_TAG_DSIZE (2+5+5)
// TODO actually should this be an lfs_bd_ operation?
static lfs_ssize_t lfsr_rbyd_readtag(lfs_t *lfs,
@@ -1130,7 +1130,7 @@ static lfs_ssize_t lfsr_rbyd_readtag(lfs_t *lfs,
uint8_t buffer[LFSR_TAG_DSIZE] = {
0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff,
};
// TODO allow different hint for lookup? bench this? does our hint work backwards?
@@ -1172,7 +1172,7 @@ static lfs_ssize_t lfsr_rbyd_readtag(lfs_t *lfs,
delta += delta_;
lfs_size_t size_;
delta_ = lfs_fromleb128(&size_, &buffer[delta], 4);
delta_ = lfs_fromleb128(&size_, &buffer[delta], 5);
if (delta_ < 0) {
return delta_;
}
@@ -1662,7 +1662,7 @@ static int lfsr_rbyd_progtag(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
}
delta += delta_;
delta_ = lfs_toleb128(size, &buf[delta], 4);
delta_ = lfs_toleb128(size, &buf[delta], 5);
if (delta_ < 0) {
return delta_;
}
@@ -2243,31 +2243,24 @@ int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// - fcrc tag id => 1 byte leb128
// - fcrc tag size => 1 byte leb128 (worst case)
// - fcrc crc => 4 byte le32
// - fcrc size => 4 byte leb128 (worst case)
// - fcrc size => 5 byte leb128 (worst case)
// - crc tag type => 1 byte leb128
// - crc tag id => 1 byte leb128
// - crc tag size => 4 byte leb128 (worst case)
// - crc tag size => 5 byte leb128 (worst case)
// - crc crc => 4 byte le32
// => 21 bytes total
// => 23 bytes total
//
// - 4-word crc with no following prog (end of block)
// - crc tag type => 1 byte leb128
// - crc tag id => 1 byte leb128
// - crc tag size => 4 byte leb128 (worst case)
// - crc tag size => 5 byte leb128 (worst case)
// - crc crc => 4 byte le32
// => 10 bytes total
// => 11 bytes total
//
const lfs_off_t aligned = lfs_alignup(
rbyd_.off + 1+1+1+4+4 + 1+1+4+4,
lfs_off_t aligned = lfs_alignup(
rbyd_.off + 1+1+1+4+5 + 1+1+5+4,
lfs->cfg->prog_size);
// TODO we can accept a tighter limit here if we recalculate aligned
// after failing to include an fcrc
// not even space for the crc?
if (aligned > lfs->cfg->block_size) {
return LFS_ERR_RANGE;
}
// space for fcrc?
uint8_t perturb = 0;
if (aligned <= lfs->cfg->block_size - lfs->cfg->prog_size) {
@@ -2305,6 +2298,16 @@ int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd,
}
rbyd_.erased = true;
} else {
// recalculate aligned without fcrc
aligned = lfs_alignup(
rbyd_.off + 1+1+5+4,
lfs->cfg->prog_size);
}
// not even space for the crc?
if (aligned > lfs->cfg->block_size) {
return LFS_ERR_RANGE;
}
// build end-of-commit crc
@@ -2312,28 +2315,29 @@ int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// note padding-size depends on leb-encoding depends on padding-size, to
// get around this catch-22 we just always write a fully-expanded leb128
// encoding
uint8_t buffer[1+1+4+4];
uint8_t buffer[1+1+5+4];
buffer[0] = LFSR_TAG_CRC | (lfs_popc(rbyd_.crc) & 1);
buffer[1] = 0;
lfs_off_t padding = aligned - (rbyd_.off + 1+1+4);
lfs_off_t padding = aligned - (rbyd_.off + 1+1+5);
buffer[2] = 0x80 | (0x7f & (padding >> 0));
buffer[3] = 0x80 | (0x7f & (padding >> 7));
buffer[4] = 0x80 | (0x7f & (padding >> 14));
buffer[5] = 0x00 | (0x7f & (padding >> 21));
buffer[5] = 0x80 | (0x7f & (padding >> 21));
buffer[6] = 0x00 | (0x7f & (padding >> 28));
rbyd_.crc = lfs_crc32c(rbyd_.crc, buffer, 1+1+4);
rbyd_.crc = lfs_crc32c(rbyd_.crc, buffer, 1+1+5);
// we can't let the next tag appear as valid, so intentionally perturb the
// commit if this happens, note parity(crc(m)) == parity(m) with crc32c,
// so we can really change any bit to make this happen, we've reserved a bit
// in crc tags just for this purpose
if ((lfs_popc(rbyd_.crc) & 1) == (perturb & 1)) {
buffer[0] ^= 0x10;
rbyd_.crc ^= 0xc00c303e; // note crc(a ^ b) == crc(a) ^ crc(b)
rbyd_.crc ^= 0x9c5bfaa6; // note crc(a ^ b) == crc(a) ^ crc(b)
}
lfs_tole32_(rbyd_.crc, &buffer[1+1+4]);
lfs_tole32_(rbyd_.crc, &buffer[1+1+5]);
int err = lfsr_rbyd_prog(lfs, &rbyd_, buffer, 1+1+4+4, NULL);
int err = lfsr_rbyd_prog(lfs, &rbyd_, buffer, 1+1+5+4, NULL);
if (err) {
return err;
}