diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/btrfs/btrfstree/types_node.go | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/lib/btrfs/btrfstree/types_node.go b/lib/btrfs/btrfstree/types_node.go index 48a065d..58dc8e5 100644 --- a/lib/btrfs/btrfstree/types_node.go +++ b/lib/btrfs/btrfstree/types_node.go @@ -408,7 +408,7 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, err) } - // sanity checking + // sanity checking (that prevents the main parse) if nodeRef.Data.Head.MetadataUUID != sb.EffectiveMetadataUUID() { return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, ErrNotANode) @@ -424,6 +424,23 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N addr, stored, calced) } + // parse (main) + // + // If the above sanity checks passed, then this is at least + // node data *that got written by the filesystem*. If it's + // invalid (the remaining sanity checks don't pass), it's + // because of something the running filesystem code did; the + // bits are probably useful to poke at, so parse them. + // Whereas if the above check didn't pass, then this is just + // garbage data that is was never a valid node, so parsing it + // isn't useful. + + if _, err := binstruct.Unmarshal(nodeBuf, &nodeRef.Data); err != nil { + return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, err) + } + + // sanity checking (that doesn't prevent parsing) + if exp.LAddr.OK && nodeRef.Data.Head.Addr != exp.LAddr.Val { return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: read from laddr=%v but claims to be at laddr=%v", addr, exp.LAddr.Val, nodeRef.Data.Head.Addr) @@ -442,12 +459,6 @@ func ReadNode[Addr ~int64](fs diskio.File[Addr], sb Superblock, addr Addr, exp N } } - // parse (main) - - if _, err := binstruct.Unmarshal(nodeBuf, &nodeRef.Data); err != nil { - return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, err) - } - // return return nodeRef, nil |