summaryrefslogtreecommitdiff
path: root/lib/btrfs/io4_fs.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-12 16:17:02 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-12 16:17:02 -0700
commitcfcc753dc8906817e15b1b7c36b4dc12462d12e4 (patch)
treef5d2aa0caaa4cb336017ba7595c3425f4aa00bfc /lib/btrfs/io4_fs.go
parent29b6b9f997913f13a0bff8bb1278a61302413615 (diff)
parentf76faa4b8debd9c94751a03dd65e46c80a340a82 (diff)
Merge branch 'lukeshu/fast'
Diffstat (limited to 'lib/btrfs/io4_fs.go')
-rw-r--r--lib/btrfs/io4_fs.go76
1 files changed, 39 insertions, 37 deletions
diff --git a/lib/btrfs/io4_fs.go b/lib/btrfs/io4_fs.go
index fce9c76..56cf266 100644
--- a/lib/btrfs/io4_fs.go
+++ b/lib/btrfs/io4_fs.go
@@ -75,10 +75,10 @@ type Subvolume struct {
rootVal btrfsitem.Root
rootErr error
- bareInodeCache *containers.LRUCache[btrfsprim.ObjID, *BareInode]
- fullInodeCache *containers.LRUCache[btrfsprim.ObjID, *FullInode]
- dirCache *containers.LRUCache[btrfsprim.ObjID, *Dir]
- fileCache *containers.LRUCache[btrfsprim.ObjID, *File]
+ bareInodeCache containers.ARCache[btrfsprim.ObjID, *BareInode]
+ fullInodeCache containers.ARCache[btrfsprim.ObjID, *FullInode]
+ dirCache containers.ARCache[btrfsprim.ObjID, *Dir]
+ fileCache containers.ARCache[btrfsprim.ObjID, *File]
}
func (sv *Subvolume) init() {
@@ -88,19 +88,19 @@ func (sv *Subvolume) init() {
sv.rootErr = err
} else {
switch rootBody := root.Body.(type) {
- case btrfsitem.Root:
- sv.rootVal = rootBody
- case btrfsitem.Error:
+ 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 = containers.NewLRUCache[btrfsprim.ObjID, *BareInode](textui.Tunable(128))
- sv.fullInodeCache = containers.NewLRUCache[btrfsprim.ObjID, *FullInode](textui.Tunable(128))
- sv.dirCache = containers.NewLRUCache[btrfsprim.ObjID, *Dir](textui.Tunable(128))
- sv.fileCache = containers.NewLRUCache[btrfsprim.ObjID, *File](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)
})
}
@@ -111,7 +111,7 @@ func (sv *Subvolume) GetRootInode() (btrfsprim.ObjID, error) {
func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) {
sv.init()
- val := sv.bareInodeCache.GetOrElse(inode, func() (val *BareInode) {
+ val := containers.LoadOrElse[btrfsprim.ObjID, *BareInode](&sv.bareInodeCache, inode, func(inode btrfsprim.ObjID) (val *BareInode) {
val = &BareInode{
Inode: inode,
}
@@ -126,9 +126,10 @@ func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) {
}
switch itemBody := item.Body.(type) {
- case btrfsitem.Inode:
- val.InodeItem = &itemBody
- case btrfsitem.Error:
+ case *btrfsitem.Inode:
+ bodyCopy := itemBody.Clone()
+ val.InodeItem = &bodyCopy
+ case *btrfsitem.Error:
val.Errs = append(val.Errs, fmt.Errorf("malformed inode: %w", itemBody.Err))
default:
panic(fmt.Errorf("should not happen: INODE_ITEM has unexpected item type: %T", itemBody))
@@ -144,7 +145,7 @@ func (sv *Subvolume) LoadBareInode(inode btrfsprim.ObjID) (*BareInode, error) {
func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
sv.init()
- val := sv.fullInodeCache.GetOrElse(inode, func() (val *FullInode) {
+ val := containers.LoadOrElse[btrfsprim.ObjID, *FullInode](&sv.fullInodeCache, inode, func(indoe btrfsprim.ObjID) (val *FullInode) {
val = &FullInode{
BareInode: BareInode{
Inode: inode,
@@ -164,24 +165,25 @@ func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
switch item.Key.ItemType {
case btrfsitem.INODE_ITEM_KEY:
switch itemBody := item.Body.(type) {
- case btrfsitem.Inode:
+ case *btrfsitem.Inode:
if val.InodeItem != nil {
if !reflect.DeepEqual(itemBody, *val.InodeItem) {
val.Errs = append(val.Errs, fmt.Errorf("multiple inodes"))
}
continue
}
- val.InodeItem = &itemBody
- case btrfsitem.Error:
+ bodyCopy := itemBody.Clone()
+ val.InodeItem = &bodyCopy
+ case *btrfsitem.Error:
val.Errs = append(val.Errs, fmt.Errorf("malformed INODE_ITEM: %w", itemBody.Err))
default:
panic(fmt.Errorf("should not happen: INODE_ITEM has unexpected item type: %T", itemBody))
}
case btrfsitem.XATTR_ITEM_KEY:
switch itemBody := item.Body.(type) {
- case btrfsitem.DirEntry:
+ case *btrfsitem.DirEntry:
val.XAttrs[string(itemBody.Name)] = string(itemBody.Data)
- case btrfsitem.Error:
+ case *btrfsitem.Error:
val.Errs = append(val.Errs, fmt.Errorf("malformed XATTR_ITEM: %w", itemBody.Err))
default:
panic(fmt.Errorf("should not happen: XATTR_ITEM has unexpected item type: %T", itemBody))
@@ -200,7 +202,7 @@ func (sv *Subvolume) LoadFullInode(inode btrfsprim.ObjID) (*FullInode, error) {
func (sv *Subvolume) LoadDir(inode btrfsprim.ObjID) (*Dir, error) {
sv.init()
- val := sv.dirCache.GetOrElse(inode, func() (val *Dir) {
+ val := containers.LoadOrElse[btrfsprim.ObjID, *Dir](&sv.dirCache, inode, func(inode btrfsprim.ObjID) (val *Dir) {
val = new(Dir)
fullInode, err := sv.LoadFullInode(inode)
if err != nil {
@@ -225,15 +227,15 @@ func (dir *Dir) populate() {
switch item.Key.ItemType {
case btrfsitem.INODE_REF_KEY:
switch body := item.Body.(type) {
- case btrfsitem.InodeRefs:
- if len(body) != 1 {
+ case *btrfsitem.InodeRefs:
+ if len(body.Refs) != 1 {
dir.Errs = append(dir.Errs, fmt.Errorf("INODE_REF item with %d entries on a directory",
- len(body)))
+ len(body.Refs)))
continue
}
ref := InodeRef{
Inode: btrfsprim.ObjID(item.Key.Offset),
- InodeRef: body[0],
+ InodeRef: body.Refs[0],
}
if dir.DotDot != nil {
if !reflect.DeepEqual(ref, *dir.DotDot) {
@@ -242,14 +244,14 @@ func (dir *Dir) populate() {
continue
}
dir.DotDot = &ref
- case btrfsitem.Error:
+ case *btrfsitem.Error:
dir.Errs = append(dir.Errs, fmt.Errorf("malformed INODE_REF: %w", body.Err))
default:
panic(fmt.Errorf("should not happen: INODE_REF has unexpected item type: %T", body))
}
case btrfsitem.DIR_ITEM_KEY:
switch entry := item.Body.(type) {
- case btrfsitem.DirEntry:
+ case *btrfsitem.DirEntry:
namehash := btrfsitem.NameHash(entry.Name)
if namehash != item.Key.Offset {
dir.Errs = append(dir.Errs, fmt.Errorf("direntry crc32c mismatch: key=%#x crc32c(%q)=%#x",
@@ -262,8 +264,8 @@ func (dir *Dir) populate() {
}
continue
}
- dir.ChildrenByName[string(entry.Name)] = entry
- case btrfsitem.Error:
+ dir.ChildrenByName[string(entry.Name)] = entry.Clone()
+ case *btrfsitem.Error:
dir.Errs = append(dir.Errs, fmt.Errorf("malformed DIR_ITEM: %w", entry.Err))
default:
panic(fmt.Errorf("should not happen: DIR_ITEM has unexpected item type: %T", entry))
@@ -271,15 +273,15 @@ func (dir *Dir) populate() {
case btrfsitem.DIR_INDEX_KEY:
index := item.Key.Offset
switch entry := item.Body.(type) {
- case btrfsitem.DirEntry:
+ case *btrfsitem.DirEntry:
if other, exists := dir.ChildrenByIndex[index]; exists {
if !reflect.DeepEqual(entry, other) {
dir.Errs = append(dir.Errs, fmt.Errorf("multiple instances of direntry index %v", index))
}
continue
}
- dir.ChildrenByIndex[index] = entry
- case btrfsitem.Error:
+ dir.ChildrenByIndex[index] = entry.Clone()
+ case *btrfsitem.Error:
dir.Errs = append(dir.Errs, fmt.Errorf("malformed DIR_INDEX: %w", entry.Err))
default:
panic(fmt.Errorf("should not happen: DIR_INDEX has unexpected item type: %T", entry))
@@ -336,7 +338,7 @@ func (dir *Dir) AbsPath() (string, error) {
func (sv *Subvolume) LoadFile(inode btrfsprim.ObjID) (*File, error) {
sv.init()
- val := sv.fileCache.GetOrElse(inode, func() (val *File) {
+ val := containers.LoadOrElse[btrfsprim.ObjID, *File](&sv.fileCache, inode, func(inode btrfsprim.ObjID) (val *File) {
val = new(File)
fullInode, err := sv.LoadFullInode(inode)
if err != nil {
@@ -361,12 +363,12 @@ func (file *File) populate() {
// TODO
case btrfsitem.EXTENT_DATA_KEY:
switch itemBody := item.Body.(type) {
- case btrfsitem.FileExtent:
+ case *btrfsitem.FileExtent:
file.Extents = append(file.Extents, FileExtent{
OffsetWithinFile: int64(item.Key.Offset),
- FileExtent: itemBody,
+ FileExtent: *itemBody,
})
- case btrfsitem.Error:
+ case *btrfsitem.Error:
file.Errs = append(file.Errs, fmt.Errorf("malformed EXTENT_DATA: %w", itemBody.Err))
default:
panic(fmt.Errorf("should not happen: EXTENT_DATA has unexpected item type: %T", itemBody))