scripts: Added better branch cksum checks
If we're fetching branches anyways, we might as well check that the checksums match. This helps protect against infinite loops in B-tree branches. Also fixed an issue where we weren't xoring perturb state on finding an explicit trunk. Note this is equivalent to LFS_M_CKFETCHES in lfs.c. --- This doesn't mean we always need LFS_M_CKFETCHES. Our dbg scripts just need to be a little bit tougher because 1. running tests with -j creates wildly corrupted and entangled littlefs images, and 2. Rbyd.fetch is almost too forgiving in choosing the nearest trunk.
This commit is contained in:
+25
-20
@@ -616,13 +616,13 @@ class Rbyd:
|
|||||||
self.trunk)
|
self.trunk)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch(cls, f, block_size, blocks, trunk=None):
|
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
|
||||||
if isinstance(blocks, int):
|
if isinstance(blocks, int):
|
||||||
blocks = (blocks,)
|
blocks = (blocks,)
|
||||||
|
|
||||||
if len(blocks) > 1:
|
if len(blocks) > 1:
|
||||||
# fetch all blocks
|
# fetch all blocks
|
||||||
rbyds = [cls.fetch(f, block_size, block, trunk)
|
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
|
||||||
for block in blocks]
|
for block in blocks]
|
||||||
# determine most recent revision
|
# determine most recent revision
|
||||||
i = 0
|
i = 0
|
||||||
@@ -654,9 +654,9 @@ class Rbyd:
|
|||||||
|
|
||||||
# fetch the rbyd
|
# fetch the rbyd
|
||||||
rev = fromle32(data[0:4])
|
rev = fromle32(data[0:4])
|
||||||
cksum = 0
|
cksum_ = 0
|
||||||
cksum_ = crc32c(data[0:4])
|
cksum__ = crc32c(data[0:4])
|
||||||
cksum__ = cksum_
|
cksum___ = cksum__
|
||||||
perturb = False
|
perturb = False
|
||||||
eoff = 0
|
eoff = 0
|
||||||
eoff_ = None
|
eoff_ = None
|
||||||
@@ -670,10 +670,10 @@ class Rbyd:
|
|||||||
while j_ < len(data) and (not trunk or eoff <= trunk):
|
while j_ < len(data) and (not trunk or eoff <= trunk):
|
||||||
# read next tag
|
# read next tag
|
||||||
v, tag, w, size, d = fromtag(data[j_:])
|
v, tag, w, size, d = fromtag(data[j_:])
|
||||||
if v != parity(cksum__):
|
if v != parity(cksum___):
|
||||||
break
|
break
|
||||||
cksum__ ^= 0x00000080 if v else 0
|
cksum___ ^= 0x00000080 if v else 0
|
||||||
cksum__ = crc32c(data[j_:j_+d], cksum__)
|
cksum___ = crc32c(data[j_:j_+d], cksum___)
|
||||||
j_ += d
|
j_ += d
|
||||||
if not tag & TAG_ALT and j_ + size > len(data):
|
if not tag & TAG_ALT and j_ + size > len(data):
|
||||||
break
|
break
|
||||||
@@ -681,22 +681,22 @@ class Rbyd:
|
|||||||
# take care of cksums
|
# take care of cksums
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
if (tag & 0xff00) != TAG_CKSUM:
|
if (tag & 0xff00) != TAG_CKSUM:
|
||||||
cksum__ = crc32c(data[j_:j_+size], cksum__)
|
cksum___ = crc32c(data[j_:j_+size], cksum___)
|
||||||
# found a cksum?
|
# found a cksum?
|
||||||
else:
|
else:
|
||||||
# check cksum
|
# check cksum
|
||||||
cksum___ = fromle32(data[j_:j_+4])
|
cksum____ = fromle32(data[j_:j_+4])
|
||||||
if cksum__ != cksum___:
|
if cksum___ != cksum____:
|
||||||
break
|
break
|
||||||
# commit what we have
|
# commit what we have
|
||||||
eoff = eoff_ if eoff_ else j_ + size
|
eoff = eoff_ if eoff_ else j_ + size
|
||||||
cksum = cksum_
|
cksum_ = cksum__
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
# update perturb bit
|
# update perturb bit
|
||||||
perturb = tag & TAG_P
|
perturb = tag & TAG_P
|
||||||
# revert to data cksum and perturb
|
# revert to data cksum and perturb
|
||||||
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
|
cksum___ = cksum__ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
# evaluate trunks
|
# evaluate trunks
|
||||||
if (tag & 0xf000) != TAG_CKSUM:
|
if (tag & 0xf000) != TAG_CKSUM:
|
||||||
@@ -720,18 +720,23 @@ class Rbyd:
|
|||||||
if trunk and j_ + size > trunk:
|
if trunk and j_ + size > trunk:
|
||||||
eoff_ = j_ + size
|
eoff_ = j_ + size
|
||||||
eoff = eoff_
|
eoff = eoff_
|
||||||
cksum = cksum_
|
cksum_ = cksum___ ^ (
|
||||||
|
0xfca42daf if perturb else 0)
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
trunk___ = 0
|
trunk___ = 0
|
||||||
|
|
||||||
# update canonical checksum, xoring out any perturb state
|
# update canonical checksum, xoring out any perturb state
|
||||||
cksum_ = cksum__ ^ (0xfca42daf if perturb else 0)
|
cksum__ = cksum___ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
j_ += size
|
j_ += size
|
||||||
|
|
||||||
return cls(block, data, rev, eoff, trunk_, weight, cksum)
|
# cksum mismatch?
|
||||||
|
if cksum is not None and cksum_ != cksum:
|
||||||
|
return cls(block, data, rev, 0, 0, 0, cksum_)
|
||||||
|
|
||||||
|
return cls(block, data, rev, eoff, trunk_, weight, cksum_)
|
||||||
|
|
||||||
def lookup(self, rid, tag):
|
def lookup(self, rid, tag):
|
||||||
if not self:
|
if not self:
|
||||||
@@ -861,7 +866,7 @@ class Rbyd:
|
|||||||
not depth or depth_ < depth):
|
not depth or depth_ < depth):
|
||||||
tag, j, d, data = branch
|
tag, j, d, data = branch
|
||||||
block, trunk, cksum = frombranch(data)
|
block, trunk, cksum = frombranch(data)
|
||||||
rbyd = Rbyd.fetch(f, block_size, block, trunk)
|
rbyd = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
# corrupted? bail here so we can keep traversing the tree
|
# corrupted? bail here so we can keep traversing the tree
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
@@ -878,7 +883,7 @@ class Rbyd:
|
|||||||
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
|
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
|
||||||
if not done and rid == -1 and tag == TAG_MTREE:
|
if not done and rid == -1 and tag == TAG_MTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
# corrupted?
|
# corrupted?
|
||||||
if not mtree:
|
if not mtree:
|
||||||
return True, -1, 0, None
|
return True, -1, 0, None
|
||||||
@@ -1161,7 +1166,7 @@ def main(disk, mroots=None, *,
|
|||||||
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
||||||
if not done and rid == -1 and tag == TAG_MTREE:
|
if not done and rid == -1 and tag == TAG_MTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
# traverse entries
|
# traverse entries
|
||||||
mbid = -1
|
mbid = -1
|
||||||
@@ -1263,7 +1268,7 @@ def main(disk, mroots=None, *,
|
|||||||
# indirect btree?
|
# indirect btree?
|
||||||
elif tag == TAG_BTREE:
|
elif tag == TAG_BTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
btree = Rbyd.fetch(f, block_size, block, trunk)
|
btree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
shrub = False
|
shrub = False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|||||||
+22
-17
@@ -288,13 +288,13 @@ class Rbyd:
|
|||||||
self.trunk)
|
self.trunk)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch(cls, f, block_size, blocks, trunk=None):
|
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
|
||||||
if isinstance(blocks, int):
|
if isinstance(blocks, int):
|
||||||
blocks = (blocks,)
|
blocks = (blocks,)
|
||||||
|
|
||||||
if len(blocks) > 1:
|
if len(blocks) > 1:
|
||||||
# fetch all blocks
|
# fetch all blocks
|
||||||
rbyds = [cls.fetch(f, block_size, block, trunk)
|
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
|
||||||
for block in blocks]
|
for block in blocks]
|
||||||
# determine most recent revision
|
# determine most recent revision
|
||||||
i = 0
|
i = 0
|
||||||
@@ -326,9 +326,9 @@ class Rbyd:
|
|||||||
|
|
||||||
# fetch the rbyd
|
# fetch the rbyd
|
||||||
rev = fromle32(data[0:4])
|
rev = fromle32(data[0:4])
|
||||||
cksum = 0
|
cksum_ = 0
|
||||||
cksum_ = crc32c(data[0:4])
|
cksum__ = crc32c(data[0:4])
|
||||||
cksum__ = cksum_
|
cksum___ = cksum__
|
||||||
perturb = False
|
perturb = False
|
||||||
eoff = 0
|
eoff = 0
|
||||||
eoff_ = None
|
eoff_ = None
|
||||||
@@ -342,10 +342,10 @@ class Rbyd:
|
|||||||
while j_ < len(data) and (not trunk or eoff <= trunk):
|
while j_ < len(data) and (not trunk or eoff <= trunk):
|
||||||
# read next tag
|
# read next tag
|
||||||
v, tag, w, size, d = fromtag(data[j_:])
|
v, tag, w, size, d = fromtag(data[j_:])
|
||||||
if v != parity(cksum__):
|
if v != parity(cksum___):
|
||||||
break
|
break
|
||||||
cksum__ ^= 0x00000080 if v else 0
|
cksum___ ^= 0x00000080 if v else 0
|
||||||
cksum__ = crc32c(data[j_:j_+d], cksum__)
|
cksum___ = crc32c(data[j_:j_+d], cksum___)
|
||||||
j_ += d
|
j_ += d
|
||||||
if not tag & TAG_ALT and j_ + size > len(data):
|
if not tag & TAG_ALT and j_ + size > len(data):
|
||||||
break
|
break
|
||||||
@@ -353,22 +353,22 @@ class Rbyd:
|
|||||||
# take care of cksums
|
# take care of cksums
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
if (tag & 0xff00) != TAG_CKSUM:
|
if (tag & 0xff00) != TAG_CKSUM:
|
||||||
cksum__ = crc32c(data[j_:j_+size], cksum__)
|
cksum___ = crc32c(data[j_:j_+size], cksum___)
|
||||||
# found a cksum?
|
# found a cksum?
|
||||||
else:
|
else:
|
||||||
# check cksum
|
# check cksum
|
||||||
cksum___ = fromle32(data[j_:j_+4])
|
cksum____ = fromle32(data[j_:j_+4])
|
||||||
if cksum__ != cksum___:
|
if cksum___ != cksum____:
|
||||||
break
|
break
|
||||||
# commit what we have
|
# commit what we have
|
||||||
eoff = eoff_ if eoff_ else j_ + size
|
eoff = eoff_ if eoff_ else j_ + size
|
||||||
cksum = cksum_
|
cksum_ = cksum__
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
# update perturb bit
|
# update perturb bit
|
||||||
perturb = tag & TAG_P
|
perturb = tag & TAG_P
|
||||||
# revert to data cksum and perturb
|
# revert to data cksum and perturb
|
||||||
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
|
cksum___ = cksum__ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
# evaluate trunks
|
# evaluate trunks
|
||||||
if (tag & 0xf000) != TAG_CKSUM:
|
if (tag & 0xf000) != TAG_CKSUM:
|
||||||
@@ -392,18 +392,23 @@ class Rbyd:
|
|||||||
if trunk and j_ + size > trunk:
|
if trunk and j_ + size > trunk:
|
||||||
eoff_ = j_ + size
|
eoff_ = j_ + size
|
||||||
eoff = eoff_
|
eoff = eoff_
|
||||||
cksum = cksum_
|
cksum_ = cksum___ ^ (
|
||||||
|
0xfca42daf if perturb else 0)
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
trunk___ = 0
|
trunk___ = 0
|
||||||
|
|
||||||
# update canonical checksum, xoring out any perturb state
|
# update canonical checksum, xoring out any perturb state
|
||||||
cksum_ = cksum__ ^ (0xfca42daf if perturb else 0)
|
cksum__ = cksum___ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
j_ += size
|
j_ += size
|
||||||
|
|
||||||
return cls(block, data, rev, eoff, trunk_, weight, cksum)
|
# cksum mismatch?
|
||||||
|
if cksum is not None and cksum_ != cksum:
|
||||||
|
return cls(block, data, rev, 0, 0, 0, cksum_)
|
||||||
|
|
||||||
|
return cls(block, data, rev, eoff, trunk_, weight, cksum_)
|
||||||
|
|
||||||
def lookup(self, rid, tag):
|
def lookup(self, rid, tag):
|
||||||
if not self:
|
if not self:
|
||||||
@@ -673,7 +678,7 @@ def main(disk, roots=None, *,
|
|||||||
not depth or depth_ < depth):
|
not depth or depth_ < depth):
|
||||||
tag, j, d, data = branch
|
tag, j, d, data = branch
|
||||||
block, trunk, cksum = frombranch(data)
|
block, trunk, cksum = frombranch(data)
|
||||||
rbyd = Rbyd.fetch(f, block_size, block, trunk)
|
rbyd = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
# corrupted? bail here so we can keep traversing the tree
|
# corrupted? bail here so we can keep traversing the tree
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
|
|||||||
+27
-22
@@ -319,13 +319,13 @@ class Rbyd:
|
|||||||
self.trunk)
|
self.trunk)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch(cls, f, block_size, blocks, trunk=None):
|
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
|
||||||
if isinstance(blocks, int):
|
if isinstance(blocks, int):
|
||||||
blocks = (blocks,)
|
blocks = (blocks,)
|
||||||
|
|
||||||
if len(blocks) > 1:
|
if len(blocks) > 1:
|
||||||
# fetch all blocks
|
# fetch all blocks
|
||||||
rbyds = [cls.fetch(f, block_size, block, trunk)
|
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
|
||||||
for block in blocks]
|
for block in blocks]
|
||||||
# determine most recent revision
|
# determine most recent revision
|
||||||
i = 0
|
i = 0
|
||||||
@@ -357,9 +357,9 @@ class Rbyd:
|
|||||||
|
|
||||||
# fetch the rbyd
|
# fetch the rbyd
|
||||||
rev = fromle32(data[0:4])
|
rev = fromle32(data[0:4])
|
||||||
cksum = 0
|
cksum_ = 0
|
||||||
cksum_ = crc32c(data[0:4])
|
cksum__ = crc32c(data[0:4])
|
||||||
cksum__ = cksum_
|
cksum___ = cksum__
|
||||||
perturb = False
|
perturb = False
|
||||||
eoff = 0
|
eoff = 0
|
||||||
eoff_ = None
|
eoff_ = None
|
||||||
@@ -373,10 +373,10 @@ class Rbyd:
|
|||||||
while j_ < len(data) and (not trunk or eoff <= trunk):
|
while j_ < len(data) and (not trunk or eoff <= trunk):
|
||||||
# read next tag
|
# read next tag
|
||||||
v, tag, w, size, d = fromtag(data[j_:])
|
v, tag, w, size, d = fromtag(data[j_:])
|
||||||
if v != parity(cksum__):
|
if v != parity(cksum___):
|
||||||
break
|
break
|
||||||
cksum__ ^= 0x00000080 if v else 0
|
cksum___ ^= 0x00000080 if v else 0
|
||||||
cksum__ = crc32c(data[j_:j_+d], cksum__)
|
cksum___ = crc32c(data[j_:j_+d], cksum___)
|
||||||
j_ += d
|
j_ += d
|
||||||
if not tag & TAG_ALT and j_ + size > len(data):
|
if not tag & TAG_ALT and j_ + size > len(data):
|
||||||
break
|
break
|
||||||
@@ -384,22 +384,22 @@ class Rbyd:
|
|||||||
# take care of cksums
|
# take care of cksums
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
if (tag & 0xff00) != TAG_CKSUM:
|
if (tag & 0xff00) != TAG_CKSUM:
|
||||||
cksum__ = crc32c(data[j_:j_+size], cksum__)
|
cksum___ = crc32c(data[j_:j_+size], cksum___)
|
||||||
# found a cksum?
|
# found a cksum?
|
||||||
else:
|
else:
|
||||||
# check cksum
|
# check cksum
|
||||||
cksum___ = fromle32(data[j_:j_+4])
|
cksum____ = fromle32(data[j_:j_+4])
|
||||||
if cksum__ != cksum___:
|
if cksum___ != cksum____:
|
||||||
break
|
break
|
||||||
# commit what we have
|
# commit what we have
|
||||||
eoff = eoff_ if eoff_ else j_ + size
|
eoff = eoff_ if eoff_ else j_ + size
|
||||||
cksum = cksum_
|
cksum_ = cksum__
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
# update perturb bit
|
# update perturb bit
|
||||||
perturb = tag & TAG_P
|
perturb = tag & TAG_P
|
||||||
# revert to data cksum and perturb
|
# revert to data cksum and perturb
|
||||||
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
|
cksum___ = cksum__ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
# evaluate trunks
|
# evaluate trunks
|
||||||
if (tag & 0xf000) != TAG_CKSUM:
|
if (tag & 0xf000) != TAG_CKSUM:
|
||||||
@@ -423,18 +423,23 @@ class Rbyd:
|
|||||||
if trunk and j_ + size > trunk:
|
if trunk and j_ + size > trunk:
|
||||||
eoff_ = j_ + size
|
eoff_ = j_ + size
|
||||||
eoff = eoff_
|
eoff = eoff_
|
||||||
cksum = cksum_
|
cksum_ = cksum___ ^ (
|
||||||
|
0xfca42daf if perturb else 0)
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
trunk___ = 0
|
trunk___ = 0
|
||||||
|
|
||||||
# update canonical checksum, xoring out any perturb state
|
# update canonical checksum, xoring out any perturb state
|
||||||
cksum_ = cksum__ ^ (0xfca42daf if perturb else 0)
|
cksum__ = cksum___ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
j_ += size
|
j_ += size
|
||||||
|
|
||||||
return cls(block, data, rev, eoff, trunk_, weight, cksum)
|
# cksum mismatch?
|
||||||
|
if cksum is not None and cksum_ != cksum:
|
||||||
|
return cls(block, data, rev, 0, 0, 0, cksum_)
|
||||||
|
|
||||||
|
return cls(block, data, rev, eoff, trunk_, weight, cksum_)
|
||||||
|
|
||||||
def lookup(self, rid, tag):
|
def lookup(self, rid, tag):
|
||||||
if not self:
|
if not self:
|
||||||
@@ -663,7 +668,7 @@ class Rbyd:
|
|||||||
not depth or depth_ < depth):
|
not depth or depth_ < depth):
|
||||||
tag, j, d, data = branch
|
tag, j, d, data = branch
|
||||||
block, trunk, cksum = frombranch(data)
|
block, trunk, cksum = frombranch(data)
|
||||||
rbyd = Rbyd.fetch(f, block_size, block, trunk)
|
rbyd = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
# corrupted? bail here so we can keep traversing the tree
|
# corrupted? bail here so we can keep traversing the tree
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
@@ -877,7 +882,7 @@ class Rbyd:
|
|||||||
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
|
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
|
||||||
if not done and rid == -1 and tag == TAG_MTREE:
|
if not done and rid == -1 and tag == TAG_MTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
# corrupted?
|
# corrupted?
|
||||||
if not mtree:
|
if not mtree:
|
||||||
return True, -1, 0, None
|
return True, -1, 0, None
|
||||||
@@ -965,7 +970,7 @@ class Rbyd:
|
|||||||
bid += rid - (w-1)
|
bid += rid - (w-1)
|
||||||
|
|
||||||
block, trunk, cksum = frombranch(data)
|
block, trunk, cksum = frombranch(data)
|
||||||
rbyd = Rbyd.fetch(f, block_size, block, trunk)
|
rbyd = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
# found best match
|
# found best match
|
||||||
else:
|
else:
|
||||||
@@ -977,7 +982,7 @@ class Rbyd:
|
|||||||
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
|
done, rid, tag, w, j, d, data, _ = self.lookup(-1, TAG_MTREE)
|
||||||
if not done and rid == -1 and tag == TAG_MTREE:
|
if not done and rid == -1 and tag == TAG_MTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
# corrupted?
|
# corrupted?
|
||||||
if not mtree:
|
if not mtree:
|
||||||
return False, -1, 0, None, -1, 0, 0
|
return False, -1, 0, None, -1, 0, 0
|
||||||
@@ -1321,7 +1326,7 @@ def dbg_fstruct(f, block_size, mdir, rid, tag, j, d, data, *,
|
|||||||
# indirect btree?
|
# indirect btree?
|
||||||
elif tag == TAG_BTREE:
|
elif tag == TAG_BTREE:
|
||||||
weight, block, trunk, cksum = frombtree(data)
|
weight, block, trunk, cksum = frombtree(data)
|
||||||
btree = Rbyd.fetch(f, block_size, block, trunk)
|
btree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
w = weight
|
w = weight
|
||||||
|
|
||||||
# precompute rbyd-trees if requested
|
# precompute rbyd-trees if requested
|
||||||
@@ -1827,7 +1832,7 @@ def main(disk, mroots=None, *,
|
|||||||
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
||||||
if not done and rid == -1 and tag == TAG_MTREE:
|
if not done and rid == -1 and tag == TAG_MTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
bweight = w
|
bweight = w
|
||||||
|
|
||||||
|
|||||||
+24
-19
@@ -303,13 +303,13 @@ class Rbyd:
|
|||||||
self.trunk)
|
self.trunk)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch(cls, f, block_size, blocks, trunk=None):
|
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
|
||||||
if isinstance(blocks, int):
|
if isinstance(blocks, int):
|
||||||
blocks = (blocks,)
|
blocks = (blocks,)
|
||||||
|
|
||||||
if len(blocks) > 1:
|
if len(blocks) > 1:
|
||||||
# fetch all blocks
|
# fetch all blocks
|
||||||
rbyds = [cls.fetch(f, block_size, block, trunk)
|
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
|
||||||
for block in blocks]
|
for block in blocks]
|
||||||
# determine most recent revision
|
# determine most recent revision
|
||||||
i = 0
|
i = 0
|
||||||
@@ -341,9 +341,9 @@ class Rbyd:
|
|||||||
|
|
||||||
# fetch the rbyd
|
# fetch the rbyd
|
||||||
rev = fromle32(data[0:4])
|
rev = fromle32(data[0:4])
|
||||||
cksum = 0
|
cksum_ = 0
|
||||||
cksum_ = crc32c(data[0:4])
|
cksum__ = crc32c(data[0:4])
|
||||||
cksum__ = cksum_
|
cksum___ = cksum__
|
||||||
perturb = False
|
perturb = False
|
||||||
eoff = 0
|
eoff = 0
|
||||||
eoff_ = None
|
eoff_ = None
|
||||||
@@ -357,10 +357,10 @@ class Rbyd:
|
|||||||
while j_ < len(data) and (not trunk or eoff <= trunk):
|
while j_ < len(data) and (not trunk or eoff <= trunk):
|
||||||
# read next tag
|
# read next tag
|
||||||
v, tag, w, size, d = fromtag(data[j_:])
|
v, tag, w, size, d = fromtag(data[j_:])
|
||||||
if v != parity(cksum__):
|
if v != parity(cksum___):
|
||||||
break
|
break
|
||||||
cksum__ ^= 0x00000080 if v else 0
|
cksum___ ^= 0x00000080 if v else 0
|
||||||
cksum__ = crc32c(data[j_:j_+d], cksum__)
|
cksum___ = crc32c(data[j_:j_+d], cksum___)
|
||||||
j_ += d
|
j_ += d
|
||||||
if not tag & TAG_ALT and j_ + size > len(data):
|
if not tag & TAG_ALT and j_ + size > len(data):
|
||||||
break
|
break
|
||||||
@@ -368,22 +368,22 @@ class Rbyd:
|
|||||||
# take care of cksums
|
# take care of cksums
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
if (tag & 0xff00) != TAG_CKSUM:
|
if (tag & 0xff00) != TAG_CKSUM:
|
||||||
cksum__ = crc32c(data[j_:j_+size], cksum__)
|
cksum___ = crc32c(data[j_:j_+size], cksum___)
|
||||||
# found a cksum?
|
# found a cksum?
|
||||||
else:
|
else:
|
||||||
# check cksum
|
# check cksum
|
||||||
cksum___ = fromle32(data[j_:j_+4])
|
cksum____ = fromle32(data[j_:j_+4])
|
||||||
if cksum__ != cksum___:
|
if cksum___ != cksum____:
|
||||||
break
|
break
|
||||||
# commit what we have
|
# commit what we have
|
||||||
eoff = eoff_ if eoff_ else j_ + size
|
eoff = eoff_ if eoff_ else j_ + size
|
||||||
cksum = cksum_
|
cksum_ = cksum__
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
# update perturb bit
|
# update perturb bit
|
||||||
perturb = tag & TAG_P
|
perturb = tag & TAG_P
|
||||||
# revert to data cksum and perturb
|
# revert to data cksum and perturb
|
||||||
cksum__ = cksum_ ^ (0xfca42daf if perturb else 0)
|
cksum___ = cksum__ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
# evaluate trunks
|
# evaluate trunks
|
||||||
if (tag & 0xf000) != TAG_CKSUM:
|
if (tag & 0xf000) != TAG_CKSUM:
|
||||||
@@ -407,18 +407,23 @@ class Rbyd:
|
|||||||
if trunk and j_ + size > trunk:
|
if trunk and j_ + size > trunk:
|
||||||
eoff_ = j_ + size
|
eoff_ = j_ + size
|
||||||
eoff = eoff_
|
eoff = eoff_
|
||||||
cksum = cksum_
|
cksum_ = cksum___ ^ (
|
||||||
|
0xfca42daf if perturb else 0)
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
trunk___ = 0
|
trunk___ = 0
|
||||||
|
|
||||||
# update canonical checksum, xoring out any perturb state
|
# update canonical checksum, xoring out any perturb state
|
||||||
cksum_ = cksum__ ^ (0xfca42daf if perturb else 0)
|
cksum__ = cksum___ ^ (0xfca42daf if perturb else 0)
|
||||||
|
|
||||||
if not tag & TAG_ALT:
|
if not tag & TAG_ALT:
|
||||||
j_ += size
|
j_ += size
|
||||||
|
|
||||||
return cls(block, data, rev, eoff, trunk_, weight, cksum)
|
# cksum mismatch?
|
||||||
|
if cksum is not None and cksum_ != cksum:
|
||||||
|
return cls(block, data, rev, 0, 0, 0, cksum_)
|
||||||
|
|
||||||
|
return cls(block, data, rev, eoff, trunk_, weight, cksum_)
|
||||||
|
|
||||||
def lookup(self, rid, tag):
|
def lookup(self, rid, tag):
|
||||||
if not self:
|
if not self:
|
||||||
@@ -647,7 +652,7 @@ class Rbyd:
|
|||||||
not depth or depth_ < depth):
|
not depth or depth_ < depth):
|
||||||
tag, j, d, data = branch
|
tag, j, d, data = branch
|
||||||
block, trunk, cksum = frombranch(data)
|
block, trunk, cksum = frombranch(data)
|
||||||
rbyd = Rbyd.fetch(f, block_size, block, trunk)
|
rbyd = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
# corrupted? bail here so we can keep traversing the tree
|
# corrupted? bail here so we can keep traversing the tree
|
||||||
if not rbyd:
|
if not rbyd:
|
||||||
@@ -943,7 +948,7 @@ def main(disk, mroots=None, *,
|
|||||||
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
||||||
if not done and rid == -1 and tag == TAG_MTREE:
|
if not done and rid == -1 and tag == TAG_MTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
bweight = w
|
bweight = w
|
||||||
|
|
||||||
@@ -1624,7 +1629,7 @@ def main(disk, mroots=None, *,
|
|||||||
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
done, rid, tag, w, j, d, data, _ = mroot.lookup(-1, TAG_MTREE)
|
||||||
if not done and rid == -1 and tag == TAG_MTREE:
|
if not done and rid == -1 and tag == TAG_MTREE:
|
||||||
w, block, trunk, cksum = frombtree(data)
|
w, block, trunk, cksum = frombtree(data)
|
||||||
mtree = Rbyd.fetch(f, block_size, block, trunk)
|
mtree = Rbyd.fetch(f, block_size, block, trunk, cksum)
|
||||||
|
|
||||||
# traverse entries
|
# traverse entries
|
||||||
mbid = -1
|
mbid = -1
|
||||||
|
|||||||
+2
-1
@@ -1003,7 +1003,8 @@ def main(disk, blocks=None, *,
|
|||||||
if trunk and j_ + size > trunk:
|
if trunk and j_ + size > trunk:
|
||||||
eoff_ = j_ + size
|
eoff_ = j_ + size
|
||||||
eoff = eoff_
|
eoff = eoff_
|
||||||
cksum = cksum_
|
cksum = cksum__ ^ (
|
||||||
|
0xfca42daf if perturb else 0)
|
||||||
trunk_ = trunk__
|
trunk_ = trunk__
|
||||||
weight = weight_
|
weight = weight_
|
||||||
trunk___ = 0
|
trunk___ = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user