summaryrefslogtreecommitdiff
path: root/pkg/btrfs
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-05-25 19:41:31 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-05-25 19:41:31 -0600
commitf11acf5f5a8c72af59712cf3cda62c47d1a80e5d (patch)
tree1b5a7a0056de5a39ae6197e6895ae5312e46af89 /pkg/btrfs
parent90c58d14d28729aa5cae8b7d1306177553b46314 (diff)
load the chunk tree
Diffstat (limited to 'pkg/btrfs')
-rw-r--r--pkg/btrfs/io_fs.go59
-rw-r--r--pkg/btrfs/types_structs.go6
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"`
}