From e784de8a66c3645fdd3a54939b5b844f3bacd82d Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 13 Jul 2022 23:55:59 -0600 Subject: diskio.File: Add .Close() and don't have .Size() return an error --- lib/btrfs/btrfsvol/lvm.go | 20 +++++++++++++++--- lib/btrfs/io1_pv.go | 24 ++------------------- lib/btrfs/io2_lv.go | 13 ++---------- lib/btrfsprogs/btrfsinspect/recoverchunks.go | 2 +- lib/btrfsprogs/btrfsutil/open.go | 12 +++++++++-- lib/btrfsprogs/btrfsutil/scan.go | 5 +---- lib/diskio/file_iface.go | 24 +++++++++++++++++++++ lib/diskio/file_os.go | 31 ++++++++++++++++++++++++++++ lib/diskio/ref.go | 13 ------------ 9 files changed, 88 insertions(+), 56 deletions(-) create mode 100644 lib/diskio/file_iface.go create mode 100644 lib/diskio/file_os.go (limited to 'lib') diff --git a/lib/btrfs/btrfsvol/lvm.go b/lib/btrfs/btrfsvol/lvm.go index 4d40ccd..149c8cd 100644 --- a/lib/btrfs/btrfsvol/lvm.go +++ b/lib/btrfs/btrfsvol/lvm.go @@ -10,6 +10,8 @@ import ( "os" "reflect" + "github.com/datawire/dlib/derror" + "git.lukeshu.com/btrfs-progs-ng/lib/containers" "git.lukeshu.com/btrfs-progs-ng/lib/diskio" ) @@ -58,15 +60,27 @@ func (lv *LogicalVolume[PhysicalVolume]) Name() string { return lv.name } -func (lv *LogicalVolume[PhysicalVolume]) Size() (LogicalAddr, error) { +func (lv *LogicalVolume[PhysicalVolume]) Size() LogicalAddr { lv.init() lastChunk := lv.logical2physical.Max() if lastChunk == nil { - return 0, nil + return 0 } - return lastChunk.Value.LAddr.Add(lastChunk.Value.Size), nil + return lastChunk.Value.LAddr.Add(lastChunk.Value.Size) } +func (lv *LogicalVolume[PhysicalVolume]) Close() error { + var errs derror.MultiError + for _, dev := range lv.id2pv { + if err := dev.Close(); err != nil && err == nil { + errs = append(errs, err) + } + } + if errs != nil { + return errs + } + return nil +} func (lv *LogicalVolume[PhysicalVolume]) AddPhysicalVolume(id DeviceID, dev PhysicalVolume) error { lv.init() if other, exists := lv.id2pv[id]; exists { diff --git a/lib/btrfs/io1_pv.go b/lib/btrfs/io1_pv.go index 10b6e32..df31671 100644 --- a/lib/btrfs/io1_pv.go +++ b/lib/btrfs/io1_pv.go @@ -6,7 +6,6 @@ package btrfs import ( "fmt" - "os" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" @@ -14,7 +13,7 @@ import ( ) type Device struct { - *os.File + diskio.File[btrfsvol.PhysicalAddr] cacheSuperblocks []*diskio.Ref[btrfsvol.PhysicalAddr, Superblock] cacheSuperblock *Superblock @@ -22,22 +21,6 @@ type Device struct { var _ diskio.File[btrfsvol.PhysicalAddr] = (*Device)(nil) -func (dev Device) Size() (btrfsvol.PhysicalAddr, error) { - fi, err := dev.Stat() - if err != nil { - return 0, err - } - return btrfsvol.PhysicalAddr(fi.Size()), nil -} - -func (dev *Device) ReadAt(dat []byte, paddr btrfsvol.PhysicalAddr) (int, error) { - return dev.File.ReadAt(dat, int64(paddr)) -} - -func (dev *Device) WriteAt(dat []byte, paddr btrfsvol.PhysicalAddr) (int, error) { - return dev.File.WriteAt(dat, int64(paddr)) -} - var SuperblockAddrs = []btrfsvol.PhysicalAddr{ 0x00_0001_0000, // 64KiB 0x00_0400_0000, // 64MiB @@ -50,10 +33,7 @@ func (dev *Device) Superblocks() ([]*diskio.Ref[btrfsvol.PhysicalAddr, Superbloc } superblockSize := btrfsvol.PhysicalAddr(binstruct.StaticSize(Superblock{})) - sz, err := dev.Size() - if err != nil { - return nil, err - } + sz := dev.Size() var ret []*diskio.Ref[btrfsvol.PhysicalAddr, Superblock] for i, addr := range SuperblockAddrs { diff --git a/lib/btrfs/io2_lv.go b/lib/btrfs/io2_lv.go index 47ab474..9316e27 100644 --- a/lib/btrfs/io2_lv.go +++ b/lib/btrfs/io2_lv.go @@ -57,7 +57,7 @@ func (fs *FS) Name() string { return name } -func (fs *FS) Size() (btrfsvol.LogicalAddr, error) { +func (fs *FS) Size() btrfsvol.LogicalAddr { return fs.LV.Size() } @@ -185,16 +185,7 @@ func (fs *FS) initDev(ctx context.Context, sb Superblock) error { } func (fs *FS) Close() error { - var errs derror.MultiError - for _, dev := range fs.LV.PhysicalVolumes() { - if err := dev.Close(); err != nil && err == nil { - errs = append(errs, err) - } - } - if errs != nil { - return errs - } - return nil + return fs.LV.Close() } var _ io.Closer = (*FS)(nil) diff --git a/lib/btrfsprogs/btrfsinspect/recoverchunks.go b/lib/btrfsprogs/btrfsinspect/recoverchunks.go index 27ac85b..257a4fd 100644 --- a/lib/btrfsprogs/btrfsinspect/recoverchunks.go +++ b/lib/btrfsprogs/btrfsinspect/recoverchunks.go @@ -155,7 +155,7 @@ func ScanOneDev(ctx context.Context, dev *btrfs.Device, superblock btrfs.Superbl FoundNodes: make(map[btrfsvol.LogicalAddr][]btrfsvol.PhysicalAddr), } - devSize, _ := dev.Size() + devSize := dev.Size() lastProgress := -1 err := btrfsutil.ScanForNodes(ctx, dev, superblock, func(nodeRef *diskio.Ref[btrfsvol.PhysicalAddr, btrfs.Node], err error) { diff --git a/lib/btrfsprogs/btrfsutil/open.go b/lib/btrfsprogs/btrfsutil/open.go index c237b54..0f3b32a 100644 --- a/lib/btrfsprogs/btrfsutil/open.go +++ b/lib/btrfsprogs/btrfsutil/open.go @@ -12,18 +12,26 @@ import ( "github.com/datawire/dlib/dlog" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol" + "git.lukeshu.com/btrfs-progs-ng/lib/diskio" ) func Open(ctx context.Context, flag int, filenames ...string) (*btrfs.FS, error) { fs := new(btrfs.FS) for i, filename := range filenames { dlog.Debugf(ctx, "Adding device file %d/%d %q...", i, len(filenames), filename) - fh, err := os.OpenFile(filename, flag, 0) + osFile, err := os.OpenFile(filename, flag, 0) if err != nil { _ = fs.Close() return nil, fmt.Errorf("device file %q: %w", filename, err) } - if err := fs.AddDevice(ctx, &btrfs.Device{File: fh}); err != nil { + typedFile := &diskio.OSFile[btrfsvol.PhysicalAddr]{ + File: osFile, + } + devFile := &btrfs.Device{ + File: typedFile, + } + if err := fs.AddDevice(ctx, devFile); err != nil { return nil, fmt.Errorf("device file %q: %w", filename, err) } } diff --git a/lib/btrfsprogs/btrfsutil/scan.go b/lib/btrfsprogs/btrfsutil/scan.go index dd77747..d5d3d8d 100644 --- a/lib/btrfsprogs/btrfsutil/scan.go +++ b/lib/btrfsprogs/btrfsutil/scan.go @@ -20,10 +20,7 @@ import ( // doing something itself when it finds a node, it simply calls a // callback function. func ScanForNodes(ctx context.Context, dev *btrfs.Device, sb btrfs.Superblock, fn func(*diskio.Ref[btrfsvol.PhysicalAddr, btrfs.Node], error), prog func(btrfsvol.PhysicalAddr)) error { - devSize, err := dev.Size() - if err != nil { - return err - } + devSize := dev.Size() if sb.NodeSize < sb.SectorSize { return fmt.Errorf("node_size(%v) < sector_size(%v)", diff --git a/lib/diskio/file_iface.go b/lib/diskio/file_iface.go new file mode 100644 index 0000000..206db0c --- /dev/null +++ b/lib/diskio/file_iface.go @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Luke Shumaker +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package diskio + +import ( + "io" +) + +type File[A ~int64] interface { + Name() string + Size() A + Close() error + ReadAt(p []byte, off A) (n int, err error) + WriteAt(p []byte, off A) (n int, err error) +} + +type assertAddr int64 + +var ( + _ io.WriterAt = File[int64](nil) + _ io.ReaderAt = File[int64](nil) +) diff --git a/lib/diskio/file_os.go b/lib/diskio/file_os.go new file mode 100644 index 0000000..2fa521d --- /dev/null +++ b/lib/diskio/file_os.go @@ -0,0 +1,31 @@ +// Copyright (C) 2022 Luke Shumaker +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package diskio + +import ( + "os" +) + +type OSFile[A ~int64] struct { + *os.File +} + +var _ File[assertAddr] = (*OSFile[assertAddr])(nil) + +func (f *OSFile[A]) Size() A { + fi, err := f.Stat() + if err != nil { + return 0 + } + return A(fi.Size()) +} + +func (f *OSFile[A]) ReadAt(dat []byte, paddr A) (int, error) { + return f.File.ReadAt(dat, int64(paddr)) +} + +func (f *OSFile[A]) WriteAt(dat []byte, paddr A) (int, error) { + return f.File.WriteAt(dat, int64(paddr)) +} diff --git a/lib/diskio/ref.go b/lib/diskio/ref.go index 9782743..137701d 100644 --- a/lib/diskio/ref.go +++ b/lib/diskio/ref.go @@ -6,23 +6,10 @@ package diskio import ( "fmt" - "io" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" ) -type File[A ~int64] interface { - Name() string - Size() (A, error) - ReadAt(p []byte, off A) (n int, err error) - WriteAt(p []byte, off A) (n int, err error) -} - -var ( - _ io.WriterAt = File[int64](nil) - _ io.ReaderAt = File[int64](nil) -) - type Ref[A ~int64, T any] struct { File File[A] Addr A -- cgit v1.2.3-2-g168b