summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-03-02 22:35:00 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-03-17 22:30:37 -0400
commite1569565240cf6487ebeb5ec4c1386c8ba70f493 (patch)
treea078f324529f9cefbc75fcf0e05b0d3e3a1b68ff
parent26e58f1cd1d47b63b1b05b26c73c4f69f7e245cb (diff)
btrfs: io4_fs.go: Subvolume: Don't have public members; use a constructor
-rw-r--r--cmd/btrfs-rec/inspect/mount/mount.go35
-rw-r--r--cmd/btrfs-rec/inspect_lsfiles.go14
-rw-r--r--lib/btrfs/io4_fs.go80
3 files changed, 71 insertions, 58 deletions
diff --git a/cmd/btrfs-rec/inspect/mount/mount.go b/cmd/btrfs-rec/inspect/mount/mount.go
index 0e8faf1..4049393 100644
--- a/cmd/btrfs-rec/inspect/mount/mount.go
+++ b/cmd/btrfs-rec/inspect/mount/mount.go
@@ -28,6 +28,7 @@ import (
"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/btrfsprim"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfstree"
"git.lukeshu.com/btrfs-progs-ng/lib/btrfsutil"
"git.lukeshu.com/btrfs-progs-ng/lib/containers"
"git.lukeshu.com/btrfs-progs-ng/lib/maps"
@@ -45,14 +46,21 @@ func MountRO(ctx context.Context, fs *btrfs.FS, mountpoint string, noChecksums b
deviceName = abs
}
+ sb, err := fs.Superblock()
+ if err != nil {
+ return err
+ }
+
rootSubvol := &subvolume{
- Subvolume: btrfs.Subvolume{
- FS: btrfsutil.NewOldRebuiltForrest(ctx, fs),
- TreeID: btrfsprim.FS_TREE_OBJECTID,
- NoChecksums: noChecksums,
- },
+ Subvolume: btrfs.NewSubvolume(
+ btrfsutil.NewOldRebuiltForrest(ctx, fs),
+ btrfsprim.FS_TREE_OBJECTID,
+ noChecksums,
+ ),
DeviceName: deviceName,
Mountpoint: mountpoint,
+
+ sb: sb,
}
return rootSubvol.Run(ctx)
}
@@ -107,10 +115,12 @@ type fileState struct {
}
type subvolume struct {
- btrfs.Subvolume
+ *btrfs.Subvolume
DeviceName string
Mountpoint string
+ sb *btrfstree.Superblock
+
fuseutil.NotImplementedFileSystem
lastHandle uint64
dirHandles typedsync.Map[fuseops.HandleID, *dirState]
@@ -189,11 +199,8 @@ func (sv *subvolume) LoadDir(inode btrfsprim.ObjID) (val *btrfs.Dir, err error)
workerName := fmt.Sprintf("%d-%s", val.Inode, filepath.Base(subMountpoint))
sv.grp.Go(workerName, func(ctx context.Context) error {
subSv := &subvolume{
- Subvolume: btrfs.Subvolume{
- FS: sv.FS,
- TreeID: entry.Location.ObjectID,
- NoChecksums: sv.NoChecksums,
- },
+ sb: sv.sb,
+ Subvolume: sv.NewChildSubvolume(entry.Location.ObjectID),
DeviceName: sv.DeviceName,
Mountpoint: filepath.Join(sv.Mountpoint, subMountpoint[1:]),
}
@@ -208,11 +215,9 @@ func (sv *subvolume) LoadDir(inode btrfsprim.ObjID) (val *btrfs.Dir, err error)
}
func (sv *subvolume) StatFS(_ context.Context, op *fuseops.StatFSOp) error {
+ sb := sv.sb
+
// See linux.git/fs/btrfs/super.c:btrfs_statfs()
- sb, err := sv.FS.Superblock()
- if err != nil {
- return err
- }
op.IoSize = sb.SectorSize
op.BlockSize = sb.SectorSize
diff --git a/cmd/btrfs-rec/inspect_lsfiles.go b/cmd/btrfs-rec/inspect_lsfiles.go
index a2b46ab..e9fd057 100644
--- a/cmd/btrfs-rec/inspect_lsfiles.go
+++ b/cmd/btrfs-rec/inspect_lsfiles.go
@@ -45,10 +45,11 @@ func init() {
}()
ctx := cmd.Context()
- printSubvol(out, "", true, "/", &btrfs.Subvolume{
- FS: btrfsutil.NewOldRebuiltForrest(ctx, fs),
- TreeID: btrfsprim.FS_TREE_OBJECTID,
- })
+ printSubvol(out, "", true, "/", btrfs.NewSubvolume(
+ btrfsutil.NewOldRebuiltForrest(ctx, fs),
+ btrfsprim.FS_TREE_OBJECTID,
+ false,
+ ))
return nil
}),
@@ -160,10 +161,7 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv
}
printDir(out, prefix, isLast, name, dir)
case btrfsitem.ROOT_ITEM_KEY:
- printSubvol(out, prefix, isLast, name, &btrfs.Subvolume{
- FS: subvol.FS,
- TreeID: entry.Location.ObjectID,
- })
+ printSubvol(out, prefix, isLast, name, subvol.NewChildSubvolume(entry.Location.ObjectID))
default:
panic(fmt.Errorf("TODO: I don't know how to handle an FT_DIR with location.ItemType=%v: %q",
entry.Location.ItemType, name))
diff --git a/lib/btrfs/io4_fs.go b/lib/btrfs/io4_fs.go
index e4511a5..0445441 100644
--- a/lib/btrfs/io4_fs.go
+++ b/lib/btrfs/io4_fs.go
@@ -10,7 +10,6 @@ import (
"path/filepath"
"reflect"
"sort"
- "sync"
"github.com/datawire/dlib/derror"
@@ -63,15 +62,13 @@ type File struct {
}
type Subvolume struct {
- FS interface {
+ fs interface {
btrfstree.TreeOperator
Superblock() (*btrfstree.Superblock, error)
diskio.ReaderAt[btrfsvol.LogicalAddr]
}
TreeID btrfsprim.ObjID
- NoChecksums bool
-
- initOnce sync.Once
+ noChecksums bool
rootVal btrfsitem.Root
rootErr error
@@ -82,41 +79,57 @@ type Subvolume struct {
fileCache containers.ARCache[btrfsprim.ObjID, *File]
}
-func (sv *Subvolume) init() {
- sv.initOnce.Do(func() {
- root, err := sv.FS.TreeSearch(btrfsprim.ROOT_TREE_OBJECTID, btrfstree.SearchRootItem(sv.TreeID))
- if err != nil {
- sv.rootErr = err
- } else {
- switch rootBody := root.Body.(type) {
- case *btrfsitem.Root:
- sv.rootVal = rootBody.Clone()
- case *btrfsitem.Error:
- sv.rootErr = fmt.Errorf("FS_TREE ROOT_ITEM has malformed body: %w", rootBody.Err)
- default:
- panic(fmt.Errorf("should not happen: ROOT_ITEM has unexpected item type: %T", rootBody))
- }
+func NewSubvolume(
+ fs interface {
+ btrfstree.TreeOperator
+ Superblock() (*btrfstree.Superblock, error)
+ diskio.ReaderAt[btrfsvol.LogicalAddr]
+ },
+ treeID btrfsprim.ObjID,
+ noChecksums bool,
+) *Subvolume {
+ sv := &Subvolume{
+ fs: fs,
+ TreeID: treeID,
+ noChecksums: noChecksums,
+ }
+
+ root, err := sv.fs.TreeSearch(btrfsprim.ROOT_TREE_OBJECTID, btrfstree.SearchRootItem(sv.TreeID))
+ if err != nil {
+ sv.rootErr = err
+ } else {
+ switch rootBody := root.Body.(type) {
+ case *btrfsitem.Root:
+ sv.rootVal = rootBody.Clone()
+ case *btrfsitem.Error:
+ sv.rootErr = fmt.Errorf("FS_TREE ROOT_ITEM has malformed body: %w", rootBody.Err)
+ default:
+ panic(fmt.Errorf("should not happen: ROOT_ITEM has unexpected item type: %T", rootBody))
}
+ }
- sv.bareInodeCache.MaxLen = textui.Tunable(128)
- sv.fullInodeCache.MaxLen = textui.Tunable(128)
- sv.dirCache.MaxLen = textui.Tunable(128)
- sv.fileCache.MaxLen = textui.Tunable(128)
- })
+ sv.bareInodeCache.MaxLen = textui.Tunable(128)
+ sv.fullInodeCache.MaxLen = textui.Tunable(128)
+ sv.dirCache.MaxLen = textui.Tunable(128)
+ sv.fileCache.MaxLen = textui.Tunable(128)
+
+ return sv
+}
+
+func (sv *Subvolume) NewChildSubvolume(childID btrfsprim.ObjID) *Subvolume {
+ return NewSubvolume(sv.fs, childID, sv.noChecksums)
}
func (sv *Subvolume) GetRootInode() (btrfsprim.ObjID, error) {
- sv.init()
return sv.rootVal.RootDirID, sv.rootErr
}
func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) {
- sv.init()
val := containers.LoadOrElse[btrfsprim.ObjID, *BareInode](&sv.bareInodeCache, inode, func(inode btrfsprim.ObjID) (val *BareInode) {
val = &BareInode{
Inode: inode,
}
- item, err := sv.FS.TreeLookup(sv.TreeID, btrfsprim.Key{
+ item, err := sv.fs.TreeLookup(sv.TreeID, btrfsprim.Key{
ObjectID: inode,
ItemType: btrfsitem.INODE_ITEM_KEY,
Offset: 0,
@@ -145,7 +158,6 @@ func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) {
}
func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
- sv.init()
val := containers.LoadOrElse[btrfsprim.ObjID, *FullInode](&sv.fullInodeCache, inode, func(indoe btrfsprim.ObjID) (val *FullInode) {
val = &FullInode{
BareInode: BareInode{
@@ -153,7 +165,7 @@ func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
},
XAttrs: make(map[string]string),
}
- items, err := sv.FS.TreeSearchAll(sv.TreeID, btrfstree.SearchObject(inode))
+ items, err := sv.fs.TreeSearchAll(sv.TreeID, btrfstree.SearchObject(inode))
if err != nil {
val.Errs = append(val.Errs, err)
if len(items) == 0 {
@@ -200,7 +212,6 @@ func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
}
func (sv *Subvolume) LoadDir(inode btrfsprim.ObjID) (*Dir, error) {
- sv.init()
val := containers.LoadOrElse[btrfsprim.ObjID, *Dir](&sv.dirCache, inode, func(inode btrfsprim.ObjID) (val *Dir) {
val = new(Dir)
fullInode, err := sv.LoadFullInode(inode)
@@ -337,7 +348,6 @@ func (dir *Dir) AbsPath() (string, error) {
}
func (sv *Subvolume) LoadFile(inode btrfsprim.ObjID) (*File, error) {
- sv.init()
val := containers.LoadOrElse[btrfsprim.ObjID, *File](&sv.fileCache, inode, func(inode btrfsprim.ObjID) (val *File) {
val = new(File)
fullInode, err := sv.LoadFullInode(inode)
@@ -449,7 +459,7 @@ func (file *File) maybeShortReadAt(dat []byte, off int64) (int, error) {
case btrfsitem.FILE_EXTENT_INLINE:
return copy(dat, extent.BodyInline[offsetWithinExt:offsetWithinExt+readSize]), nil
case btrfsitem.FILE_EXTENT_REG, btrfsitem.FILE_EXTENT_PREALLOC:
- sb, err := file.SV.FS.Superblock()
+ sb, err := file.SV.fs.Superblock()
if err != nil {
return 0, err
}
@@ -458,7 +468,7 @@ func (file *File) maybeShortReadAt(dat []byte, off int64) (int, error) {
Add(btrfsvol.AddrDelta(offsetWithinExt))
var block [btrfssum.BlockSize]byte
blockBeg := (beg / btrfssum.BlockSize) * btrfssum.BlockSize
- n, err := file.SV.FS.ReadAt(block[:], blockBeg)
+ n, err := file.SV.fs.ReadAt(block[:], blockBeg)
if n > int(beg-blockBeg) {
n = copy(dat[:readSize], block[beg-blockBeg:])
} else {
@@ -467,8 +477,8 @@ func (file *File) maybeShortReadAt(dat []byte, off int64) (int, error) {
if err != nil {
return 0, err
}
- if !file.SV.NoChecksums {
- sumRun, err := LookupCSum(file.SV.FS, sb.ChecksumType, blockBeg)
+ if !file.SV.noChecksums {
+ sumRun, err := LookupCSum(file.SV.fs, sb.ChecksumType, blockBeg)
if err != nil {
return 0, fmt.Errorf("checksum@%v: %w", blockBeg, err)
}