summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-06-26 21:27:55 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-06-26 22:19:41 -0600
commit64c04fc690ec5a276e11500691173962bbe4d99e (patch)
treef01996f95da88c38ee4bc1aa3691dc650eebf2e7
parentbfb830d024fd6309d81e20a7d21a2433c4ec9c93 (diff)
fuss with exposing .LV and how init happens
-rw-r--r--cmd/btrfs-dump-tree/main.go3
-rw-r--r--cmd/btrfs-fsck/main.go31
-rw-r--r--cmd/btrfs-fsck/pass0.go19
-rw-r--r--cmd/btrfs-fsck/pass1.go11
-rw-r--r--pkg/btrfs/io2_fs.go135
5 files changed, 97 insertions, 102 deletions
diff --git a/cmd/btrfs-dump-tree/main.go b/cmd/btrfs-dump-tree/main.go
index 9c8e4c5..ded7a39 100644
--- a/cmd/btrfs-dump-tree/main.go
+++ b/cmd/btrfs-dump-tree/main.go
@@ -35,9 +35,6 @@ func Main(imgfilename string) (err error) {
fs := new(btrfs.FS)
if err := fs.AddDevice(&btrfs.Device{File: fh}); err != nil {
- return err
- }
- if err := fs.Init(); err != nil {
fmt.Printf("(error) %v\n", err)
}
diff --git a/cmd/btrfs-fsck/main.go b/cmd/btrfs-fsck/main.go
index 0083bd9..e51aae9 100644
--- a/cmd/btrfs-fsck/main.go
+++ b/cmd/btrfs-fsck/main.go
@@ -3,43 +3,40 @@ package main
import (
"fmt"
"os"
-
- "lukeshu.com/btrfs-tools/pkg/btrfs"
)
func main() {
- if err := Main(os.Args[1]); err != nil {
+ if err := Main(os.Args[1:]...); err != nil {
fmt.Fprintf(os.Stderr, "%v: error: %v\n", os.Args[0], err)
os.Exit(1)
}
}
-func Main(imgfilename string) (err error) {
+func Main(imgfilenames ...string) (err error) {
maybeSetErr := func(_err error) {
if _err != nil && err == nil {
err = _err
}
}
- fh, err := os.OpenFile(imgfilename, os.O_RDWR, 0)
- if err != nil {
- return err
- }
- defer func() {
- maybeSetErr(fh.Close())
- }()
-
- fs := new(btrfs.FS)
- if err := fs.AddDevice(&btrfs.Device{File: fh}); err != nil {
- return err
+ var imgfiles []*os.File
+ for _, imgfilename := range imgfilenames {
+ fh, err := os.OpenFile(imgfilename, os.O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ maybeSetErr(fh.Close())
+ }()
+ imgfiles = append(imgfiles, fh)
}
- superblock, err := pass0(fs)
+ fs, sb, err := pass0(imgfiles...)
if err != nil {
return err
}
- foundNodes, err := pass1(fs, superblock)
+ foundNodes, err := pass1(fs, sb)
if err != nil {
return err
}
diff --git a/cmd/btrfs-fsck/pass0.go b/cmd/btrfs-fsck/pass0.go
index 8482826..2a8e20a 100644
--- a/cmd/btrfs-fsck/pass0.go
+++ b/cmd/btrfs-fsck/pass0.go
@@ -2,18 +2,27 @@ package main
import (
"fmt"
+ "os"
"lukeshu.com/btrfs-tools/pkg/btrfs"
"lukeshu.com/btrfs-tools/pkg/util"
)
-func pass0(fs *btrfs.FS) (*util.Ref[btrfs.PhysicalAddr, btrfs.Superblock], error) {
- fmt.Printf("\nPass 0: superblocks...\n")
+func pass0(imgfiles ...*os.File) (*btrfs.FS, *util.Ref[btrfs.PhysicalAddr, btrfs.Superblock], error) {
+ fmt.Printf("\nPass 0: init and superblocks...\n")
- superblock, err := fs.Superblock()
+ fs := new(btrfs.FS)
+ for _, imgfile := range imgfiles {
+ fmt.Printf("Pass 0: ... adding device %q...\n", imgfile.Name())
+ if err := fs.AddDevice(&btrfs.Device{File: imgfile}); err != nil {
+ fmt.Printf("Pass 0: ... add device %q: error: %v\n", imgfile.Name(), err)
+ }
+ }
+
+ sb, err := fs.Superblock()
if err != nil {
- return nil, fmt.Errorf("superblock: %w", err)
+ return nil, nil, err
}
- return superblock, nil
+ return fs, sb, nil
}
diff --git a/cmd/btrfs-fsck/pass1.go b/cmd/btrfs-fsck/pass1.go
index 7798650..aada80d 100644
--- a/cmd/btrfs-fsck/pass1.go
+++ b/cmd/btrfs-fsck/pass1.go
@@ -18,11 +18,6 @@ import (
func pass1(fs *btrfs.FS, superblock *util.Ref[btrfs.PhysicalAddr, btrfs.Superblock]) (map[btrfs.LogicalAddr]struct{}, error) {
fmt.Printf("\nPass 1: chunk mappings...\n")
- fmt.Printf("Pass 1: ... initializing chunk mappings\n")
- if err := fs.Init(); err != nil {
- fmt.Printf("Pass 1: ... init chunk tree: error: %v\n", err)
- }
-
fmt.Printf("Pass 1: ... walking fs\n")
visitedNodes := make(map[btrfs.LogicalAddr]struct{})
btrfsmisc.WalkFS(fs, btrfs.WalkTreeHandler{
@@ -45,7 +40,7 @@ func pass1(fs *btrfs.FS, superblock *util.Ref[btrfs.PhysicalAddr, btrfs.Superblo
Size btrfs.AddrDelta
Stripes []btrfsitem.ChunkStripe
})
- for _, dev := range fs.Devices() {
+ for _, dev := range fs.LV.PhysicalVolumes() {
fmt.Printf("Pass 1: ... dev[%q] scanning for nodes...\n", dev.Name())
devResult, err := pass1ScanOneDev(dev, superblock.Data)
if err != nil {
@@ -506,7 +501,7 @@ func pass1WriteReconstructedChunks(
},
}
- for _, dev := range fs.Devices() {
+ for _, dev := range fs.LV.PhysicalVolumes() {
superblock, _ := dev.Superblock()
reconstructedNode.Data.BodyLeaf = append(reconstructedNode.Data.BodyLeaf, btrfs.Item{
Head: btrfs.ItemHeader{
@@ -568,7 +563,7 @@ func pass1WriteReconstructedChunks(
fmt.Printf("Pass 1: ... write new node: error: %v\n", err)
}
- if err := fs.Init(); err != nil {
+ if err := fs.ReInit(); err != nil {
fmt.Printf("Pass 1: ... re-init mappings: %v\n", err)
}
}
diff --git a/pkg/btrfs/io2_fs.go b/pkg/btrfs/io2_fs.go
index c9208b7..80f0862 100644
--- a/pkg/btrfs/io2_fs.go
+++ b/pkg/btrfs/io2_fs.go
@@ -2,7 +2,6 @@ package btrfs
import (
"fmt"
- "reflect"
"lukeshu.com/btrfs-tools/pkg/btrfs/btrfsitem"
"lukeshu.com/btrfs-tools/pkg/btrfs/btrfsvol"
@@ -10,7 +9,9 @@ import (
)
type FS struct {
- lv btrfsvol.LogicalVolume[*Device]
+ // You should probably not access .LV directly, except when
+ // implementing special things like fsck.
+ LV btrfsvol.LogicalVolume[*Device]
cacheSuperblocks []*util.Ref[PhysicalAddr, Superblock]
cacheSuperblock *util.Ref[PhysicalAddr, Superblock]
@@ -23,11 +24,19 @@ func (fs *FS) AddDevice(dev *Device) error {
if err != nil {
return err
}
- return fs.lv.AddPhysicalVolume(sb.Data.DevItem.DevUUID, dev)
+ if err := fs.LV.AddPhysicalVolume(sb.Data.DevItem.DevUUID, dev); err != nil {
+ return err
+ }
+ fs.cacheSuperblocks = nil
+ fs.cacheSuperblock = nil
+ if err := fs.initDev(sb); err != nil {
+ return err
+ }
+ return nil
}
func (fs *FS) Name() string {
- if name := fs.lv.Name(); name != "" {
+ if name := fs.LV.Name(); name != "" {
return name
}
sb, err := fs.Superblock()
@@ -35,31 +44,23 @@ func (fs *FS) Name() string {
return fmt.Sprintf("fs_uuid=%v", "(unreadable)")
}
name := fmt.Sprintf("fs_uuid=%v", sb.Data.FSUUID)
- fs.lv.SetName(name)
+ fs.LV.SetName(name)
return name
}
func (fs *FS) Size() (LogicalAddr, error) {
- return fs.lv.Size()
+ return fs.LV.Size()
}
func (fs *FS) ReadAt(p []byte, off LogicalAddr) (int, error) {
- return fs.lv.ReadAt(p, off)
+ return fs.LV.ReadAt(p, off)
}
func (fs *FS) WriteAt(p []byte, off LogicalAddr) (int, error) {
- return fs.lv.WriteAt(p, off)
+ return fs.LV.WriteAt(p, off)
}
func (fs *FS) Resolve(laddr LogicalAddr) (paddrs map[QualifiedPhysicalAddr]struct{}, maxlen AddrDelta) {
- return fs.lv.Resolve(laddr)
-}
-
-func (fs *FS) UnResolve(paddr QualifiedPhysicalAddr) LogicalAddr {
- return fs.lv.UnResolve(paddr)
-}
-
-func (fs *FS) Devices() []*Device {
- return fs.lv.PhysicalVolumes()
+ return fs.LV.Resolve(laddr)
}
func (fs *FS) Superblocks() ([]*util.Ref[PhysicalAddr, Superblock], error) {
@@ -67,7 +68,7 @@ func (fs *FS) Superblocks() ([]*util.Ref[PhysicalAddr, Superblock], error) {
return fs.cacheSuperblocks, nil
}
var ret []*util.Ref[PhysicalAddr, Superblock]
- for _, dev := range fs.lv.PhysicalVolumes() {
+ for _, dev := range fs.LV.PhysicalVolumes() {
sbs, err := dev.Superblocks()
if err != nil {
return nil, fmt.Errorf("file %q: %w", dev.Name(), err)
@@ -86,6 +87,9 @@ func (fs *FS) Superblock() (*util.Ref[PhysicalAddr, Superblock], error) {
if err != nil {
return nil, err
}
+ if len(sbs) == 0 {
+ return nil, fmt.Errorf("no superblocks")
+ }
fname := ""
sbi := 0
@@ -115,70 +119,63 @@ func (fs *FS) Superblock() (*util.Ref[PhysicalAddr, Superblock], error) {
return sbs[0], nil
}
-func (fs *FS) Init() error {
- fs.lv.ClearMappings()
- for _, dev := range fs.lv.PhysicalVolumes() {
- sbs, err := dev.Superblocks()
+func (fs *FS) ReInit() error {
+ fs.LV.ClearMappings()
+ for _, dev := range fs.LV.PhysicalVolumes() {
+ sb, err := dev.Superblock()
if err != nil {
return fmt.Errorf("file %q: %w", dev.Name(), err)
}
+ if err := fs.initDev(sb); err != nil {
+ return fmt.Errorf("file %q: %w", dev.Name(), err)
+ }
+ }
+ return nil
+}
- a := sbs[0].Data
- a.Checksum = CSum{}
- a.Self = 0
- for i, sb := range sbs[1:] {
- b := sb.Data
- b.Checksum = CSum{}
- b.Self = 0
- if !reflect.DeepEqual(a, b) {
- return fmt.Errorf("file %q: superblock %v disagrees with superblock 0",
- dev.Name(), i+1)
+func (fs *FS) initDev(sb *util.Ref[PhysicalAddr, Superblock]) error {
+ syschunks, err := sb.Data.ParseSysChunkArray()
+ if err != nil {
+ return err
+ }
+ for _, chunk := range syschunks {
+ for _, stripe := range chunk.Chunk.Stripes {
+ if err := fs.LV.AddMapping(
+ LogicalAddr(chunk.Key.Offset),
+ QualifiedPhysicalAddr{
+ Dev: stripe.DeviceUUID,
+ Addr: stripe.Offset,
+ },
+ chunk.Chunk.Head.Size,
+ &chunk.Chunk.Head.Type,
+ ); err != nil {
+ return err
}
}
- sb := sbs[0]
- syschunks, err := sb.Data.ParseSysChunkArray()
- if err != nil {
- return fmt.Errorf("file %q: %w", dev.Name(), err)
- }
- for _, chunk := range syschunks {
- for _, stripe := range chunk.Chunk.Stripes {
- if err := fs.lv.AddMapping(
- LogicalAddr(chunk.Key.Offset),
+ }
+ if err := fs.WalkTree(sb.Data.ChunkTree, WalkTreeHandler{
+ Item: func(_ WalkTreePath, item Item) error {
+ if item.Head.Key.ItemType != btrfsitem.CHUNK_ITEM_KEY {
+ return nil
+ }
+ body := item.Body.(btrfsitem.Chunk)
+ for _, stripe := range body.Stripes {
+ if err := fs.LV.AddMapping(
+ LogicalAddr(item.Head.Key.Offset),
QualifiedPhysicalAddr{
Dev: stripe.DeviceUUID,
Addr: stripe.Offset,
},
- chunk.Chunk.Head.Size,
- &chunk.Chunk.Head.Type,
+ body.Head.Size,
+ &body.Head.Type,
); err != nil {
- return fmt.Errorf("file %q: %w", dev.Name(), err)
+ return err
}
}
- }
- if err := fs.WalkTree(sb.Data.ChunkTree, WalkTreeHandler{
- Item: func(_ WalkTreePath, item Item) error {
- if item.Head.Key.ItemType != btrfsitem.CHUNK_ITEM_KEY {
- return nil
- }
- body := item.Body.(btrfsitem.Chunk)
- for _, stripe := range body.Stripes {
- if err := fs.lv.AddMapping(
- LogicalAddr(item.Head.Key.Offset),
- QualifiedPhysicalAddr{
- Dev: stripe.DeviceUUID,
- Addr: stripe.Offset,
- },
- body.Head.Size,
- &body.Head.Type,
- ); err != nil {
- return fmt.Errorf("file %q: %w", dev.Name(), err)
- }
- }
- return nil
- },
- }); err != nil {
- return err
- }
+ return nil
+ },
+ }); err != nil {
+ return err
}
return nil
}