Added bptr checksums
Looking forward, bptr checksums provide an easy mechanism to validate
data residing in blocks. This extends the merkle-tree-like nature of the
filesystem all the way down to the data level, and is common in other
COW filesystems.
Two interesting things to note:
1. We don't actually check data-level checksums yet, but we do calculate
data-level checksums unconditionally.
Writing checksums is easy, but validating checksums is a bit more
tricky. This is made a bit harder for littlefs, since we can't hold
an entire block of data in RAM, so we have to choose between separate
bus transactions for checksum + data reads, or extremely expensive
overreads every read.
Note this already exists at the metadata-level, the separate bus
transactions for rbyd fetch + rbyd lookup means we _are_ susceptible
to a very small window where bit errors can get through.
But anyways, writing checksums is easy. And has basically no cost
since we are already processing the data for our write. So we might
as well write the data-level checksums at all times, even if we
aren't validating at the data-level.
2. To make bptr checksums work cheaply we need an additional cksize
field to indicate how much data is checksummed.
This field seems redundant when we already have the bptr's data size,
but if we didn't have this field, we would be forced to recalculate
the checksum every time a block is sliced. This would be
unreasonable.
The immutable cksize field does mean we may be checksumming more data
than we need to when validating, but we should be avoiding small
block slices anyways for storage cost reasons.
This does add some stack cost because our bptr struct is larger now:
code stack
before: 31200 2768
after: 31272 (+0.2%) 2800 (+1.1%)
This commit is contained in:
@@ -372,14 +372,6 @@ typedef struct lfsr_rbyd {
|
||||
uint32_t cksum;
|
||||
} lfsr_rbyd_t;
|
||||
|
||||
typedef struct lfsr_bptr {
|
||||
// note size lines up with weight in lfsr_btree_t
|
||||
lfs_off_t size;
|
||||
lfs_block_t block;
|
||||
lfs_size_t off;
|
||||
// TODO how do we track ecksum?
|
||||
} lfsr_bptr_t;
|
||||
|
||||
typedef lfsr_rbyd_t lfsr_btree_t;
|
||||
|
||||
typedef struct lfsr_mptr {
|
||||
@@ -513,6 +505,14 @@ typedef struct lfsr_bsprout {
|
||||
lfsr_data_t data_;
|
||||
} lfsr_bsprout_t;
|
||||
|
||||
typedef struct lfsr_bptr {
|
||||
// note data.size lines up with weight in lfsr_btree_t
|
||||
lfsr_data_t data;
|
||||
lfs_size_t cksize;
|
||||
uint32_t cksum;
|
||||
// TODO how do we track ecksum?
|
||||
} lfsr_bptr_t;
|
||||
|
||||
// bshrubs must always be associated with an mdir
|
||||
//
|
||||
// rbyd.block == mdir.blocks[0] => bshrub
|
||||
@@ -529,6 +529,7 @@ typedef struct lfsr_bshrub {
|
||||
typedef struct lfsr_ftree {
|
||||
union {
|
||||
lfs_soff_t size;
|
||||
lfsr_data_t data;
|
||||
lfsr_bsprout_t bsprout;
|
||||
lfsr_bptr_t bptr;
|
||||
lfsr_bshrub_t bshrub;
|
||||
|
||||
Reference in New Issue
Block a user