Replaced separate BLOCKSIZE/BLOCKCOUNT attrs with single GEOMETRY attr

This saves a bit of rbyd overhead, since these almost always come
together.

Perhaps more interesting, it carves out space for storing mroot-anchor
redundancy information. This uses the lowest two bits of the GEOMETRY
tag to indicate how many redundant blocks belong to the mroot-anchor:

  LFSR_TAG_GEOMETRY       0x0008  v--- ---- ---- 1-rr

This solves a bit of a hole in our redundancy encoding. The plan is for
this info to be stored in the lowest two bits of every pointer, but the
mroot-anchor doesn't really have a pointer.

Though this is just future plans. Right now the redundancy information
is unused. Current implementations should use the GEOMETRY tag 0x0009,
which you may notice implied redundancy level-1. This matches our
current 2-block per mdir default.

Geometry attr encoding:

  .---+---+---+---.      tag (0x0008+r): 1 be16    2 bytes
  |x0008+r| 0 |siz|      weight (0):     1 leb128  1 byte
  +---+---+---+---+      size:           1 leb128  1 byte
  | block_size    |      block_size:     1 leb128  <=4 bytes
  +---+- -+- -+- -+- -.
  | block_count       |  block_count:    1 leb128  <=5 bytes
  '---+- -+- -+- -+- -'  total:                    <=13 bytes

Code changes:

           code          stack
  before: 34092           2880
  after:  34040 (-0.2%)   2880 (+0.0%)
This commit is contained in:
Christopher Haster
2024-03-18 02:15:46 -05:00
parent 796be705ac
commit 9366674416
6 changed files with 105 additions and 91 deletions
+3 -4
View File
@@ -17,10 +17,9 @@ TAG_VERSION = 0x0004
TAG_RCOMPAT = 0x0005
TAG_WCOMPAT = 0x0006
TAG_OCOMPAT = 0x0007
TAG_BLOCKSIZE = 0x0008
TAG_BLOCKCOUNT = 0x0009
TAG_NAMELIMIT = 0x000a
TAG_SIZELIMIT = 0x000b
TAG_GEOMETRY = 0x0009
TAG_NAMELIMIT = 0x000c
TAG_SIZELIMIT = 0x000d
TAG_GDELTA = 0x0100
TAG_GRMDELTA = 0x0100
TAG_NAME = 0x0200
+4 -6
View File
@@ -15,10 +15,9 @@ TAG_VERSION = 0x0004
TAG_RCOMPAT = 0x0005
TAG_WCOMPAT = 0x0006
TAG_OCOMPAT = 0x0007
TAG_BLOCKSIZE = 0x0008
TAG_BLOCKCOUNT = 0x0009
TAG_NAMELIMIT = 0x000a
TAG_SIZELIMIT = 0x000b
TAG_GEOMETRY = 0x0009
TAG_NAMELIMIT = 0x000c
TAG_SIZELIMIT = 0x000d
TAG_GDELTA = 0x0100
TAG_GRMDELTA = 0x0100
TAG_NAME = 0x0200
@@ -168,8 +167,7 @@ def tagrepr(tag, w, size, off=None):
else 'rcompat' if (tag & 0xfff) == TAG_RCOMPAT
else 'wcompat' if (tag & 0xfff) == TAG_WCOMPAT
else 'ocompat' if (tag & 0xfff) == TAG_OCOMPAT
else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE
else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT
else 'geometry' if (tag & 0xfff) == TAG_GEOMETRY
else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
else 'config 0x%02x' % (tag & 0xff),
+15 -26
View File
@@ -16,10 +16,9 @@ TAG_VERSION = 0x0004
TAG_RCOMPAT = 0x0005
TAG_WCOMPAT = 0x0006
TAG_OCOMPAT = 0x0007
TAG_BLOCKSIZE = 0x0008
TAG_BLOCKCOUNT = 0x0009
TAG_NAMELIMIT = 0x000a
TAG_SIZELIMIT = 0x000b
TAG_GEOMETRY = 0x0009
TAG_NAMELIMIT = 0x000c
TAG_SIZELIMIT = 0x000d
TAG_GDELTA = 0x0100
TAG_GRMDELTA = 0x0100
TAG_NAME = 0x0200
@@ -199,8 +198,7 @@ def tagrepr(tag, w, size, off=None):
else 'rcompat' if (tag & 0xfff) == TAG_RCOMPAT
else 'wcompat' if (tag & 0xfff) == TAG_WCOMPAT
else 'ocompat' if (tag & 0xfff) == TAG_OCOMPAT
else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE
else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT
else 'geometry' if (tag & 0xfff) == TAG_GEOMETRY
else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
else 'config 0x%02x' % (tag & 0xff),
@@ -1055,22 +1053,15 @@ class Config:
return None
@ft.cached_property
def block_size(self):
if TAG_BLOCKSIZE in self.config:
_, data = self.config[TAG_BLOCKSIZE]
block_size, _ = fromleb128(data)
return block_size
def geometry(self):
if TAG_GEOMETRY in self.config:
_, data = self.config[TAG_GEOMETRY]
d = 0
block_size, d_ = fromleb128(data[d:]); d += d_
block_count, d_ = fromleb128(data[d:]); d += d_
return (block_size+1, block_count+1)
else:
return None
@ft.cached_property
def block_count(self):
if TAG_BLOCKCOUNT in self.config:
_, data = self.config[TAG_BLOCKCOUNT]
block_count, _ = fromleb128(data)
return block_count
else:
return None
return (None, None)
@ft.cached_property
def name_limit(self):
@@ -1107,10 +1098,8 @@ class Config:
elif tag == TAG_OCOMPAT:
return 'ocompat 0x%s' % ''.join(
'%x' % f for f in reversed(self.ocompat))
elif tag == TAG_BLOCKSIZE:
return 'blocksize %d' % self.block_size
elif tag == TAG_BLOCKCOUNT:
return 'blockcount %d' % self.block_count
elif tag == TAG_GEOMETRY:
return 'geometry %dx%d' % self.geometry
elif tag == TAG_SIZELIMIT:
return 'sizelimit %d' % self.size_limit
elif tag == TAG_NAMELIMIT:
@@ -1865,7 +1854,7 @@ def main(disk, mroots=None, *,
print('littlefs v%s.%s %dx%d %s, rev %d, weight %d.%d' % (
config.version[0] if config.version[0] is not None else '?',
config.version[1] if config.version[1] is not None else '?',
(config.block_size or -1)+1, (config.block_count or -1)+1,
(config.geometry[0] or 0), (config.geometry[1] or 0),
mroot.addr(), mroot.rev, bweight//mleaf_weight, 1*mleaf_weight))
# dynamically size the id field
+4 -6
View File
@@ -15,10 +15,9 @@ TAG_VERSION = 0x0004
TAG_RCOMPAT = 0x0005
TAG_WCOMPAT = 0x0006
TAG_OCOMPAT = 0x0007
TAG_BLOCKSIZE = 0x0008
TAG_BLOCKCOUNT = 0x0009
TAG_NAMELIMIT = 0x000a
TAG_SIZELIMIT = 0x000b
TAG_GEOMETRY = 0x0009
TAG_NAMELIMIT = 0x000c
TAG_SIZELIMIT = 0x000d
TAG_GDELTA = 0x0100
TAG_GRMDELTA = 0x0100
TAG_NAME = 0x0200
@@ -183,8 +182,7 @@ def tagrepr(tag, w, size, off=None):
else 'rcompat' if (tag & 0xfff) == TAG_RCOMPAT
else 'wcompat' if (tag & 0xfff) == TAG_WCOMPAT
else 'ocompat' if (tag & 0xfff) == TAG_OCOMPAT
else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE
else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT
else 'geometry' if (tag & 0xfff) == TAG_GEOMETRY
else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
else 'config 0x%02x' % (tag & 0xff),
+4 -6
View File
@@ -24,10 +24,9 @@ TAG_VERSION = 0x0004
TAG_RCOMPAT = 0x0005
TAG_WCOMPAT = 0x0006
TAG_OCOMPAT = 0x0007
TAG_BLOCKSIZE = 0x0008
TAG_BLOCKCOUNT = 0x0009
TAG_NAMELIMIT = 0x000a
TAG_SIZELIMIT = 0x000b
TAG_GEOMETRY = 0x0009
TAG_NAMELIMIT = 0x000c
TAG_SIZELIMIT = 0x000d
TAG_GDELTA = 0x0100
TAG_GRMDELTA = 0x0100
TAG_NAME = 0x0200
@@ -170,8 +169,7 @@ def tagrepr(tag, w, size, off=None):
else 'rcompat' if (tag & 0xfff) == TAG_RCOMPAT
else 'wcompat' if (tag & 0xfff) == TAG_WCOMPAT
else 'ocompat' if (tag & 0xfff) == TAG_OCOMPAT
else 'blocksize' if (tag & 0xfff) == TAG_BLOCKSIZE
else 'blockcount' if (tag & 0xfff) == TAG_BLOCKCOUNT
else 'geometry' if (tag & 0xfff) == TAG_GEOMETRY
else 'sizelimit' if (tag & 0xfff) == TAG_SIZELIMIT
else 'namelimit' if (tag & 0xfff) == TAG_NAMELIMIT
else 'config 0x%02x' % (tag & 0xff),