forked from Imagelibrary/littlefs
Added phase bits to cksum tags
This carves out two more bits in cksum tags to store the "phase" of the
rbyd block (maybe the name is too fancy, this is just the lowest 2 bits
of the block address):
LFSR_TAG_CKSUM 0x300p v-11 ---- ---- -pqq
^ ^
| '-- phase bits
'---- perturb bit
The intention here is to catch mrootanchors that are "out-of-phase",
i.e. they've been shifted by a small number of blocks.
This can happen if we find the wrong mrootanchor (after, say, a magic
scan), and risks filesystem corruption:
formatted
.-----------------'-----------------.
mounted
.-----------------'-----------------.
.--------+--------+--------+--------+ ...
|(erased)| mroot |
| | anchor | ...
| | |
'--------+--------+--------+--------+ ...
Including the lower 2 bits of the block address in cksum tags avoids
this, for up to a 3 block shift (the maximum number of redund
mrootanchors).
---
Note that cksum tags really are the only place we could put these bits.
Anywhere else and they would interfere with the canonical cksum, which
would break error correction. By definition these need to be different
per block.
We include these phase bits in every cksum tag (because it's easier),
but these don't really say much about mdirs that are not the
mrootanchor. Non-anchor mdirs can have arbitrary block addresses,
therefore arbitrary phase bits.
You _might_ be able to do something interesting if you sort the rbyd
addresses and use the index as the phase bits, but that would add quite
a bit of code for questionable benefit...
You could argue this adds noise to our cksums, but:
1. 2 bits seems like a really small amount of noise
2. our cksums are just crc32cs
3. the phase bits humorously never change when you rewrite a block
---
As with any feature this adds code, but only a small amount. I think
it's worth the extra protection:
code stack ctx
before: 35792 2368 636
after: 35824 (+0.1%) 2368 (+0.0%) 636 (+0.0%)
Also added test_mount_incompat_out_of_phase to test this.
The dbg scripts _don't_ error (block mismatch seems likely when
debugging), but dbgrbyd.py at least adds phase mismatch notes in
-l/--log mode.
This commit is contained in:
@@ -67,8 +67,9 @@ TAG_B = 0x0000
|
||||
TAG_R = 0x2000
|
||||
TAG_LE = 0x0000
|
||||
TAG_GT = 0x1000
|
||||
TAG_CKSUM = 0x3000 ## 0x300p v-11 ---- ---- ---p
|
||||
TAG_P = 0x0001
|
||||
TAG_CKSUM = 0x3000 ## 0x300p v-11 ---- ---- -pqq
|
||||
TAG_PHASE = 0x0003
|
||||
TAG_PERTURB = 0x0004
|
||||
TAG_NOTE = 0x3100 ## 0x3100 v-11 ---1 ---- ----
|
||||
TAG_ECKSUM = 0x3200 ## 0x3200 v-11 --1- ---- ----
|
||||
TAG_GCKSUMDELTA = 0x3300 ## 0x3300 v-11 --11 ---- ----
|
||||
@@ -346,7 +347,7 @@ def tagrepr(tag, weight=None, size=None, *,
|
||||
return '%s%sattr 0x%02x%s%s' % (
|
||||
'shrub' if tag & TAG_SHRUB else '',
|
||||
's' if tag & 0x100 else 'u',
|
||||
((tag & 0x100) >> 1) ^ (tag & 0xff),
|
||||
((tag & 0x100) >> 1) + (tag & 0xff),
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# alt pointers
|
||||
@@ -362,9 +363,10 @@ def tagrepr(tag, weight=None, size=None, *,
|
||||
else '')
|
||||
# checksum tags
|
||||
elif (tag & 0x7f00) == TAG_CKSUM:
|
||||
return 'cksum%s%s%s%s' % (
|
||||
'p' if not tag & 0xfe and tag & TAG_P else '',
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xfe else '',
|
||||
return 'cksum%s%s%s%s%s' % (
|
||||
'q%d' % (tag & 0x3),
|
||||
'p' if tag & TAG_PERTURB else '',
|
||||
' 0x%02x' % (tag & 0xff) if tag & 0xf8 else '',
|
||||
' w%d' % weight if weight else '',
|
||||
' %s' % size if size is not None else '')
|
||||
# note tags
|
||||
@@ -684,7 +686,7 @@ class Rbyd:
|
||||
gcksumdelta = gcksumdelta_
|
||||
gcksumdelta_ = None
|
||||
# update perturb bit
|
||||
perturb = tag & TAG_P
|
||||
perturb = bool(tag & TAG_PERTURB)
|
||||
# revert to data cksum and perturb
|
||||
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user