From f6f0a251ed962374f69e9fd7722dcd5c44aa58ad Mon Sep 17 00:00:00 2001
From: Luke Shumaker <lukeshu@lukeshu.com>
Date: Fri, 24 Mar 2023 21:49:26 -0600
Subject: containers: Rethink the caching libraries

---
 cmd/btrfs-rec/inspect/lsfiles/lsfiles.go | 30 +++++++++++++++++++----------
 cmd/btrfs-rec/inspect/mount/mount.go     | 33 ++++++++++++++++++++++----------
 2 files changed, 43 insertions(+), 20 deletions(-)

(limited to 'cmd/btrfs-rec/inspect')

diff --git a/cmd/btrfs-rec/inspect/lsfiles/lsfiles.go b/cmd/btrfs-rec/inspect/lsfiles/lsfiles.go
index e42050f..af8f690 100644
--- a/cmd/btrfs-rec/inspect/lsfiles/lsfiles.go
+++ b/cmd/btrfs-rec/inspect/lsfiles/lsfiles.go
@@ -84,12 +84,14 @@ func printSubvol(out io.Writer, prefix string, isLast bool, name string, subvol
 			subvol.TreeID, fmtErr(err)))
 		return
 	}
-	dir, err := subvol.LoadDir(rootInode)
+
+	dir, err := subvol.AcquireDir(rootInode)
 	if err != nil {
 		printText(out, prefix, isLast, name+"/", textui.Sprintf("subvol_id=%v err=%v",
 			subvol.TreeID, fmtErr(err)))
 		return
 	}
+
 	if name == "/" {
 		printDir(out, prefix, isLast, name, dir)
 		return
@@ -127,19 +129,23 @@ func fmtInode(inode btrfs.BareInode) string {
 
 func printDir(out io.Writer, prefix string, isLast bool, name string, dir *btrfs.Dir) {
 	printText(out, prefix, isLast, name+"/", fmtInode(dir.BareInode))
+	childrenByName := dir.ChildrenByName
+	subvol := dir.SV
+	subvol.ReleaseDir(dir.Inode)
+
 	if isLast {
 		prefix += tS
 	} else {
 		prefix += tl
 	}
-	for i, childName := range maps.SortedKeys(dir.ChildrenByName) {
+	for i, childName := range maps.SortedKeys(childrenByName) {
 		printDirEntry(
 			out,
 			prefix,
-			i == len(dir.ChildrenByName)-1,
-			dir.SV,
+			i == len(childrenByName)-1,
+			subvol,
 			path.Join(name, childName),
-			dir.ChildrenByName[childName])
+			childrenByName[childName])
 	}
 }
 
@@ -151,7 +157,7 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv
 	case btrfsitem.FT_DIR:
 		switch entry.Location.ItemType {
 		case btrfsitem.INODE_ITEM_KEY:
-			dir, err := subvol.LoadDir(entry.Location.ObjectID)
+			dir, err := subvol.AcquireDir(entry.Location.ObjectID)
 			if err != nil {
 				printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err)))
 				return
@@ -168,44 +174,48 @@ func printDirEntry(out io.Writer, prefix string, isLast bool, subvol *btrfs.Subv
 			panic(fmt.Errorf("TODO: I don't know how to handle an FT_SYMLINK with location.ItemType=%v: %q",
 				entry.Location.ItemType, name))
 		}
-		file, err := subvol.LoadFile(entry.Location.ObjectID)
+		file, err := subvol.AcquireFile(entry.Location.ObjectID)
 		if err != nil {
 			printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err)))
 			return
 		}
+		defer subvol.ReleaseFile(entry.Location.ObjectID)
 		printSymlink(out, prefix, isLast, name, file)
 	case btrfsitem.FT_REG_FILE:
 		if entry.Location.ItemType != btrfsitem.INODE_ITEM_KEY {
 			panic(fmt.Errorf("TODO: I don't know how to handle an FT_REG_FILE with location.ItemType=%v: %q",
 				entry.Location.ItemType, name))
 		}
-		file, err := subvol.LoadFile(entry.Location.ObjectID)
+		file, err := subvol.AcquireFile(entry.Location.ObjectID)
 		if err != nil {
 			printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err)))
 			return
 		}
+		defer subvol.ReleaseFile(entry.Location.ObjectID)
 		printFile(out, prefix, isLast, name, file)
 	case btrfsitem.FT_SOCK:
 		if entry.Location.ItemType != btrfsitem.INODE_ITEM_KEY {
 			panic(fmt.Errorf("TODO: I don't know how to handle an FT_SOCK with location.ItemType=%v: %q",
 				entry.Location.ItemType, name))
 		}
-		file, err := subvol.LoadFile(entry.Location.ObjectID)
+		file, err := subvol.AcquireFile(entry.Location.ObjectID)
 		if err != nil {
 			printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err)))
 			return
 		}
+		defer subvol.ReleaseFile(entry.Location.ObjectID)
 		printSocket(out, prefix, isLast, name, file)
 	case btrfsitem.FT_FIFO:
 		if entry.Location.ItemType != btrfsitem.INODE_ITEM_KEY {
 			panic(fmt.Errorf("TODO: I don't know how to handle an FT_FIFO with location.ItemType=%v: %q",
 				entry.Location.ItemType, name))
 		}
-		file, err := subvol.LoadFile(entry.Location.ObjectID)
+		file, err := subvol.AcquireFile(entry.Location.ObjectID)
 		if err != nil {
 			printText(out, prefix, isLast, name, textui.Sprintf("%v err=%v", entry.Type, fmtErr(err)))
 			return
 		}
+		defer subvol.ReleaseFile(entry.Location.ObjectID)
 		printPipe(out, prefix, isLast, name, file)
 	default:
 		panic(fmt.Errorf("TODO: I don't know how to handle a fileType=%v: %q",
diff --git a/cmd/btrfs-rec/inspect/mount/mount.go b/cmd/btrfs-rec/inspect/mount/mount.go
index d4d2e0a..143131a 100644
--- a/cmd/btrfs-rec/inspect/mount/mount.go
+++ b/cmd/btrfs-rec/inspect/mount/mount.go
@@ -169,8 +169,8 @@ func inodeItemToFUSE(itemBody btrfsitem.Inode) fuseops.InodeAttributes {
 	}
 }
 
-func (sv *subvolume) LoadDir(inode btrfsprim.ObjID) (val *btrfs.Dir, err error) {
-	val, err = sv.Subvolume.LoadDir(inode)
+func (sv *subvolume) AcquireDir(inode btrfsprim.ObjID) (val *btrfs.Dir, err error) {
+	val, err = sv.Subvolume.AcquireDir(inode)
 	if val != nil {
 		haveSubvolumes := false
 		for _, index := range maps.SortedKeys(val.ChildrenByIndex) {
@@ -245,10 +245,11 @@ func (sv *subvolume) LookUpInode(_ context.Context, op *fuseops.LookUpInodeOp) e
 		op.Parent = fuseops.InodeID(parent)
 	}
 
-	dir, err := sv.LoadDir(btrfsprim.ObjID(op.Parent))
+	dir, err := sv.AcquireDir(btrfsprim.ObjID(op.Parent))
 	if err != nil {
 		return err
 	}
+	defer sv.Subvolume.ReleaseDir(btrfsprim.ObjID(op.Parent))
 	entry, ok := dir.ChildrenByName[op.Name]
 	if !ok {
 		return syscall.ENOENT
@@ -275,10 +276,13 @@ func (sv *subvolume) LookUpInode(_ context.Context, op *fuseops.LookUpInodeOp) e
 		}
 		return nil
 	}
-	bareInode, err := sv.LoadBareInode(entry.Location.ObjectID)
+
+	bareInode, err := sv.AcquireBareInode(entry.Location.ObjectID)
 	if err != nil {
 		return err
 	}
+	defer sv.ReleaseBareInode(entry.Location.ObjectID)
+
 	op.Entry = fuseops.ChildInodeEntry{
 		Child:      fuseops.InodeID(entry.Location.ObjectID),
 		Generation: fuseops.GenerationNumber(bareInode.InodeItem.Sequence),
@@ -296,10 +300,11 @@ func (sv *subvolume) GetInodeAttributes(_ context.Context, op *fuseops.GetInodeA
 		op.Inode = fuseops.InodeID(inode)
 	}
 
-	bareInode, err := sv.LoadBareInode(btrfsprim.ObjID(op.Inode))
+	bareInode, err := sv.AcquireBareInode(btrfsprim.ObjID(op.Inode))
 	if err != nil {
 		return err
 	}
+	defer sv.Subvolume.ReleaseBareInode(btrfsprim.ObjID(op.Inode))
 
 	op.Attributes = inodeItemToFUSE(*bareInode.InodeItem)
 	return nil
@@ -314,10 +319,12 @@ func (sv *subvolume) OpenDir(_ context.Context, op *fuseops.OpenDirOp) error {
 		op.Inode = fuseops.InodeID(inode)
 	}
 
-	dir, err := sv.LoadDir(btrfsprim.ObjID(op.Inode))
+	dir, err := sv.AcquireDir(btrfsprim.ObjID(op.Inode))
 	if err != nil {
 		return err
 	}
+	defer sv.Subvolume.ReleaseDir(btrfsprim.ObjID(op.Inode))
+
 	handle := sv.newHandle()
 	sv.dirHandles.Store(handle, &dirState{
 		Dir: dir,
@@ -369,10 +376,12 @@ func (sv *subvolume) ReleaseDirHandle(_ context.Context, op *fuseops.ReleaseDirH
 }
 
 func (sv *subvolume) OpenFile(_ context.Context, op *fuseops.OpenFileOp) error {
-	file, err := sv.LoadFile(btrfsprim.ObjID(op.Inode))
+	file, err := sv.AcquireFile(btrfsprim.ObjID(op.Inode))
 	if err != nil {
 		return err
 	}
+	defer sv.Subvolume.ReleaseFile(btrfsprim.ObjID(op.Inode))
+
 	handle := sv.newHandle()
 	sv.fileHandles.Store(handle, &fileState{
 		File: file,
@@ -415,10 +424,12 @@ func (sv *subvolume) ReleaseFileHandle(_ context.Context, op *fuseops.ReleaseFil
 }
 
 func (sv *subvolume) ReadSymlink(_ context.Context, op *fuseops.ReadSymlinkOp) error {
-	file, err := sv.LoadFile(btrfsprim.ObjID(op.Inode))
+	file, err := sv.AcquireFile(btrfsprim.ObjID(op.Inode))
 	if err != nil {
 		return err
 	}
+	defer sv.Subvolume.ReleaseFile(btrfsprim.ObjID(op.Inode))
+
 	reader := io.NewSectionReader(file, 0, file.InodeItem.Size)
 	tgt, err := io.ReadAll(reader)
 	if err != nil {
@@ -437,10 +448,11 @@ func (sv *subvolume) ListXattr(_ context.Context, op *fuseops.ListXattrOp) error
 		op.Inode = fuseops.InodeID(inode)
 	}
 
-	fullInode, err := sv.LoadFullInode(btrfsprim.ObjID(op.Inode))
+	fullInode, err := sv.AcquireFullInode(btrfsprim.ObjID(op.Inode))
 	if err != nil {
 		return err
 	}
+	defer sv.Subvolume.ReleaseFullInode(btrfsprim.ObjID(op.Inode))
 
 	size := 0
 	for name := range fullInode.XAttrs {
@@ -469,10 +481,11 @@ func (sv *subvolume) GetXattr(_ context.Context, op *fuseops.GetXattrOp) error {
 		op.Inode = fuseops.InodeID(inode)
 	}
 
-	fullInode, err := sv.LoadFullInode(btrfsprim.ObjID(op.Inode))
+	fullInode, err := sv.AcquireFullInode(btrfsprim.ObjID(op.Inode))
 	if err != nil {
 		return err
 	}
+	defer sv.Subvolume.ReleaseFullInode(btrfsprim.ObjID(op.Inode))
 
 	val, ok := fullInode.XAttrs[op.Name]
 	if !ok {
-- 
cgit v1.2.3-2-g168b