Skip to content

Commit e3fdc3d

Browse files
committed
scripts: Added simple mroot cycle detectors to dbg scripts
These work by keeping a set of all seen mroots as we descend down the mroot chain. Simple, but it works. The downside of this approach is that the mroot set grows unbounded, but it's unlikely we'll ever have enough mroots in a system for this to really matter. This fixes scripts like dbgbmap.py getting stuck on intentional mroot cycles created for testing. It's not a problem for a foreground script to get stuck in an infinite loop, since you can just kill it, but a background script getting stuck at 100% CPU is a bit more annoying.
1 parent b08c66e commit e3fdc3d

File tree

9 files changed

+173
-126
lines changed

9 files changed

+173
-126
lines changed

scripts/dbgblock.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ def bdgeom(s):
2727
return int(s, b)
2828

2929
# parse some rbyd addr encodings
30-
# 0xa -> [0xa]
31-
# 0xa.c -> [(0xa, 0xc)]
32-
# 0x{a,b} -> [0xa, 0xb]
33-
# 0x{a,b}.c -> [(0xa, 0xc), (0xb, 0xc)]
30+
# 0xa -> (0xa,)
31+
# 0xa.c -> ((0xa, 0xc),)
32+
# 0x{a,b} -> (0xa, 0xb)
33+
# 0x{a,b}.c -> ((0xa, 0xc), (0xb, 0xc))
3434
def rbydaddr(s):
3535
s = s.strip()
3636
b = 10
@@ -61,7 +61,7 @@ def rbydaddr(s):
6161
else:
6262
addr.append(int(s, b))
6363

64-
return addr
64+
return tuple(addr)
6565

6666
def xxd(data, width=16):
6767
for i in range(0, len(data), width):
@@ -95,7 +95,7 @@ def main(disk, block=None, *,
9595

9696
# flatten block, default to block 0
9797
if not block:
98-
block = [0]
98+
block = (0,)
9999

100100
if len(block) > 1:
101101
print("error: more than one block address?",

scripts/dbgbmap.py

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@ def bdgeom(s):
9292
return int(s, b)
9393

9494
# parse some rbyd addr encodings
95-
# 0xa -> [0xa]
96-
# 0xa.c -> [(0xa, 0xc)]
97-
# 0x{a,b} -> [0xa, 0xb]
98-
# 0x{a,b}.c -> [(0xa, 0xc), (0xb, 0xc)]
95+
# 0xa -> (0xa,)
96+
# 0xa.c -> ((0xa, 0xc),)
97+
# 0x{a,b} -> (0xa, 0xb)
98+
# 0x{a,b}.c -> ((0xa, 0xc), (0xb, 0xc))
9999
def rbydaddr(s):
100100
s = s.strip()
101101
b = 10
@@ -126,7 +126,7 @@ def rbydaddr(s):
126126
else:
127127
addr.append(int(s, b))
128128

129-
return addr
129+
return tuple(addr)
130130

131131
def crc32c(data, crc=0):
132132
crc ^= 0xffffffff
@@ -168,7 +168,7 @@ def frommdir(data):
168168
block, d_ = fromleb128(data[d:])
169169
blocks.append(block)
170170
d += d_
171-
return blocks
171+
return tuple(blocks)
172172

173173
def fromshrub(data):
174174
d = 0
@@ -591,33 +591,34 @@ def draw(self, row, *,
591591

592592
# our core rbyd type
593593
class Rbyd:
594-
def __init__(self, block, data, rev, eoff, trunk, weight, cksum):
595-
self.block = block
594+
def __init__(self, blocks, data, rev, eoff, trunk, weight, cksum):
595+
if isinstance(blocks, int):
596+
blocks = (blocks,)
597+
598+
self.blocks = tuple(blocks)
596599
self.data = data
597600
self.rev = rev
598601
self.eoff = eoff
599602
self.trunk = trunk
600603
self.weight = weight
601604
self.cksum = cksum
602-
self.redund_blocks = []
603605

604606
@property
605-
def blocks(self):
606-
return (self.block, *self.redund_blocks)
607+
def block(self):
608+
return self.blocks[0]
607609

608610
def addr(self):
609-
if not self.redund_blocks:
611+
if len(self.blocks) == 1:
610612
return '0x%x.%x' % (self.block, self.trunk)
611613
else:
612-
return '0x{%x,%s}.%x' % (
613-
self.block,
614-
','.join('%x' % block for block in self.redund_blocks),
614+
return '0x{%s}.%x' % (
615+
','.join('%x' % block for block in self.blocks),
615616
self.trunk)
616617

617618
@classmethod
618619
def fetch(cls, f, block_size, blocks, trunk=None):
619620
if isinstance(blocks, int):
620-
blocks = [blocks]
621+
blocks = (blocks,)
621622

622623
if len(blocks) > 1:
623624
# fetch all blocks
@@ -635,9 +636,9 @@ def fetch(cls, f, block_size, blocks, trunk=None):
635636
i = i_
636637
# keep track of the other blocks
637638
rbyd = rbyds[i]
638-
rbyd.redund_blocks = [
639+
rbyd.blocks += tuple(
639640
rbyds[(i+1+j) % len(rbyds)].block
640-
for j in range(len(rbyds)-1)]
641+
for j in range(len(rbyds)-1))
641642
return rbyd
642643
else:
643644
# block may encode a trunk
@@ -982,13 +983,13 @@ def main(disk, mroots=None, *,
982983
off, = size
983984
size = None
984985

985-
if any(isinstance(b, list) and len(b) > 1 for b in block):
986+
if any(isinstance(b, tuple) and len(b) > 1 for b in block):
986987
print("error: more than one block address?",
987988
file=sys.stderr)
988989
sys.exit(-1)
989-
if isinstance(block[0], list):
990+
if isinstance(block[0], tuple):
990991
block = (block[0][0], *block[1:])
991-
if len(block) > 1 and isinstance(block[1], list):
992+
if len(block) > 1 and isinstance(block[1], tuple):
992993
block = (block[0], block[1][0])
993994
if isinstance(block[0], tuple):
994995
block, off_ = (block[0][0], *block[1:]), block[0][1]
@@ -1058,7 +1059,7 @@ def main(disk, mroots=None, *,
10581059

10591060
# flatten mroots, default to 0x{0,1}
10601061
if not mroots:
1061-
mroots = [[0,1]]
1062+
mroots = [(0,1)]
10621063
mroots = [block for mroots_ in mroots for block in mroots_]
10631064

10641065
# we seek around a bunch, so just keep the disk open
@@ -1087,11 +1088,18 @@ def main(disk, mroots=None, *,
10871088
btrees__ = []
10881089
mroot = Rbyd.fetch(f, block_size, mroots)
10891090
mdepth = 1
1091+
mseen = set()
10901092
while True:
10911093
# corrupted?
10921094
if not mroot:
10931095
corrupted = True
10941096
break
1097+
# cycle detected
1098+
elif mroot.blocks in mseen:
1099+
corrupted = True
1100+
break
1101+
1102+
mseen.add(mroot.blocks)
10951103

10961104
# mark mroots in our bmap
10971105
for block in mroot.blocks:

scripts/dbgbtree.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ def bdgeom(s):
7575
return int(s, b)
7676

7777
# parse some rbyd addr encodings
78-
# 0xa -> [0xa]
79-
# 0xa.c -> [(0xa, 0xc)]
80-
# 0x{a,b} -> [0xa, 0xb]
81-
# 0x{a,b}.c -> [(0xa, 0xc), (0xb, 0xc)]
78+
# 0xa -> (0xa,)
79+
# 0xa.c -> ((0xa, 0xc),)
80+
# 0x{a,b} -> (0xa, 0xb)
81+
# 0x{a,b}.c -> ((0xa, 0xc), (0xb, 0xc))
8282
def rbydaddr(s):
8383
s = s.strip()
8484
b = 10
@@ -109,7 +109,7 @@ def rbydaddr(s):
109109
else:
110110
addr.append(int(s, b))
111111

112-
return addr
112+
return tuple(addr)
113113

114114
def crc32c(data, crc=0):
115115
crc ^= 0xffffffff
@@ -263,29 +263,34 @@ def tagrepr(tag, w=None, size=None, off=None):
263263

264264
# our core rbyd type
265265
class Rbyd:
266-
def __init__(self, block, data, rev, eoff, trunk, weight, cksum):
267-
self.block = block
266+
def __init__(self, blocks, data, rev, eoff, trunk, weight, cksum):
267+
if isinstance(blocks, int):
268+
blocks = (blocks,)
269+
270+
self.blocks = tuple(blocks)
268271
self.data = data
269272
self.rev = rev
270273
self.eoff = eoff
271274
self.trunk = trunk
272275
self.weight = weight
273276
self.cksum = cksum
274-
self.redund_blocks = []
277+
278+
@property
279+
def block(self):
280+
return self.blocks[0]
275281

276282
def addr(self):
277-
if not self.redund_blocks:
283+
if len(self.blocks) == 1:
278284
return '0x%x.%x' % (self.block, self.trunk)
279285
else:
280-
return '0x{%x,%s}.%x' % (
281-
self.block,
282-
','.join('%x' % block for block in self.redund_blocks),
286+
return '0x{%s}.%x' % (
287+
','.join('%x' % block for block in self.blocks),
283288
self.trunk)
284289

285290
@classmethod
286291
def fetch(cls, f, block_size, blocks, trunk=None):
287292
if isinstance(blocks, int):
288-
blocks = [blocks]
293+
blocks = (blocks,)
289294

290295
if len(blocks) > 1:
291296
# fetch all blocks
@@ -303,9 +308,9 @@ def fetch(cls, f, block_size, blocks, trunk=None):
303308
i = i_
304309
# keep track of the other blocks
305310
rbyd = rbyds[i]
306-
rbyd.redund_blocks = [
311+
rbyd.blocks += tuple(
307312
rbyds[(i+1+j) % len(rbyds)].block
308-
for j in range(len(rbyds)-1)]
313+
for j in range(len(rbyds)-1))
309314
return rbyd
310315
else:
311316
# block may encode a trunk
@@ -605,7 +610,7 @@ def main(disk, roots=None, *,
605610

606611
# flatten roots, default to block 0
607612
if not roots:
608-
roots = [[0]]
613+
roots = [(0,)]
609614
roots = [block for roots_ in roots for block in roots_]
610615

611616
# we seek around a bunch, so just keep the disk open

scripts/dbgcat.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ def bdgeom(s):
2727
return int(s, b)
2828

2929
# parse some rbyd addr encodings
30-
# 0xa -> [0xa]
31-
# 0xa.c -> [(0xa, 0xc)]
32-
# 0x{a,b} -> [0xa, 0xb]
33-
# 0x{a,b}.c -> [(0xa, 0xc), (0xb, 0xc)]
30+
# 0xa -> (0xa,)
31+
# 0xa.c -> ((0xa, 0xc),)
32+
# 0x{a,b} -> (0xa, 0xb)
33+
# 0x{a,b}.c -> ((0xa, 0xc), (0xb, 0xc))
3434
def rbydaddr(s):
3535
s = s.strip()
3636
b = 10
@@ -61,7 +61,7 @@ def rbydaddr(s):
6161
else:
6262
addr.append(int(s, b))
6363

64-
return addr
64+
return tuple(addr)
6565

6666
def xxd(data, width=16):
6767
for i in range(0, len(data), width):
@@ -94,7 +94,7 @@ def main(disk, blocks=None, *,
9494

9595
# flatten block, default to block 0
9696
if not blocks:
97-
blocks = [[0]]
97+
blocks = [(0,)]
9898
blocks = [block for blocks_ in blocks for block in blocks_]
9999

100100
with open(disk, 'rb') as f:

0 commit comments

Comments
 (0)