From 5504936b1054d278960fe99b5d6c0b4bd2925306 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 14 Sep 2023 15:02:55 -0500 Subject: [PATCH] Added mlimit to the superconfig, dropped mtreelimit This should be stored in the superconfig, and we should use it during mount instead of rederiving it from the block_size (TODO). Note that this stores the "mlimit", (1 << mbits)-1, not the mbits directly. littlefs will probably always be limited to powers-of-two for this, since mbits is fairly arbitrary, but storing the expanded value allows for non-powers-of-two _just in case_. --- lfs.c | 43 ++++++++++++++++++++-------------------- scripts/dbglfs.py | 48 ++++++++++++++++++++++++++------------------- scripts/dbgmtree.py | 31 +++++++++++++++++------------ 3 files changed, 68 insertions(+), 54 deletions(-) diff --git a/lfs.c b/lfs.c index 5229c862..69757ec8 100644 --- a/lfs.c +++ b/lfs.c @@ -6235,15 +6235,16 @@ static lfsr_data_t lfsr_data_fromsuperconfig(lfs_t *lfs, LFS_ASSERT(d_ >= 0); d += d_; + // on-disk mlimit + lfsr_mid_t mlimit = lfsr_mweight(lfs)-1; + d_ = lfs_toleb128(mlimit, &buffer[d], 5); + LFS_ASSERT(d_ >= 0); + d += d_; + // on-disk utag limit buffer[d] = 0x7f; d += 1; - // on-disk mtree limit - d_ = lfs_toleb128(0x7fffffff, &buffer[d], 5); - LFS_ASSERT(d_ >= 0); - d += d_; - // on-disk attr limit d_ = lfs_toleb128(0x7fffffff, &buffer[d], 5); LFS_ASSERT(d_ >= 0); @@ -6432,6 +6433,21 @@ static int lfsr_mountinited(lfs_t *lfs) { return LFS_ERR_INVAL; } + // check the on-disk mtree limit + // TODO actually use this + lfsr_mid_t mlimit; + err = lfsr_data_readleb128(lfs, &data, (int32_t*)&mlimit); + // treat any leb128 overflows as out-of-range values + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + + if (err == LFS_ERR_CORRUPT || mlimit != lfsr_mweight(lfs)-1) { + LFS_ERROR("Incompatible mlimit 0x%"PRIx32, + (err ? (lfsr_mid_t)-1 : mlimit)); + return LFS_ERR_INVAL; + } + // check the on-disk utag limit // TODO actually use this int32_t utag_limit; @@ -6449,23 +6465,6 @@ static int lfsr_mountinited(lfs_t *lfs) { return LFS_ERR_INVAL; } - // check the on-disk mtree limit - // TODO actually use this - lfsr_smid_t mtree_limit; - err = lfsr_data_readleb128(lfs, &data, &mtree_limit); - // treat any leb128 overflows as out-of-range values - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - - if (err == LFS_ERR_CORRUPT || mtree_limit != 0x7fffffff) { - LFS_ERROR("Incompatible mdir limit 0x%"PRIx32 - " (> 0x%"PRIx32")", - (err ? -1 : mtree_limit), - 0x7fffffff); - return LFS_ERR_INVAL; - } - // check the on-disk attr limit // TODO actually use this lfs_ssize_t attr_limit; diff --git a/scripts/dbglfs.py b/scripts/dbglfs.py index 45224566..f9c94a8c 100755 --- a/scripts/dbglfs.py +++ b/scripts/dbglfs.py @@ -645,6 +645,7 @@ def superconfig(mroot): next('flags') next('block_size') next('block_count') + next('mlimit') next('utag_limit') next('attr_limit') next('name_limit') @@ -653,10 +654,10 @@ def superconfig(mroot): # collect gstate class GState: - def __init__(self, mbits): + def __init__(self, mweight): self.gstate = {} self.gdelta = {} - self.mbits = mbits + self.mweight = mweight def xor(self, mbid, mw, mdir): tag = TAG_GSTATE-0x1 @@ -690,11 +691,11 @@ class GState: for _ in range(count): mid, d_ = fromleb128(data[d:]); d += d_ rms.append(( - mid & ~((1 << self.mbits)-1), - mid & ((1 << self.mbits)-1))) + mid - (mid % self.mweight), + mid % self.mweight)) return rms -def grepr(tag, data, mbits): +def grepr(tag, data, mweight): if tag == TAG_GRM: d = 0 count, d_ = fromleb128(data[d:]); d += d_ @@ -703,11 +704,11 @@ def grepr(tag, data, mbits): for _ in range(count): mid, d_ = fromleb128(data[d:]); d += d_ rms.append(( - mid & ~((1 << mbits)-1), - mid & ((1 << mbits)-1))) + mid - (mid % self.mweight), + mid % self.mweight)) return 'grm %s' % ( 'none' if count == 0 - else ' '.join('%d.%d' % (mbid >> mbits, rid) + else ' '.join('%d.%d' % (mbid//mweight, rid) for mbid, rid in rms) if count <= 2 else '0x%x' % count) @@ -737,6 +738,7 @@ def frepr(mdir, rid, tag): def main(disk, mroots=None, *, block_size=None, + mweight=None, color='auto', **args): # figure out what color should be @@ -759,9 +761,10 @@ def main(disk, mroots=None, *, f.seek(0, os.SEEK_END) block_size = f.tell() - # determine the number of mbits from the block_size, this is just - # for printing purposes - mbits = m.ceil(m.log2(block_size // 16)) + # determine the mweight from the block_size, this is just for + # printing purposes + if mweight is None: + mweight = 1 << m.ceil(m.log2(block_size // 16)) # before we print, we need to do a pass for a few things: # - find the actual mroot @@ -770,10 +773,10 @@ def main(disk, mroots=None, *, # - collect superconfig # - collect gstate # - any missing or orphaned bookmark entries - mweight = 0 + bweight = 0 rweight = 0 corrupted = False - gstate = GState(mbits) + gstate = GState(mweight) config = {} dir_dids = [(0, b'', -1, 0, None, -1, TAG_DID, 0)] bookmark_dids = [] @@ -844,7 +847,7 @@ def main(disk, mroots=None, *, block, trunk, w, cksum = frombtree(data) mtree = Rbyd.fetch(f, block_size, block, trunk) - mweight = w + bweight = w # traverse entries mbid = -1 @@ -941,10 +944,10 @@ def main(disk, mroots=None, *, print('littlefs v%s.%s %s, rev %d, weight %d.%d' % ( config.get('major_version', ('?',))[0], config.get('minor_version', ('?',))[0], - mroot.addr(), mroot.rev, mweight >> mbits, 1 << mbits)) + mroot.addr(), mroot.rev, bweight//mweight, 1*mweight)) # print header - w_width = (m.ceil(m.log10(max(1, mweight >> mbits)+1)) + w_width = (m.ceil(m.log10(max(1, bweight//mweight)+1)) + 2*m.ceil(m.log10(max(1, rweight)+1)) + 2) if dtree: @@ -999,7 +1002,7 @@ def main(disk, mroots=None, *, print('%12s %-*s %s' % ( 'gstate:' if i == 0 else '', w_width + 23, - grepr(tag, data, mbits), + grepr(tag, data, mweight), next(xxd(data, 8), '') if not args.get('no_truncate') else '')) @@ -1034,7 +1037,7 @@ def main(disk, mroots=None, *, ','.join('%04x' % block for block in it.chain([mdir.block], mdir.redund_blocks)), - w_width, mbid >> mbits, + w_width, mbid//mweight, tagrepr(tag, 0, len(data)), next(xxd(data, 8), '') if not args.get('no_truncate') else '', @@ -1137,8 +1140,8 @@ def main(disk, mroots=None, *, mdir.redund_blocks)) if mbid != pmbid else '', w_width, '%d.%d-%d' % ( - mbid >> mbits, rid-(w-1), rid) - if w > 1 else '%d.%d' % (mbid >> mbits, rid) + mbid//mweight, rid-(w-1), rid) + if w > 1 else '%d.%d' % (mbid//mweight, rid) if w > 0 else '', f_width, '%s%s' % ( prefixes[0+(i==len(dir)-1)], @@ -1239,6 +1242,11 @@ if __name__ == "__main__": '-B', '--block-size', type=lambda x: int(x, 0), help="Block size in bytes.") + parser.add_argument( + '-M', '--mweight', + type=lambda x: int(x, 0), + help="Weight of mtree leaves for mid decoding. Defaults to a " + "block_size derived value.") parser.add_argument( '--color', choices=['never', 'always', 'auto'], diff --git a/scripts/dbgmtree.py b/scripts/dbgmtree.py index af8c4a85..e8f839d3 100755 --- a/scripts/dbgmtree.py +++ b/scripts/dbgmtree.py @@ -739,6 +739,7 @@ class Rbyd: def main(disk, mroots=None, *, block_size=None, + mweight=None, color='auto', **args): # figure out what color should be @@ -761,14 +762,15 @@ def main(disk, mroots=None, *, f.seek(0, os.SEEK_END) block_size = f.tell() - # determine the number of mbits from the block_size, this is just - # for printing purposes - mbits = m.ceil(m.log2(block_size // 16)) + # determine the mweight from the block_size, this is just for + # printing purposes + if mweight is None: + mweight = 1 << m.ceil(m.log2(block_size // 16)) # before we print, we need to do a pass for a few things: # - find the actual mroot # - find the total weight - mweight = 0 + bweight = 0 rweight = 0 mroot = Rbyd.fetch(f, block_size, mroots) @@ -813,7 +815,7 @@ def main(disk, mroots=None, *, block, trunk, w, cksum = frombtree(data) mtree = Rbyd.fetch(f, block_size, block, trunk) - mweight = w + bweight = w # traverse entries mbid = -1 @@ -1307,8 +1309,8 @@ def main(disk, mroots=None, *, if args.get('tree') or args.get('btree') else '', '%*s %-22s%s' % ( w_width, '%d.%d-%d' % ( - mbid >> mbits, rid-(w-1), rid) - if w > 1 else '%d.%d' % (mbid >> mbits, rid) + mbid//mweight, rid-(w-1), rid) + if w > 1 else '%d.%d' % (mbid//mweight, rid) if w > 0 or i == 0 else '', tagrepr(tag, w, len(data), j), ' %s' % next(xxd(data, 8), '') @@ -1364,9 +1366,9 @@ def main(disk, mroots=None, *, treerepr(bid, w, bd, rid, 0, tag) if args.get('tree') or args.get('btree') else '', w_width, '' if i != 0 - else '%d-%d' % ((bid-(w-1)) >> mbits, bid >> mbits) - if (w >> mbits) > 1 - else bid >> mbits if w > 0 + else '%d-%d' % ((bid-(w-1))//mweight, bid//mweight) + if (w//mweight) > 1 + else bid//mweight if w > 0 else '', tagrepr(tag, w if i == 0 else 0, len(data), None), # note we render names a bit different here @@ -1407,10 +1409,10 @@ def main(disk, mroots=None, *, # print some information about the mtree print('mtree %s, rev %d, weight %d.%d' % ( - mroot.addr(), mroot.rev, mweight >> mbits, 1 << mbits)) + mroot.addr(), mroot.rev, bweight//mweight, 1*mweight)) # print header - w_width = (m.ceil(m.log10(max(1, mweight >> mbits)+1)) + w_width = (m.ceil(m.log10(max(1, bweight//mweight)+1)) + 2*m.ceil(m.log10(max(1, rweight)+1)) + 2) print('%-11s %*s%-*s %-22s %s' % ( @@ -1600,6 +1602,11 @@ if __name__ == "__main__": '-B', '--block-size', type=lambda x: int(x, 0), help="Block size in bytes.") + parser.add_argument( + '-M', '--mweight', + type=lambda x: int(x, 0), + help="Weight of mtree leaves for mid decoding. Defaults to a " + "block_size derived value.") parser.add_argument( '--color', choices=['never', 'always', 'auto'],