scripts: dbglfs.py: Added --ckmeta/--ckdata
For more aggressive checking of filesystem state. These should match the behavior of LFS_M_CKMETA/CKDATA in lfs.c. Also tweaked dbgbmapd3.py (and eventually dbgmap.py) to match, though we don't need new flags there since we're already checking every block in the filesystem.
This commit is contained in:
+34
-24
@@ -1550,7 +1550,11 @@ class Mdir:
|
|||||||
return self.rbyd.gcksumdelta
|
return self.rbyd.gcksumdelta
|
||||||
|
|
||||||
def addr(self):
|
def addr(self):
|
||||||
return self.rbyd.addr()
|
if len(self.blocks) == 1:
|
||||||
|
return '0x%x' % self.block
|
||||||
|
else:
|
||||||
|
return '0x{%s}' % (
|
||||||
|
','.join('%x' % block for block in self.blocks))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s %s>' % (self.__class__.__name__, self.repr())
|
return '<%s %s>' % (self.__class__.__name__, self.repr())
|
||||||
@@ -4636,12 +4640,12 @@ class RangeDict:
|
|||||||
|
|
||||||
|
|
||||||
def main(disk, output, mroots=None, *,
|
def main(disk, output, mroots=None, *,
|
||||||
quiet=False,
|
|
||||||
trunk=None,
|
trunk=None,
|
||||||
mtree_only=False,
|
|
||||||
block_size=None,
|
block_size=None,
|
||||||
block_count=None,
|
block_count=None,
|
||||||
blocks=None,
|
blocks=None,
|
||||||
|
mtree_only=False,
|
||||||
|
quiet=False,
|
||||||
labels=[],
|
labels=[],
|
||||||
colors=[],
|
colors=[],
|
||||||
width=None,
|
width=None,
|
||||||
@@ -4752,6 +4756,7 @@ def main(disk, output, mroots=None, *,
|
|||||||
# fetch the filesystem
|
# fetch the filesystem
|
||||||
bd = Bd(f, block_size, block_count)
|
bd = Bd(f, block_size, block_count)
|
||||||
lfs = Lfs.fetch(bd, mroots, trunk)
|
lfs = Lfs.fetch(bd, mroots, trunk)
|
||||||
|
corrupted = not bool(lfs)
|
||||||
|
|
||||||
# if we can't figure out the block_count, guess
|
# if we can't figure out the block_count, guess
|
||||||
if block_count is None:
|
if block_count is None:
|
||||||
@@ -4832,9 +4837,12 @@ def main(disk, output, mroots=None, *,
|
|||||||
bmap[b] = Block(b, 'conflict', [
|
bmap[b] = Block(b, 'conflict', [
|
||||||
bmap[b].value,
|
bmap[b].value,
|
||||||
child])
|
child])
|
||||||
|
corrupted = True
|
||||||
|
|
||||||
# corrupt block?
|
# corrupt block?
|
||||||
elif not child:
|
elif not child:
|
||||||
bmap[b] = Block(b, 'corrupt', child)
|
bmap[b] = Block(b, 'corrupt', child)
|
||||||
|
corrupted = True
|
||||||
|
|
||||||
# normal block
|
# normal block
|
||||||
else:
|
else:
|
||||||
@@ -5663,19 +5671,21 @@ def main(disk, output, mroots=None, *,
|
|||||||
|
|
||||||
# print some summary info
|
# print some summary info
|
||||||
if not quiet:
|
if not quiet:
|
||||||
print('updated %s, littlefs%s v%s.%s %sx%s %s w%s.%s, cksum %08x%s' % (
|
print('updated %s, '
|
||||||
output,
|
'littlefs%s v%s.%s %sx%s %s w%s.%s, '
|
||||||
'' if lfs.ckmagic() else '?',
|
'cksum %08x%s' % (
|
||||||
lfs.version.major if lfs.version is not None else '?',
|
output,
|
||||||
lfs.version.minor if lfs.version is not None else '?',
|
'' if lfs.ckmagic() else '?',
|
||||||
lfs.block_size if lfs.block_size is not None else '?',
|
lfs.version.major if lfs.version is not None else '?',
|
||||||
lfs.block_count if lfs.block_count is not None else '?',
|
lfs.version.minor if lfs.version is not None else '?',
|
||||||
lfs.addr(),
|
lfs.block_size if lfs.block_size is not None else '?',
|
||||||
lfs.mbweightrepr(), lfs.mrweightrepr(),
|
lfs.block_count if lfs.block_count is not None else '?',
|
||||||
lfs.cksum,
|
lfs.addr(),
|
||||||
'' if lfs.ckcksum() else '?'))
|
lfs.mbweightrepr(), lfs.mrweightrepr(),
|
||||||
|
lfs.cksum,
|
||||||
|
'' if lfs.ckcksum() else '?'))
|
||||||
|
|
||||||
if args.get('error_on_corrupt') and not lfs:
|
if args.get('error_on_corrupt') and corrupted:
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
@@ -5698,19 +5708,10 @@ if __name__ == "__main__":
|
|||||||
'-o', '--output',
|
'-o', '--output',
|
||||||
required=True,
|
required=True,
|
||||||
help="Output *.svg file.")
|
help="Output *.svg file.")
|
||||||
parser.add_argument(
|
|
||||||
'-q', '--quiet',
|
|
||||||
action='store_true',
|
|
||||||
help="Don't print info.")
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--trunk',
|
'--trunk',
|
||||||
type=lambda x: int(x, 0),
|
type=lambda x: int(x, 0),
|
||||||
help="Use this offset as the trunk of the mroots.")
|
help="Use this offset as the trunk of the mroots.")
|
||||||
# TODO adopt this in dbglfs.py for --ckdata?
|
|
||||||
parser.add_argument(
|
|
||||||
'--mtree-only',
|
|
||||||
action='store_true',
|
|
||||||
help="Only traverse the mtree.")
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-b', '--block-size',
|
'-b', '--block-size',
|
||||||
type=bdgeom,
|
type=bdgeom,
|
||||||
@@ -5768,6 +5769,15 @@ if __name__ == "__main__":
|
|||||||
if ',' in x
|
if ',' in x
|
||||||
else int(x, 0)),
|
else int(x, 0)),
|
||||||
help="Show a specific block, may be a range.")
|
help="Show a specific block, may be a range.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--mtree-only',
|
||||||
|
action='store_true',
|
||||||
|
help="Only traverse the mtree.")
|
||||||
|
parser.add_argument(
|
||||||
|
'-q', '--quiet',
|
||||||
|
action='store_true',
|
||||||
|
help="Don't print info.")
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-L', '--add-label',
|
'-L', '--add-label',
|
||||||
dest='labels',
|
dest='labels',
|
||||||
|
|||||||
+114
-21
@@ -1481,7 +1481,11 @@ class Mdir:
|
|||||||
return self.rbyd.gcksumdelta
|
return self.rbyd.gcksumdelta
|
||||||
|
|
||||||
def addr(self):
|
def addr(self):
|
||||||
return self.rbyd.addr()
|
if len(self.blocks) == 1:
|
||||||
|
return '0x%x' % self.block
|
||||||
|
else:
|
||||||
|
return '0x{%s}' % (
|
||||||
|
','.join('%x' % block for block in self.blocks))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s %s>' % (self.__class__.__name__, self.repr())
|
return '<%s %s>' % (self.__class__.__name__, self.repr())
|
||||||
@@ -4011,7 +4015,7 @@ TreeArt.fromfile = treeartfromfile
|
|||||||
|
|
||||||
|
|
||||||
# show the littlefs config
|
# show the littlefs config
|
||||||
def dbg_config(lfs,
|
def dbg_config(lfs, *,
|
||||||
color=False,
|
color=False,
|
||||||
w_width=2,
|
w_width=2,
|
||||||
**args):
|
**args):
|
||||||
@@ -4049,7 +4053,7 @@ def dbg_config(lfs,
|
|||||||
line))
|
line))
|
||||||
|
|
||||||
# show the littlefs gstate
|
# show the littlefs gstate
|
||||||
def dbg_gstate(lfs,
|
def dbg_gstate(lfs, *,
|
||||||
color=False,
|
color=False,
|
||||||
w_width=2,
|
w_width=2,
|
||||||
**args):
|
**args):
|
||||||
@@ -4115,7 +4119,7 @@ def dbg_gstate(lfs,
|
|||||||
line))
|
line))
|
||||||
|
|
||||||
# show the littlefs file tree
|
# show the littlefs file tree
|
||||||
def dbg_files(lfs, paths,
|
def dbg_files(lfs, paths, *,
|
||||||
color=False,
|
color=False,
|
||||||
w_width=2,
|
w_width=2,
|
||||||
recurse=None,
|
recurse=None,
|
||||||
@@ -4445,11 +4449,57 @@ def dbg_files(lfs, paths,
|
|||||||
for dir in dirs:
|
for dir in dirs:
|
||||||
dbg_dir(dir, recurse)
|
dbg_dir(dir, recurse)
|
||||||
|
|
||||||
|
# common ck function
|
||||||
|
def dbg_ck(lfs, *,
|
||||||
|
meta=True,
|
||||||
|
data=True,
|
||||||
|
mtree_only=False,
|
||||||
|
quiet=False,
|
||||||
|
color=False,
|
||||||
|
**args):
|
||||||
|
# lfs traverse does most of the work here
|
||||||
|
corrupted = False
|
||||||
|
for child in lfs.traverse(
|
||||||
|
mtree_only=mtree_only):
|
||||||
|
# limit to metadata blocks?
|
||||||
|
if (((meta and isinstance(child, (Mdir, Rbyd)))
|
||||||
|
or (data and isinstance(child, Bptr)))
|
||||||
|
and not child):
|
||||||
|
if not quiet:
|
||||||
|
print('%11s: %s%s%s' % (
|
||||||
|
'{%s}' % ','.join('%04x' % block
|
||||||
|
for block in child.blocks)
|
||||||
|
if isinstance(child, Mdir)
|
||||||
|
else '%04x.%04x' % (child.block, child.trunk)
|
||||||
|
if isinstance(child, Rbyd)
|
||||||
|
else '%04x.%04x' % (child.block, child.off),
|
||||||
|
'\x1b[31m' if color else '',
|
||||||
|
'(corrupted %s %s)' % (
|
||||||
|
'mroot' if isinstance(child, Mdir)
|
||||||
|
and child.mid == -1
|
||||||
|
else 'mdir' if isinstance(child, Mdir)
|
||||||
|
else 'rbyd' if isinstance(child, Rbyd)
|
||||||
|
else 'bptr',
|
||||||
|
child.addr()),
|
||||||
|
'\x1b[m' if color else ''))
|
||||||
|
corrupted = True
|
||||||
|
|
||||||
|
return not corrupted
|
||||||
|
|
||||||
|
# check metadata blocks for errors
|
||||||
|
def dbg_ckmeta(lfs, **args):
|
||||||
|
return dbg_ck(lfs, meta=True, **args)
|
||||||
|
|
||||||
|
# check metadata + data blocks for errors
|
||||||
|
def dbg_ckdata(lfs, **args):
|
||||||
|
return dbg_ck(lfs, meta=True, data=True, **args)
|
||||||
|
|
||||||
|
|
||||||
def main(disk, mroots=None, paths=None, *,
|
def main(disk, mroots=None, paths=None, *,
|
||||||
trunk=None,
|
trunk=None,
|
||||||
block_size=None,
|
block_size=None,
|
||||||
block_count=None,
|
block_count=None,
|
||||||
|
quiet=False,
|
||||||
color='auto',
|
color='auto',
|
||||||
**args):
|
**args):
|
||||||
# figure out what color should be
|
# figure out what color should be
|
||||||
@@ -4468,10 +4518,14 @@ def main(disk, mroots=None, paths=None, *,
|
|||||||
show_files = (args.get('files')
|
show_files = (args.get('files')
|
||||||
or args.get('structs')
|
or args.get('structs')
|
||||||
or args.get('attrs'))
|
or args.get('attrs'))
|
||||||
|
show_ckmeta = args.get('ckmeta')
|
||||||
|
show_ckdata = args.get('ckdata')
|
||||||
|
|
||||||
if (not show_config
|
if (not show_config
|
||||||
and not show_gstate
|
and not show_gstate
|
||||||
and not show_files):
|
and not show_files
|
||||||
|
and not show_ckmeta
|
||||||
|
and not show_ckdata):
|
||||||
show_files = True
|
show_files = True
|
||||||
|
|
||||||
# is bd geometry specified?
|
# is bd geometry specified?
|
||||||
@@ -4507,17 +4561,20 @@ def main(disk, mroots=None, paths=None, *,
|
|||||||
lfs = Lfs.fetch(bd, mroots, trunk)
|
lfs = Lfs.fetch(bd, mroots, trunk)
|
||||||
|
|
||||||
# print some information about the filesystem
|
# print some information about the filesystem
|
||||||
print('littlefs%s v%s.%s %sx%s %s w%s.%s, rev %08x, cksum %08x%s' % (
|
if not quiet:
|
||||||
'' if lfs.ckmagic() else '?',
|
print('littlefs%s v%s.%s %sx%s %s w%s.%s, '
|
||||||
lfs.version.major if lfs.version is not None else '?',
|
'rev %08x, '
|
||||||
lfs.version.minor if lfs.version is not None else '?',
|
'cksum %08x%s' % (
|
||||||
lfs.block_size if lfs.block_size is not None else '?',
|
'' if lfs.ckmagic() else '?',
|
||||||
lfs.block_count if lfs.block_count is not None else '?',
|
lfs.version.major if lfs.version is not None else '?',
|
||||||
lfs.addr(),
|
lfs.version.minor if lfs.version is not None else '?',
|
||||||
lfs.mbweightrepr(), lfs.mrweightrepr(),
|
lfs.block_size if lfs.block_size is not None else '?',
|
||||||
lfs.rev,
|
lfs.block_count if lfs.block_count is not None else '?',
|
||||||
lfs.cksum,
|
lfs.addr(),
|
||||||
'' if lfs.ckcksum() else '?'))
|
lfs.mbweightrepr(), lfs.mrweightrepr(),
|
||||||
|
lfs.rev,
|
||||||
|
lfs.cksum,
|
||||||
|
'' if lfs.ckcksum() else '?'))
|
||||||
|
|
||||||
# dynamically size the id field
|
# dynamically size the id field
|
||||||
w_width = max(
|
w_width = max(
|
||||||
@@ -4528,30 +4585,50 @@ def main(disk, mroots=None, paths=None, *,
|
|||||||
2)
|
2)
|
||||||
|
|
||||||
# show the on-disk config?
|
# show the on-disk config?
|
||||||
if show_config:
|
if show_config and not quiet:
|
||||||
dbg_config(lfs,
|
dbg_config(lfs,
|
||||||
color=color,
|
color=color,
|
||||||
w_width=w_width,
|
w_width=w_width,
|
||||||
**args)
|
**args)
|
||||||
|
|
||||||
# show the on-disk gstate?
|
# show the on-disk gstate?
|
||||||
if show_gstate:
|
if show_gstate and not quiet:
|
||||||
dbg_gstate(lfs,
|
dbg_gstate(lfs,
|
||||||
color=color,
|
color=color,
|
||||||
w_width=w_width,
|
w_width=w_width,
|
||||||
**args)
|
**args)
|
||||||
|
|
||||||
# show the on-disk file tree?
|
# show the on-disk file tree?
|
||||||
if show_files:
|
if show_files and not quiet:
|
||||||
dbg_files(lfs, paths,
|
dbg_files(lfs, paths,
|
||||||
color=color,
|
color=color,
|
||||||
w_width=w_width,
|
w_width=w_width,
|
||||||
**args)
|
**args)
|
||||||
|
|
||||||
# is the filesystem corrupt?
|
# always check magic/gcksum
|
||||||
corrupted = not bool(lfs)
|
corrupted = not bool(lfs)
|
||||||
|
|
||||||
if args.get('error_on_corrupt') and corrupted:
|
# check metadata blocks for errors
|
||||||
|
if show_ckmeta and not show_ckdata:
|
||||||
|
if not dbg_ckmeta(lfs,
|
||||||
|
quiet=quiet,
|
||||||
|
color=color,
|
||||||
|
w_width=w_width,
|
||||||
|
**args):
|
||||||
|
corrupted = True
|
||||||
|
|
||||||
|
# check metadata + data blocks for errors
|
||||||
|
if show_ckdata:
|
||||||
|
if not dbg_ckdata(lfs,
|
||||||
|
quiet=quiet,
|
||||||
|
color=color,
|
||||||
|
w_width=w_width,
|
||||||
|
**args):
|
||||||
|
corrupted = True
|
||||||
|
|
||||||
|
# ckmeta/ckdata implies error_on_corrupt
|
||||||
|
if ((show_ckmeta or show_ckdata or args.get('error_on_corrupt'))
|
||||||
|
and corrupted):
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
@@ -4602,6 +4679,10 @@ if __name__ == "__main__":
|
|||||||
'--block-count',
|
'--block-count',
|
||||||
type=lambda x: int(x, 0),
|
type=lambda x: int(x, 0),
|
||||||
help="Block count in blocks.")
|
help="Block count in blocks.")
|
||||||
|
parser.add_argument(
|
||||||
|
'-q', '--quiet',
|
||||||
|
action='store_true',
|
||||||
|
help="Don't show anything, useful when checking for errors.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--color',
|
'--color',
|
||||||
choices=['never', 'always', 'auto'],
|
choices=['never', 'always', 'auto'],
|
||||||
@@ -4632,6 +4713,18 @@ if __name__ == "__main__":
|
|||||||
'--attrs',
|
'--attrs',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help="Show custom attributes attached to files. Implies --files.")
|
help="Show custom attributes attached to files. Implies --files.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--ckmeta',
|
||||||
|
action='store_true',
|
||||||
|
help="Check metadata blocks for errors.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--ckdata',
|
||||||
|
action='store_true',
|
||||||
|
help="Check metadata + data blocks for errors.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--mtree-only',
|
||||||
|
action='store_true',
|
||||||
|
help="Only traverse the mtree.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-r', '--recurse', '--file-depth',
|
'-r', '--recurse', '--file-depth',
|
||||||
nargs='?',
|
nargs='?',
|
||||||
|
|||||||
+5
-1
@@ -1447,7 +1447,11 @@ class Mdir:
|
|||||||
return self.rbyd.gcksumdelta
|
return self.rbyd.gcksumdelta
|
||||||
|
|
||||||
def addr(self):
|
def addr(self):
|
||||||
return self.rbyd.addr()
|
if len(self.blocks) == 1:
|
||||||
|
return '0x%x' % self.block
|
||||||
|
else:
|
||||||
|
return '0x{%s}' % (
|
||||||
|
','.join('%x' % block for block in self.blocks))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s %s>' % (self.__class__.__name__, self.repr())
|
return '<%s %s>' % (self.__class__.__name__, self.repr())
|
||||||
|
|||||||
Reference in New Issue
Block a user