summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-06-05 20:31:46 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-06-05 20:31:46 -0600
commit9c0f3db2bc6bb9fa63542194eda91fab304a6b86 (patch)
tree322f7e5c84fac6ae420328dc2a41c6f28712c2af
parente10943ca04c06e54777447c2b81a3736befd68cd (diff)
wip fsck
-rw-r--r--cmd/btrfs-fsck.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/cmd/btrfs-fsck.go b/cmd/btrfs-fsck.go
new file mode 100644
index 0000000..8f48430
--- /dev/null
+++ b/cmd/btrfs-fsck.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "lukeshu.com/btrfs-tools/pkg/btrfs"
+ "lukeshu.com/btrfs-tools/pkg/btrfsmisc"
+ "lukeshu.com/btrfs-tools/pkg/util"
+)
+
+func main() {
+ if err := Main(os.Args[1]); err != nil {
+ fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err)
+ os.Exit(1)
+ }
+}
+
+func Main(imgfilename string) (err error) {
+ maybeSetErr := func(_err error) {
+ if _err != nil && err == nil {
+ err = _err
+ }
+ }
+
+ fh, err := os.Open(imgfilename)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ maybeSetErr(fh.Close())
+ }()
+ fs := &btrfs.FS{
+ Devices: []*btrfs.Device{
+ {
+ File: fh,
+ },
+ },
+ }
+
+ superblock, err := fs.Superblock()
+ if err != nil {
+ return fmt.Errorf("superblock: %w", err)
+ }
+
+ if err := fs.Init(); err != nil {
+ fmt.Printf("init chunk tree: error: %v\n", err)
+ }
+
+ foundNodes := make(map[btrfs.LogicalAddr]struct{})
+
+ if err := btrfsmisc.ScanForNodes(fs.Devices[0], superblock.Data, func(nodeRef *util.Ref[btrfs.PhysicalAddr, btrfs.Node], err error) {
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ foundNodes[nodeRef.Data.Head.Addr] = struct{}{}
+ fmt.Printf("node@%d: physical_addr=0x%0X logical_addr=0x%0X generation=%d owner=%v level=%d\n",
+ nodeRef.Addr,
+ nodeRef.Addr, nodeRef.Data.Head.Addr,
+ nodeRef.Data.Head.Generation, nodeRef.Data.Head.Owner, nodeRef.Data.Head.Level)
+ srcPaddr := btrfs.QualifiedPhysicalAddr{
+ Dev: superblock.Data.DevItem.DevUUID,
+ Addr: nodeRef.Addr,
+ }
+ resPaddrs, _ := fs.Resolve(nodeRef.Data.Head.Addr)
+ if len(resPaddrs) == 0 {
+ fmt.Printf("node@%d: logical_addr=0x%0X is not mapped\n",
+ nodeRef.Addr, nodeRef.Data.Head.Addr)
+ } else if _, ok := resPaddrs[srcPaddr]; !ok {
+ fmt.Printf("node@%d: logical_addr=0x%0X maps to %v, not %v\n",
+ nodeRef.Addr, nodeRef.Data.Head.Addr, resPaddrs, srcPaddr)
+ }
+ }); err != nil {
+ return err
+ }
+
+ return nil
+}