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:
@@ -1154,7 +1154,8 @@ enum lfsr_tag {
|
||||
|
||||
// checksum tags
|
||||
LFSR_TAG_CKSUM = 0x3000,
|
||||
LFSR_TAG_P = 0x0001,
|
||||
LFSR_TAG_PHASE = 0x0003,
|
||||
LFSR_TAG_PERTURB = 0x0004,
|
||||
LFSR_TAG_NOTE = 0x3100,
|
||||
LFSR_TAG_ECKSUM = 0x3200,
|
||||
LFSR_TAG_GCKSUMDELTA = 0x3300,
|
||||
@@ -1213,7 +1214,7 @@ static inline lfsr_tag_t lfsr_tag_subkey(lfsr_tag_t tag) {
|
||||
return tag & 0x00ff;
|
||||
}
|
||||
|
||||
static inline lfsr_tag_t lfsr_tag_redund(lfsr_tag_t tag) {
|
||||
static inline uint8_t lfsr_tag_redund(lfsr_tag_t tag) {
|
||||
return tag & 0x0003;
|
||||
}
|
||||
|
||||
@@ -1229,8 +1230,12 @@ static inline bool lfsr_tag_istrunk(lfsr_tag_t tag) {
|
||||
return lfsr_tag_mode(tag) != LFSR_TAG_CKSUM;
|
||||
}
|
||||
|
||||
static inline bool lfsr_tag_p(lfsr_tag_t tag) {
|
||||
return tag & LFSR_TAG_P;
|
||||
static inline uint8_t lfsr_tag_phase(lfsr_tag_t tag) {
|
||||
return tag & LFSR_TAG_PHASE;
|
||||
}
|
||||
|
||||
static inline bool lfsr_tag_perturb(lfsr_tag_t tag) {
|
||||
return tag & LFSR_TAG_PERTURB;
|
||||
}
|
||||
|
||||
static inline bool lfsr_tag_isinternal(lfsr_tag_t tag) {
|
||||
@@ -3013,11 +3018,17 @@ static int lfsr_rbyd_fetch_(lfs_t *lfs,
|
||||
|
||||
// is an end-of-commit cksum
|
||||
} else {
|
||||
// truncate checksum?
|
||||
// truncated checksum?
|
||||
if (size < sizeof(uint32_t)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// check phase
|
||||
if (lfsr_tag_phase(tag) != (block & 0x3)) {
|
||||
// uh oh, phase doesn't match, mounted incorrectly?
|
||||
break;
|
||||
}
|
||||
|
||||
// check checksum
|
||||
uint32_t cksum__ = 0;
|
||||
err = lfsr_bd_read(lfs, block, off_, -1,
|
||||
@@ -3037,7 +3048,7 @@ static int lfsr_rbyd_fetch_(lfs_t *lfs,
|
||||
|
||||
// save what we've found so far
|
||||
rbyd->eoff
|
||||
= ((lfs_size_t)lfsr_tag_p(tag)
|
||||
= ((lfs_size_t)lfsr_tag_perturb(tag)
|
||||
<< (8*sizeof(lfs_size_t)-1))
|
||||
| (off_ + size);
|
||||
rbyd->cksum = cksum;
|
||||
@@ -4488,7 +4499,10 @@ static int lfsr_rbyd_appendcksum_(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
| ((uint8_t)v << 7);
|
||||
cksum_buf[1] = (uint8_t)(LFSR_TAG_CKSUM >> 0)
|
||||
// set the perturb bit so next commit is invalid
|
||||
| ((uint8_t)perturb << 0);
|
||||
| ((uint8_t)perturb << 2)
|
||||
// include the lower 2 bits of the block address to help
|
||||
// with resynchronization
|
||||
| (rbyd->blocks[0] & 0x3);
|
||||
cksum_buf[2] = 0;
|
||||
|
||||
lfs_size_t padding = off_ - (lfsr_rbyd_eoff(rbyd) + 2+1+4);
|
||||
|
||||
+9
-7
@@ -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)
|
||||
|
||||
|
||||
@@ -65,8 +65,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 ---- ----
|
||||
@@ -376,7 +377,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
|
||||
@@ -392,9 +393,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
|
||||
@@ -714,7 +716,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)
|
||||
|
||||
|
||||
+9
-7
@@ -56,8 +56,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 ---- ----
|
||||
@@ -254,7 +255,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
|
||||
@@ -270,9 +271,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
|
||||
@@ -592,7 +594,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)
|
||||
|
||||
|
||||
+9
-7
@@ -57,8 +57,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 ---- ----
|
||||
@@ -303,7 +304,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
|
||||
@@ -319,9 +320,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
|
||||
@@ -641,7 +643,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)
|
||||
|
||||
|
||||
+9
-7
@@ -56,8 +56,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 ---- ----
|
||||
@@ -269,7 +270,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
|
||||
@@ -285,9 +286,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
|
||||
@@ -607,7 +609,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)
|
||||
|
||||
|
||||
+15
-8
@@ -66,8 +66,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 ---- ----
|
||||
@@ -257,7 +258,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
|
||||
@@ -273,9 +274,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
|
||||
@@ -575,7 +577,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)
|
||||
|
||||
@@ -1548,6 +1550,7 @@ def dbg_log(rbyd, *,
|
||||
# read next tag
|
||||
j = j_
|
||||
v, tag, w, size, d = fromtag(data, j_)
|
||||
# note if parity doesn't match
|
||||
if v != parity(cksum_):
|
||||
notes.append('v!=%x' % parity(cksum_))
|
||||
cksum_ ^= 0x00000080 if v else 0
|
||||
@@ -1560,12 +1563,16 @@ def dbg_log(rbyd, *,
|
||||
cksum_ = crc32c(data[j_:j_+size], cksum_)
|
||||
# found a cksum?
|
||||
else:
|
||||
# note if phase doesn't match
|
||||
if (tag & 0x3) != (rbyd.block & 0x3):
|
||||
notes.append('q!=%x' % (rbyd.block & 0x3))
|
||||
# check cksum
|
||||
cksum__ = fromle32(data, j_)
|
||||
# note if cksum doesn't match
|
||||
if cksum_ != cksum__:
|
||||
notes.append('cksum!=%08x' % cksum__)
|
||||
# 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)
|
||||
j_ += size
|
||||
|
||||
+8
-6
@@ -49,8 +49,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 ---- ----
|
||||
@@ -161,7 +162,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
|
||||
@@ -177,9 +178,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
|
||||
|
||||
@@ -1963,3 +1963,55 @@ code = '''
|
||||
|
||||
lfsr_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
|
||||
# Ok, here's an interesting one, test that we fail if we're
|
||||
# "out-of-phase", i.e. the mrootanchor has 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. To prevent this, we include 2
|
||||
# phase bits in cksum tags to detect up to a 3 block shift (the maximum
|
||||
# number of redund mrootanchors)
|
||||
#
|
||||
[cases.test_mount_incompat_out_of_phase]
|
||||
defines.PHASE = [1, 2, 3, 4]
|
||||
in = 'lfs.c'
|
||||
code = '''
|
||||
// create a superblock
|
||||
lfs_t lfs;
|
||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||
|
||||
// with some files
|
||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0;
|
||||
lfsr_file_t file;
|
||||
lfsr_file_open(&lfs, &file, "r2d2",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
char wbuf[256];
|
||||
strcpy(wbuf, "beep boop");
|
||||
lfsr_file_write(&lfs, &file, wbuf, strlen(wbuf)) => strlen(wbuf);
|
||||
lfsr_file_close(&lfs, &file) => 0;
|
||||
lfsr_file_open(&lfs, &file, "c3po",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
strcpy(wbuf, "we seem to be made to suffer");
|
||||
lfsr_file_write(&lfs, &file, wbuf, strlen(wbuf)) => strlen(wbuf);
|
||||
lfsr_file_close(&lfs, &file) => 0;
|
||||
|
||||
// shift the filesystem out-of-phase
|
||||
uint8_t shift_buf[BLOCK_SIZE];
|
||||
for (lfs_size_t i = 0; i < 4; i++) {
|
||||
CFG->read(CFG, 4-1-i, 0, shift_buf, BLOCK_SIZE) => 0;
|
||||
CFG->erase(CFG, 4-1-i + PHASE) => 0;
|
||||
CFG->prog(CFG, 4-1-i + PHASE, 0, shift_buf, BLOCK_SIZE) => 0;
|
||||
|
||||
memset(shift_buf, 0, BLOCK_SIZE);
|
||||
strcpy((char*)shift_buf,
|
||||
"these aren't the files you're looking for ;)");
|
||||
CFG->erase(CFG, 4-1-i) => 0;
|
||||
CFG->prog(CFG, 4-1-i, 0, shift_buf, BLOCK_SIZE) => 0;
|
||||
}
|
||||
|
||||
// mount should now fail
|
||||
lfsr_mount(&lfs, LFS_M_RDWR, CFG) => LFS_ERR_CORRUPT;
|
||||
lfsr_mount(&lfs, LFS_M_RDONLY, CFG) => LFS_ERR_CORRUPT;
|
||||
'''
|
||||
|
||||
Reference in New Issue
Block a user