scripts: dbgmtree.py: Fixed minor mtree rendering/traversal issues

- Added TreeArt __bool__ and __len__.

  This was causing a crash in _treeartfrommtreertree when rtree was
  empty.

  The code was not updated in the set -> TreeArt class transition, and
  went unnoticed because it's unlikely to be hit unless the filesystem
  is corrupt.

  Fortunately(?) realtime rendering creates a bunch of transiently
  corrupt filesystem images.

- Tweaked lookupleaf to not include mroots in their own paths.

  This matches the behavior of leaf mdirs, and is intentionally
  different from btree's lookupleaf which needs to lookup the leaf rattr
  to terminate.

- Tweaked leaves to not remove the last path entry if it is an mdir.

  This hid the previous lookupleaf inconsistency. We only remove the
  last rbyd from the path because it is redundant, and for mdirs/mroots
  it should never be redundant.

  I ended up just replacing the corrupt check with an explicit check
  that the rbyd is redundant. This should be more precise and avoid
  issues like this in the future.

  Also adopted explicit redundant checks in Btree.leaves and
  Lfs.File.leaves.
This commit is contained in:
Christopher Haster
2025-04-12 17:45:26 -05:00
parent 71930a5c01
commit a5747bb2b2
6 changed files with 108 additions and 37 deletions

View File

@@ -1203,7 +1203,9 @@ class Btree:
if path:
yield (bid-rid + (rbyd.weight-1), rbyd,
# path tail is usually redundant unless corrupt
path_[:-1] if rbyd else path_)
path_[:-1]
if path_ and path_[-1][1] == rbyd
else path_)
else:
yield bid-rid + (rbyd.weight-1), rbyd
bid += rbyd.weight - rid + 1
@@ -1754,8 +1756,6 @@ class Mtree:
# iterate over mrootchain
path_ = []
for mroot in self.mrootchain:
name = mroot.lookup(-1, TAG_MAGIC)
path_.append((mroot.mid, mroot, name))
# stop here?
if depth and len(path_) >= depth:
if path:
@@ -1763,6 +1763,9 @@ class Mtree:
else:
return mroot
name = mroot.lookup(-1, TAG_MAGIC)
path_.append((mroot.mid, mroot, name))
# no mtree? must be inlined in mroot
if self.mtree is None:
if mid.mbid >= (1 << self.mbits):
@@ -1903,12 +1906,13 @@ class Mtree:
yield mroot
if path or depth:
name = mroot.lookup(-1, TAG_MAGIC)
path_.append((mroot.mid, mroot, name))
# stop here?
if depth and len(path_) >= depth:
return
name = mroot.lookup(-1, TAG_MAGIC)
path_.append((mroot.mid, mroot, name))
# do we even have an mtree?
if self.mtree is not None:
# include the mtree root even if the weight is zero
@@ -1945,7 +1949,11 @@ class Mtree:
if path:
yield ((bid-rid + (rbyd.weight-1), rbyd),
# path tail is usually redundant unless corrupt
path_[:-1] if rbyd else path_)
path_[:-1]
if path_
and isinstance(path_[-1][1], Rbyd)
and path_[-1][1] == rbyd
else path_)
else:
yield (bid-rid + (rbyd.weight-1), rbyd)
mid = self.mid(bid-rid + (rbyd.weight-1) + 1)
@@ -2128,8 +2136,6 @@ class Mtree:
# iterate over mrootchain
path_ = []
for mroot in self.mrootchain:
name = mroot.lookup(-1, TAG_MAGIC)
path_.append((mroot.mid, mroot, name))
# stop here?
if depth and len(path_) >= depth:
if path:
@@ -2137,6 +2143,9 @@ class Mtree:
else:
return mroot
name = mroot.lookup(-1, TAG_MAGIC)
path_.append((mroot.mid, mroot, name))
# no mtree? must be inlined in mroot
if self.mtree is None:
mdir = Mdir(0, self.mroot)
@@ -3423,7 +3432,9 @@ class Lfs:
if path:
yield (pos, rbyd,
# path tail is usually redundant unless corrupt
path_[:-1] if rbyd else path_)
path_[:-1]
if path_ and path_[-1][1] == rbyd
else path_)
else:
yield pos, rbyd
pos += rbyd.weight