forked from Imagelibrary/littlefs
Flipped btree encoding to allow variable redund blocks
This should have been done as a part of the earlier tag reencoding work,
since having the block at the end was what allowed us to move the
redund-count out of the tag encoding.
New encoding:
[-- 32-bit csum --]
[-- leb128 weight --]
[-- leb128 trunk --]
[-- leb128 block --]
Note that since our tags have an explicit size, we can store a variable
number of blocks. The plan is to use this to eventually store redundant
copies for error correction:
[-- 32-bit csum --]
[-- leb128 weight --]
[-- leb128 trunk --]
[-- leb128 block --] -.
[-- leb128 block --] +- n redundant blocks
[-- leb128 block --] |
... -'
This does have a significant tradeoff, we need to know the checksum size
to access the btree structure. This doesn't seem like a big deal, but
with the possibility of different checksum types may be an annoying
issue.
Note that FCRC was also flipped for consistency.
This commit is contained in:
42
lfs.c
42
lfs.c
@@ -1338,8 +1338,8 @@ typedef struct lfsr_attr {
|
||||
|
||||
// fcrc on-disk encoding
|
||||
typedef struct lfsr_fcrc {
|
||||
lfs_size_t size;
|
||||
uint32_t crc;
|
||||
lfs_size_t size;
|
||||
} lfsr_fcrc_t;
|
||||
|
||||
// 1 leb128 + 1 crc32c => 9 bytes (worst case)
|
||||
@@ -1349,28 +1349,29 @@ static lfs_ssize_t lfsr_fcrc_todisk(lfs_t *lfs, const lfsr_fcrc_t *fcrc,
|
||||
uint8_t buffer[static LFSR_FCRC_DSIZE]) {
|
||||
(void)lfs;
|
||||
lfs_ssize_t d = 0;
|
||||
lfs_ssize_t d_ = lfs_toleb128(fcrc->size, &buffer[0], 5);
|
||||
|
||||
lfs_tole32_(fcrc->crc, &buffer[d]);
|
||||
d += 4;
|
||||
|
||||
lfs_ssize_t d_ = lfs_toleb128(fcrc->size, &buffer[d], 5);
|
||||
if (d_ < 0) {
|
||||
return d_;
|
||||
}
|
||||
d += d_;
|
||||
|
||||
lfs_tole32_(fcrc->crc, &buffer[d]);
|
||||
d += 4;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static lfs_ssize_t lfsr_fcrc_fromdisk(lfs_t *lfs, lfsr_fcrc_t *fcrc,
|
||||
lfsr_data_t data) {
|
||||
lfs_ssize_t d = 0;
|
||||
lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &fcrc->size);
|
||||
lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &fcrc->crc);
|
||||
if (d_ < 0) {
|
||||
return d_;
|
||||
}
|
||||
d += d_;
|
||||
|
||||
d_ = lfsr_data_readle32(lfs, data, d, &fcrc->crc);
|
||||
d_ = lfsr_data_readleb128(lfs, data, d, &fcrc->size);
|
||||
if (d_ < 0) {
|
||||
return d_;
|
||||
}
|
||||
@@ -2650,7 +2651,7 @@ static int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
|
||||
// find the expected fcrc, don't bother avoiding a reread of the
|
||||
// perturb byte, as it should still be in our cache
|
||||
lfsr_fcrc_t fcrc = {.size=lfs->cfg->prog_size, .crc=0};
|
||||
lfsr_fcrc_t fcrc = {.crc=0, .size=lfs->cfg->prog_size};
|
||||
err = lfsr_bd_csum(lfs, rbyd_.block, aligned, lfs->cfg->prog_size,
|
||||
lfs->cfg->prog_size,
|
||||
&fcrc.crc);
|
||||
@@ -3042,13 +3043,17 @@ static inline lfs_size_t lfsr_btree_setinlined(lfs_size_t weight) {
|
||||
|
||||
// branch on-disk encoding
|
||||
|
||||
// 3 leb128 + 1 crc32c => 19 bytes (worst case)
|
||||
#define LFSR_BRANCH_DSIZE (5+5+5+4)
|
||||
// 1 crc32c + 3 leb128 => 19 bytes (worst case)
|
||||
#define LFSR_BRANCH_DSIZE (4+5+5+5)
|
||||
|
||||
static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch,
|
||||
uint8_t buffer[static LFSR_BRANCH_DSIZE]) {
|
||||
(void)lfs;
|
||||
lfs_ssize_t d = 0;
|
||||
|
||||
lfs_tole32_(branch->crc, &buffer[d]);
|
||||
d += 4;
|
||||
|
||||
lfs_ssize_t d_ = lfs_toleb128(branch->weight, &buffer[d], 5);
|
||||
if (d_ < 0) {
|
||||
return d_;
|
||||
@@ -3067,9 +3072,6 @@ static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch,
|
||||
}
|
||||
d += d_;
|
||||
|
||||
lfs_tole32_(branch->crc, &buffer[d]);
|
||||
d += 4;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -3080,7 +3082,13 @@ static lfs_ssize_t lfsr_branch_fromdisk(lfs_t *lfs, lfsr_rbyd_t *branch,
|
||||
branch->off = 0;
|
||||
|
||||
lfs_ssize_t d = 0;
|
||||
lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &branch->weight);
|
||||
lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &branch->crc);
|
||||
if (d_ < 0) {
|
||||
return d_;
|
||||
}
|
||||
d += d_;
|
||||
|
||||
d_ = lfsr_data_readleb128(lfs, data, d, &branch->weight);
|
||||
if (d_ < 0) {
|
||||
return d_;
|
||||
}
|
||||
@@ -3098,12 +3106,6 @@ static lfs_ssize_t lfsr_branch_fromdisk(lfs_t *lfs, lfsr_rbyd_t *branch,
|
||||
}
|
||||
d += d_;
|
||||
|
||||
d_ = lfsr_data_readle32(lfs, data, d, &branch->crc);
|
||||
if (d_ < 0) {
|
||||
return d_;
|
||||
}
|
||||
d += d_;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,10 +93,10 @@ def fromtag(data):
|
||||
return tag>>15, tag&0x7fff, weight, size, 2+d+d_
|
||||
|
||||
def frombtree(data):
|
||||
w, d1 = fromleb128(data)
|
||||
trunk, d2 = fromleb128(data[d1:])
|
||||
block, d3 = fromleb128(data[d1+d2:])
|
||||
crc = fromle32(data[d1+d2+d3:])
|
||||
crc = fromle32(data)
|
||||
w, d1 = fromleb128(data[4:])
|
||||
trunk, d2 = fromleb128(data[4+d1:])
|
||||
block, d3 = fromleb128(data[4+d1+d2:])
|
||||
return w, trunk, block, crc
|
||||
|
||||
def popc(x):
|
||||
|
||||
@@ -102,10 +102,10 @@ def frommdir(data):
|
||||
return blocks
|
||||
|
||||
def frombtree(data):
|
||||
w, d1 = fromleb128(data)
|
||||
trunk, d2 = fromleb128(data[d1:])
|
||||
block, d3 = fromleb128(data[d1+d2:])
|
||||
crc = fromle32(data[d1+d2+d3:])
|
||||
crc = fromle32(data)
|
||||
w, d1 = fromleb128(data[4:])
|
||||
trunk, d2 = fromleb128(data[4+d1:])
|
||||
block, d3 = fromleb128(data[4+d1+d2:])
|
||||
return w, trunk, block, crc
|
||||
|
||||
def popc(x):
|
||||
|
||||
Reference in New Issue
Block a user