mirror of
https://github.com/littlefs-project/littlefs.git
synced 2025-12-26 09:08:30 +00:00
scripts: Avoid rereading shrub blocks
This extends Rbyd.fetch to accept another rbyd, in which case we inherit the RAM-backed block without rereading it from disk. This avoids an issue where shrubs can become corrupted if the disk is being simultaneously written and debugged. Normally we can detect the checksum mismatch and toss out the rbyd during fetch, but shrub pointers don't include a checksum since they assume the containing rbyd has already been checksummed. It's interesting to note this even avoids the memory copy thanks to Python's reference counting.
This commit is contained in:
@@ -616,14 +616,14 @@ class Rbyd:
|
||||
self.trunk)
|
||||
|
||||
@classmethod
|
||||
def fetch(cls, f, block_size, blocks, trunk=None, cksum=None):
|
||||
if isinstance(blocks, int):
|
||||
blocks = (blocks,)
|
||||
|
||||
if len(blocks) > 1:
|
||||
def fetch(cls, f, block_size, block, trunk=None, cksum=None):
|
||||
# multiple blocks?
|
||||
if (not isinstance(block, int)
|
||||
and not isinstance(block, Rbyd)
|
||||
and len(block) > 1):
|
||||
# fetch all blocks
|
||||
rbyds = [cls.fetch(f, block_size, block, trunk, cksum)
|
||||
for block in blocks]
|
||||
for block in block]
|
||||
# determine most recent revision
|
||||
i = 0
|
||||
for i_, rbyd in enumerate(rbyds):
|
||||
@@ -640,17 +640,27 @@ class Rbyd:
|
||||
rbyds[(i+1+j) % len(rbyds)].block
|
||||
for j in range(len(rbyds)-1))
|
||||
return rbyd
|
||||
|
||||
# block may be an rbyd, in which case we inherit the
|
||||
# already-read data
|
||||
#
|
||||
# this helps avoid race conditions with cksums and shrubs
|
||||
if isinstance(block, Rbyd):
|
||||
# inherit the trunk too I guess?
|
||||
if trunk is None:
|
||||
trunk = block.trunk
|
||||
block, data = block.block, block.data
|
||||
else:
|
||||
# block may encode a trunk
|
||||
block = blocks[0]
|
||||
block = block[0] if not isinstance(block, int) else block
|
||||
if isinstance(block, tuple):
|
||||
if trunk is None:
|
||||
trunk = block[1]
|
||||
block = block[0]
|
||||
|
||||
# seek to the block
|
||||
f.seek(block * block_size)
|
||||
data = f.read(block_size)
|
||||
# seek to the block
|
||||
f.seek(block * block_size)
|
||||
data = f.read(block_size)
|
||||
|
||||
# fetch the rbyd
|
||||
rev = fromle32(data[0:4])
|
||||
@@ -1262,7 +1272,7 @@ def main(disk, mroots=None, *,
|
||||
# inlined bshrub?
|
||||
elif tag == TAG_BSHRUB:
|
||||
weight, trunk = fromshrub(data)
|
||||
btree = Rbyd.fetch(f, block_size, mdir.block, trunk)
|
||||
btree = Rbyd.fetch(f, block_size, mdir, trunk)
|
||||
shrub = True
|
||||
|
||||
# indirect btree?
|
||||
|
||||
Reference in New Issue
Block a user