diff options
-rw-r--r-- | cmd/btrfs-fsck/pass1.go | 24 | ||||
-rw-r--r-- | pkg/btrfs/crc32c.go | 2 | ||||
-rw-r--r-- | pkg/btrfs/types_btree.go | 48 |
3 files changed, 46 insertions, 28 deletions
diff --git a/cmd/btrfs-fsck/pass1.go b/cmd/btrfs-fsck/pass1.go index 97129cd..378c88d 100644 --- a/cmd/btrfs-fsck/pass1.go +++ b/cmd/btrfs-fsck/pass1.go @@ -170,16 +170,16 @@ func pass1ReconstructChunksOneDev( LAddr btrfs.LogicalAddr Size uint64 } - var stripes []stripe + var stripes []*stripe for _, paddr := range sortedPaddrs { var lastStripe *stripe if len(stripes) > 0 { - lastStripe = &stripes[len(stripes)-1] + lastStripe = stripes[len(stripes)-1] } if lastStripe != nil && (lastStripe.PAddr+btrfs.PhysicalAddr(lastStripe.Size)) == paddr { lastStripe.Size += uint64(superblock.Data.NodeSize) } else { - stripes = append(stripes, stripe{ + stripes = append(stripes, &stripe{ PAddr: paddr, LAddr: lostAndFoundNodes[paddr], Size: uint64(superblock.Data.NodeSize), @@ -242,6 +242,7 @@ func pass1WriteReconstructedChunks( }, }, } + for _, dev := range fs.Devices { superblock, _ := dev.Superblock() reconstructedNode.Data.BodyLeaf = append(reconstructedNode.Data.BodyLeaf, btrfs.Item{ @@ -255,7 +256,20 @@ func pass1WriteReconstructedChunks( Body: superblock.Data.DevItem, }) } - for laddr, chunk := range fsReconstructedChunks { + + sortedLAddrs := make([]btrfs.LogicalAddr, 0, len(fsReconstructedChunks)) + for laddr := range fsReconstructedChunks { + sortedLAddrs = append(sortedLAddrs, laddr) + } + sort.Slice(sortedLAddrs, func(i, j int) bool { + return sortedLAddrs[i] < sortedLAddrs[j] + }) + for i, laddr := range sortedLAddrs { + chunk := fsReconstructedChunks[laddr] + for j, stripe := range chunk.Stripes { + fmt.Printf("Pass 1: chunk[%d].stripe[%d] = { laddr=0x%0x ⇒ { dev_id=%v, paddr=0x%0x }, size=0x%0x }\n", + i, j, laddr, stripe.DeviceID, stripe.Offset, chunk.Size) + } reconstructedNode.Data.BodyLeaf = append(reconstructedNode.Data.BodyLeaf, btrfs.Item{ Head: btrfs.ItemHeader{ Key: btrfs.Key{ @@ -280,11 +294,13 @@ func pass1WriteReconstructedChunks( }, }) } + var err error reconstructedNode.Data.Head.Checksum, err = reconstructedNode.Data.CalculateChecksum() if err != nil { fmt.Printf("Pass 1: ... new node checksum: error: %v\n", err) } + if err := reconstructedNode.Write(); err != nil { fmt.Printf("Pass 1: ... write new node: error: %v\n", err) } diff --git a/pkg/btrfs/crc32c.go b/pkg/btrfs/crc32c.go index 8266706..ab2d6e9 100644 --- a/pkg/btrfs/crc32c.go +++ b/pkg/btrfs/crc32c.go @@ -9,7 +9,7 @@ import ( type CSum [0x20]byte func (csum CSum) String() string { - return fmt.Sprintf("%x", csum) + return fmt.Sprintf("%x", [0x20]byte(csum)) } func CRC32c(data []byte) CSum { diff --git a/pkg/btrfs/types_btree.go b/pkg/btrfs/types_btree.go index f72be96..734c859 100644 --- a/pkg/btrfs/types_btree.go +++ b/pkg/btrfs/types_btree.go @@ -204,7 +204,7 @@ func (node *Node) marshalInternalTo(bodyBuf []byte) error { } if copy(bodyBuf[n:], bs) < len(bs) { return fmt.Errorf("item %d: not enough space: need at least %d+%d=%d bytes, but only have %d", - n, len(bs), n+len(bs), len(bodyBuf)) + i, n, len(bs), n+len(bs), len(bodyBuf)) } n += len(bs) } @@ -346,7 +346,7 @@ func ReadNode[Addr ~int64](fs util.File[Addr], sb Superblock, addr Addr, laddrCB if laddrCB != nil { if err := laddrCB(nodeRef.Data.Head.Addr); err != nil { - return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%d: %w", err) + return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%d: %w", addr, err) } } @@ -410,34 +410,36 @@ func (fs *FS) WalkTree(nodeAddr LogicalAddr, cbs WalkTreeHandler) error { } return fmt.Errorf("btrfs.FS.WalkTree: %w", err) } - for _, item := range node.Data.BodyInternal { - if cbs.PreKeyPointer != nil { - if err := cbs.PreKeyPointer(item); err != nil { - if errors.Is(err, iofs.SkipDir) { - continue + if node != nil { + for _, item := range node.Data.BodyInternal { + if cbs.PreKeyPointer != nil { + if err := cbs.PreKeyPointer(item); err != nil { + if errors.Is(err, iofs.SkipDir) { + continue + } + return err } + } + if err := fs.WalkTree(item.BlockPtr, cbs); err != nil { return err } - } - if err := fs.WalkTree(item.BlockPtr, cbs); err != nil { - return err - } - if cbs.PostKeyPointer != nil { - if err := cbs.PostKeyPointer(item); err != nil { - if errors.Is(err, iofs.SkipDir) { - continue + if cbs.PostKeyPointer != nil { + if err := cbs.PostKeyPointer(item); err != nil { + if errors.Is(err, iofs.SkipDir) { + continue + } + return err } - return err } } - } - for _, item := range node.Data.BodyLeaf { - if cbs.Item != nil { - if err := cbs.Item(item.Head.Key, item.Body); err != nil { - if errors.Is(err, iofs.SkipDir) { - continue + for _, item := range node.Data.BodyLeaf { + if cbs.Item != nil { + if err := cbs.Item(item.Head.Key, item.Body); err != nil { + if errors.Is(err, iofs.SkipDir) { + continue + } + return fmt.Errorf("btrfs.FS.WalkTree: callback: %w", err) } - return fmt.Errorf("btrfs.FS.WalkTree: callback: %w", err) } } } |