summaryrefslogtreecommitdiff
path: root/lib/btrfsutil/listnodes.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/btrfsutil/listnodes.go')
-rw-r--r--lib/btrfsutil/listnodes.go66
1 files changed, 66 insertions, 0 deletions
diff --git a/lib/btrfsutil/listnodes.go b/lib/btrfsutil/listnodes.go
new file mode 100644
index 0000000..16300da
--- /dev/null
+++ b/lib/btrfsutil/listnodes.go
@@ -0,0 +1,66 @@
+// Copyright (C) 2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package btrfsutil
+
+import (
+ "context"
+
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
+ "git.lukeshu.com/btrfs-progs-ng/lib/containers"
+ "git.lukeshu.com/btrfs-progs-ng/lib/diskio"
+ "git.lukeshu.com/btrfs-progs-ng/lib/maps"
+ "git.lukeshu.com/btrfs-progs-ng/lib/textui"
+)
+
+type nodeScanner struct {
+ nodes containers.Set[btrfsvol.LogicalAddr]
+}
+
+type nodeStats struct {
+ numNodes int
+}
+
+func (s nodeStats) String() string {
+ return textui.Sprintf("found: %d nodes", s.numNodes)
+}
+
+var _ DeviceScanner[nodeStats, containers.Set[btrfsvol.LogicalAddr]] = (*nodeScanner)(nil)
+
+func newNodeScanner(ctx context.Context, sb btrfstree.Superblock, numBytes btrfsvol.PhysicalAddr, numSectors int) DeviceScanner[nodeStats, containers.Set[btrfsvol.LogicalAddr]] {
+ s := new(nodeScanner)
+ s.nodes = make(containers.Set[btrfsvol.LogicalAddr])
+ return s
+}
+
+func (s *nodeScanner) ScanStats() nodeStats {
+ return nodeStats{numNodes: len(s.nodes)}
+}
+
+func (*nodeScanner) ScanSector(ctx context.Context, dev *btrfs.Device, paddr btrfsvol.PhysicalAddr) error {
+ return nil
+}
+
+func (s *nodeScanner) ScanNode(ctx context.Context, nodeRef *diskio.Ref[btrfsvol.PhysicalAddr, btrfstree.Node]) error {
+ s.nodes.Insert(nodeRef.Data.Head.Addr)
+ return nil
+}
+
+func (s *nodeScanner) ScanDone(ctx context.Context) (containers.Set[btrfsvol.LogicalAddr], error) {
+ return s.nodes, nil
+}
+
+func ListNodes(ctx context.Context, fs *btrfs.FS) ([]btrfsvol.LogicalAddr, error) {
+ perDev, err := ScanDevices[nodeStats, containers.Set[btrfsvol.LogicalAddr]](ctx, fs, newNodeScanner)
+ if err != nil {
+ return nil, err
+ }
+ set := make(containers.Set[btrfsvol.LogicalAddr])
+ for _, devSet := range perDev {
+ set.InsertFrom(devSet)
+ }
+ return maps.SortedKeys(set), nil
+}