diff options
-rw-r--r-- | cmd/btrfs-dump-tree/main.go | 3 | ||||
-rw-r--r-- | cmd/btrfs-fsck/main.go | 31 | ||||
-rw-r--r-- | cmd/btrfs-fsck/pass0.go | 19 | ||||
-rw-r--r-- | cmd/btrfs-fsck/pass1.go | 11 | ||||
-rw-r--r-- | pkg/btrfs/io2_fs.go | 135 |
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 } |