diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-05-25 19:41:31 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-05-25 19:41:31 -0600 |
commit | f11acf5f5a8c72af59712cf3cda62c47d1a80e5d (patch) | |
tree | 1b5a7a0056de5a39ae6197e6895ae5312e46af89 /pkg/btrfs | |
parent | 90c58d14d28729aa5cae8b7d1306177553b46314 (diff) |
load the chunk tree
Diffstat (limited to 'pkg/btrfs')
-rw-r--r-- | pkg/btrfs/io_fs.go | 59 | ||||
-rw-r--r-- | pkg/btrfs/types_structs.go | 6 |
2 files changed, 57 insertions, 8 deletions
diff --git a/pkg/btrfs/io_fs.go b/pkg/btrfs/io_fs.go index 5dee6dc..4f52d86 100644 --- a/pkg/btrfs/io_fs.go +++ b/pkg/btrfs/io_fs.go @@ -81,7 +81,7 @@ func (fs *FS) Superblock() (ret Ref[PhysicalAddr, Superblock], err error) { return sbs[0], nil } -func (fs *FS) init() error { +func (fs *FS) Init() error { if fs.uuid2dev != nil { return fs.initErr } @@ -121,6 +121,28 @@ func (fs *FS) init() error { for _, chunk := range syschunks { fs.chunks = append(fs.chunks, chunk) } + if err := fs.WalkTree(sb.Data.ChunkTree, func(key Key, dat []byte) error { + pair := SysChunk{ + Key: key, + } + if err := binstruct.Unmarshal(dat, &pair.Chunk); err != nil { + return err + } + dat = dat[0x30:] + for i := 0; i < int(pair.Chunk.NumStripes); i++ { + var stripe Stripe + if err := binstruct.Unmarshal(dat, &stripe); err != nil { + return err + } + pair.Chunk.Stripes = append(pair.Chunk.Stripes, stripe) + dat = dat[0x20:] + } + fs.chunks = append(fs.chunks, pair) + return nil + }); err != nil { + fs.initErr = err + return fs.initErr + } } return nil } @@ -138,10 +160,6 @@ func (fs *FS) ReadAt(dat []byte, laddr LogicalAddr) (int, error) { } func (fs *FS) maybeShortReadAt(dat []byte, laddr LogicalAddr) (int, error) { - if err := fs.init(); err != nil { - return 0, err - } - type physicalAddr struct { Dev UUID Addr PhysicalAddr @@ -209,6 +227,11 @@ func (fs *FS) ReadNode(addr LogicalAddr) (Node, error) { return nil, fmt.Errorf("node@%d: does not look like a node", addr) } + if nodeHeader.Addr != addr { + return nil, fmt.Errorf("node@%d: read from laddr=%d but claims to be at laddr=%d", + addr, addr, nodeHeader.Addr) + } + stored := nodeHeader.Checksum calced := CRC32c(nodeBuf[0x20:]) if !calced.Equal(stored) { @@ -275,3 +298,29 @@ func (fs *FS) ReadNode(addr LogicalAddr) (Node, error) { return ret, nil } } + +func (fs *FS) WalkTree(nodeAddr LogicalAddr, fn func(Key, []byte) error) error { + if nodeAddr == 0 { + return nil + } + node, err := fs.ReadNode(nodeAddr) + if err != nil { + return err + } + switch node := node.(type) { + case *InternalNode: + for _, item := range node.Body { + // fn(item.Data.Key, TODO) + if err := fs.WalkTree(item.Data.BlockPtr, fn); err != nil { + return err + } + } + case *LeafNode: + for _, item := range node.Body { + if err := fn(item.Data.Key, item.Data.Data.Data); err != nil { + return err + } + } + } + return nil +} diff --git a/pkg/btrfs/types_structs.go b/pkg/btrfs/types_structs.go index f96c20a..22e3f73 100644 --- a/pkg/btrfs/types_structs.go +++ b/pkg/btrfs/types_structs.go @@ -226,9 +226,9 @@ func (in *InternalNode) GetNodeHeader() Ref[LogicalAddr, NodeHeader] { } type KeyPointer struct { - Key Key `bin:"off=0, siz=11"` - BlockNumber uint64 `bin:"off=11, siz=8"` - Generation Generation `bin:"off=19, siz=8"` + Key Key `bin:"off=0, siz=11"` + BlockPtr LogicalAddr `bin:"off=11, siz=8"` + Generation Generation `bin:"off=19, siz=8"` binstruct.End `bin:"off=21"` } |