diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/btrfs-fsck/main.go | 43 | ||||
-rw-r--r-- | cmd/btrfs-fsck/pass0.go | 31 | ||||
-rw-r--r-- | cmd/btrfs-fsck/pass1.go | 163 | ||||
-rw-r--r-- | cmd/btrfs-fsck/pass2.go | 68 |
4 files changed, 0 insertions, 305 deletions
diff --git a/cmd/btrfs-fsck/main.go b/cmd/btrfs-fsck/main.go deleted file mode 100644 index e4e2b25..0000000 --- a/cmd/btrfs-fsck/main.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com> -// -// SPDX-License-Identifier: GPL-2.0-or-later - -package main - -import ( - "context" - "fmt" - "os" -) - -func main() { - if err := Main(context.Background(), os.Args[1:]...); err != nil { - fmt.Fprintf(os.Stderr, "%v: error: %v\n", os.Args[0], err) - os.Exit(1) - } -} - -func Main(ctx context.Context, imgfilenames ...string) (err error) { - maybeSetErr := func(_err error) { - if _err != nil && err == nil { - err = _err - } - } - - fs, sb, err := pass0(ctx, imgfilenames...) - if err != nil { - return err - } - defer func() { - maybeSetErr(fs.Close()) - }() - - foundNodes, err := pass1(ctx, fs, sb) - if err != nil { - return err - } - - pass2(ctx, fs, foundNodes) - - return nil -} diff --git a/cmd/btrfs-fsck/pass0.go b/cmd/btrfs-fsck/pass0.go deleted file mode 100644 index fc087e5..0000000 --- a/cmd/btrfs-fsck/pass0.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com> -// -// SPDX-License-Identifier: GPL-2.0-or-later - -package main - -import ( - "context" - "fmt" - "os" - - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsutil" -) - -func pass0(ctx context.Context, filenames ...string) (*btrfs.FS, *btrfs.Superblock, error) { - fmt.Printf("\nPass 0: init and superblocks...\n") - - fs, err := btrfsutil.Open(ctx, os.O_RDWR, filenames...) - if err != nil { - return nil, nil, err - } - - sb, err := fs.Superblock() - if err != nil { - _ = fs.Close() - return nil, nil, err - } - - return fs, sb, nil -} diff --git a/cmd/btrfs-fsck/pass1.go b/cmd/btrfs-fsck/pass1.go deleted file mode 100644 index e22cebd..0000000 --- a/cmd/btrfs-fsck/pass1.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com> -// -// SPDX-License-Identifier: GPL-2.0-or-later - -package main - -import ( - "context" - "fmt" - "os" - - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsitem" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsinspect" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsutil" - "git.lukeshu.com/btrfs-progs-ng/lib/diskio" -) - -func pass1(ctx context.Context, fs *btrfs.FS, superblock *btrfs.Superblock) (map[btrfsvol.LogicalAddr]struct{}, error) { - fmt.Printf("\nPass 1: chunk mappings...\n") - - fmt.Printf("Pass 1: ... walking fs\n") - visitedNodes := make(map[btrfsvol.LogicalAddr]struct{}) - btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ - TreeWalkHandler: btrfs.TreeWalkHandler{ - Node: func(path btrfs.TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, btrfs.Node]) error { - visitedNodes[node.Addr] = struct{}{} - return nil - }, - }, - Err: func(err *btrfsutil.WalkError) { - fmt.Printf("Pass 1: ... walk fs: error: %v\n", err) - }, - }) - - fsFoundNodes := make(map[btrfsvol.LogicalAddr]struct{}) - for _, dev := range fs.LV.PhysicalVolumes() { - fmt.Printf("Pass 1: ... dev[%q] scanning for nodes...\n", dev.Name()) - devResult, err := btrfsinspect.ScanOneDevice(ctx, dev, *superblock) - if err != nil { - return nil, err - } - - fmt.Printf("Pass 1: ... dev[%q] re-inserting lost+found mappings\n", dev.Name()) - devResult.AddToLV(ctx, fs, dev) - - // merge those results in to the total-fs results - for laddr := range devResult.FoundNodes { - fsFoundNodes[laddr] = struct{}{} - } - } - - fmt.Printf("Pass 1: ... logical address space:\n") - btrfsinspect.PrintLogicalSpace(os.Stdout, fs) - fmt.Printf("Pass 1: ... physical address space:\n") - btrfsinspect.PrintPhysicalSpace(os.Stdout, fs) - - fmt.Printf("Pass 1: ... writing re-constructed chunks\n") - pass1WriteReconstructedChunks(ctx, fs) - - return fsFoundNodes, nil -} - -func pass1WriteReconstructedChunks(ctx context.Context, fs *btrfs.FS) { - superblock, _ := fs.Superblock() - - // FIXME(lukeshu): OK, so this just assumes that all the - // reconstructed stripes fit in one node, and that we can just - // store that node at the root node of the chunk tree. This - // isn't true in general, but it's true of my particular - // filesystem. - reconstructedNode := &diskio.Ref[btrfsvol.LogicalAddr, btrfs.Node]{ - File: fs, - Addr: superblock.ChunkTree, - Data: btrfs.Node{ - Size: superblock.NodeSize, - Head: btrfs.NodeHeader{ - MetadataUUID: superblock.EffectiveMetadataUUID(), - Addr: superblock.ChunkTree, - Flags: btrfs.NodeWritten, - //BackrefRef: ???, - //ChunkTreeUUID: ???, - Generation: superblock.ChunkRootGeneration, - Owner: btrfs.CHUNK_TREE_OBJECTID, - Level: 0, - }, - }, - } - - for _, dev := range fs.LV.PhysicalVolumes() { - superblock, _ := dev.Superblock() - reconstructedNode.Data.BodyLeaf = append(reconstructedNode.Data.BodyLeaf, btrfs.Item{ - Key: btrfs.Key{ - ObjectID: btrfs.DEV_ITEMS_OBJECTID, - ItemType: btrfsitem.DEV_ITEM_KEY, - Offset: uint64(superblock.DevItem.DevID), - }, - Body: superblock.DevItem, - }) - } - - for _, mapping := range fs.LV.Mappings() { - chunkIdx := len(reconstructedNode.Data.BodyLeaf) - 1 - if len(reconstructedNode.Data.BodyLeaf) == 0 || reconstructedNode.Data.BodyLeaf[chunkIdx].Key.Offset != uint64(mapping.LAddr) { - reconstructedNode.Data.BodyLeaf = append(reconstructedNode.Data.BodyLeaf, btrfs.Item{ - Key: btrfs.Key{ - ObjectID: btrfs.FIRST_CHUNK_TREE_OBJECTID, - ItemType: btrfsitem.CHUNK_ITEM_KEY, - Offset: uint64(mapping.LAddr), - }, - Body: btrfsitem.Chunk{ - Head: btrfsitem.ChunkHeader{ - Size: mapping.Size, - Owner: btrfs.EXTENT_TREE_OBJECTID, - StripeLen: 65536, // ??? - Type: mapping.Flags.Val, - IOOptimalAlign: superblock.DevItem.IOOptimalAlign, - IOOptimalWidth: superblock.DevItem.IOOptimalWidth, - IOMinSize: superblock.DevItem.IOMinSize, - SubStripes: 1, - }, - }, - }) - chunkIdx++ - } - dev := fs.LV.PhysicalVolumes()[mapping.PAddr.Dev] - devSB, _ := dev.Superblock() - chunkBody := reconstructedNode.Data.BodyLeaf[chunkIdx].Body.(btrfsitem.Chunk) - chunkBody.Stripes = append(chunkBody.Stripes, btrfsitem.ChunkStripe{ - DeviceID: mapping.PAddr.Dev, - Offset: mapping.PAddr.Addr, - DeviceUUID: devSB.DevItem.DevUUID, - }) - reconstructedNode.Data.BodyLeaf[chunkIdx].Body = chunkBody - } - - 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) - } - - if err := fs.ReInit(ctx); err != nil { - fmt.Printf("Pass 1: ... re-init mappings: %v\n", err) - } - - sbs, _ := fs.Superblocks() - for i, sb := range sbs { - sb.Data.ChunkLevel = reconstructedNode.Data.Head.Level - sb.Data.Checksum, err = sb.Data.CalculateChecksum() - if err != nil { - fmt.Printf("Pass 1: ... calculate superblock %d checksum: %v\n", i, err) - } - if err := sb.Write(); err != nil { - fmt.Printf("Pass 1: ... write superblock %d: %v\n", i, err) - } - } -} diff --git a/cmd/btrfs-fsck/pass2.go b/cmd/btrfs-fsck/pass2.go deleted file mode 100644 index e71cd84..0000000 --- a/cmd/btrfs-fsck/pass2.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2022 Luke Shumaker <lukeshu@lukeshu.com> -// -// SPDX-License-Identifier: GPL-2.0-or-later - -package main - -import ( - "context" - "fmt" - - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" - "git.lukeshu.com/btrfs-progs-ng/lib/btrfsprogs/btrfsutil" - "git.lukeshu.com/btrfs-progs-ng/lib/diskio" -) - -func pass2(ctx context.Context, fs *btrfs.FS, foundNodes map[btrfsvol.LogicalAddr]struct{}) { - fmt.Printf("\nPass 2: orphaned nodes\n") - - visitedNodes := make(map[btrfsvol.LogicalAddr]struct{}) - btrfsutil.WalkAllTrees(ctx, fs, btrfsutil.WalkAllTreesHandler{ - TreeWalkHandler: btrfs.TreeWalkHandler{ - Node: func(path btrfs.TreePath, node *diskio.Ref[btrfsvol.LogicalAddr, btrfs.Node]) error { - visitedNodes[node.Addr] = struct{}{} - return nil - }, - }, - Err: func(err *btrfsutil.WalkError) { - fmt.Printf("Pass 2: walk FS: error: %v\n", err) - }, - }) - - orphanedNodes := make(map[btrfsvol.LogicalAddr]int) - for foundNode := range foundNodes { - if _, visited := visitedNodes[foundNode]; !visited { - orphanedNodes[foundNode] = 0 - } - } - - orphanedRoots := make(map[btrfsvol.LogicalAddr]struct{}, len(orphanedNodes)) - for node := range orphanedNodes { - orphanedRoots[node] = struct{}{} - } - /* - for potentialRoot := range orphanedRoots { - if err := fs.TreeWalk(potentialRoot, btrfs.TreeWalkHandler{ - Node: func(path btrfs.TreePath, _ *diskio.Ref[btrfsvol.LogicalAddr, btrfs.Node], _ error) error { - nodeAddr := path[len(path)-1].NodeAddr - if nodeAddr != potentialRoot { - delete(orphanedRoots, nodeAddr) - } - orphanedNodes[nodeAddr] = orphanedNodes[nodeAddr] + 1 - visitCnt := orphanedNodes[nodeAddr] - if visitCnt > 1 { - return iofs.SkipDir - } - return nil - }, - }); err != nil { - fmt.Printf("Pass 2: walk orphans: error: %v\n", err) - } - } - - for _, node := range maps.SortedKeys(orphanedRoots) { - fmt.Printf("Pass 2: orphaned root: %v\n", node) - } - */ -} |