From 799e7cfc81e84a241bedd0ac812c6672bbd2e9e5 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 19 Jun 2023 13:17:52 -0500 Subject: [PATCH] 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. --- lfs.c | 42 ++++++++++++++++++++++-------------------- scripts/dbgbtree.py | 8 ++++---- scripts/dbgmtree.py | 8 ++++---- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/lfs.c b/lfs.c index 4d698d0b..19f0f9e6 100644 --- a/lfs.c +++ b/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; } diff --git a/scripts/dbgbtree.py b/scripts/dbgbtree.py index 501ae442..7eb54708 100755 --- a/scripts/dbgbtree.py +++ b/scripts/dbgbtree.py @@ -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): diff --git a/scripts/dbgmtree.py b/scripts/dbgmtree.py index a2f90b9e..9715c627 100755 --- a/scripts/dbgmtree.py +++ b/scripts/dbgmtree.py @@ -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):