summaryrefslogtreecommitdiff
path: root/lib/btrfs/btrfstree/ops.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/btrfstree/ops.go
parent29b6b9f997913f13a0bff8bb1278a61302413615 (diff)
parentf76faa4b8debd9c94751a03dd65e46c80a340a82 (diff)
Merge branch 'lukeshu/fast'
Diffstat (limited to 'lib/btrfs/btrfstree/ops.go')
-rw-r--r--lib/btrfs/btrfstree/ops.go51
1 files changed, 45 insertions, 6 deletions
diff --git a/lib/btrfs/btrfstree/ops.go b/lib/btrfs/btrfstree/ops.go
index cdacef9..b01312f 100644
--- a/lib/btrfs/btrfstree/ops.go
+++ b/lib/btrfs/btrfstree/ops.go
@@ -144,6 +144,7 @@ func (fs TreeOperatorImpl) treeWalk(ctx context.Context, path TreePath, errHandl
}
}
node, err := fs.ReadNode(path)
+ defer FreeNodeRef(node)
if ctx.Err() != nil {
return
}
@@ -207,7 +208,7 @@ func (fs TreeOperatorImpl) treeWalk(ctx context.Context, path TreePath, errHandl
ToKey: item.Key,
ToMaxKey: item.Key,
})
- if errBody, isErr := item.Body.(btrfsitem.Error); isErr {
+ if errBody, isErr := item.Body.(*btrfsitem.Error); isErr {
if cbs.BadItem == nil {
errHandle(&TreeError{Path: itemPath, Err: errBody.Err})
} else {
@@ -255,6 +256,7 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
}
node, err := fs.ReadNode(path)
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
@@ -273,6 +275,7 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
return slices.Min(fn(kp.Key, math.MaxUint32), 0) // don't return >0; a key can't be "too low"
})
if !ok {
+ FreeNodeRef(node)
return nil, nil, iofs.ErrNotExist
}
toMaxKey := path.Node(-1).ToMaxKey
@@ -288,6 +291,7 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
ToKey: node.Data.BodyInternal[lastGood].Key,
ToMaxKey: toMaxKey,
})
+ FreeNodeRef(node)
} else {
// leaf node
@@ -305,6 +309,7 @@ func (fs TreeOperatorImpl) treeSearch(treeRoot TreeRoot, fn func(btrfsprim.Key,
return fn(item.Key, item.BodySize)
})
if !ok {
+ FreeNodeRef(node)
return nil, nil, iofs.ErrNotExist
}
path = append(path, TreePathElem{
@@ -333,8 +338,10 @@ func (fs TreeOperatorImpl) prev(path TreePath, node *diskio.Ref[btrfsvol.Logical
path.Node(-1).FromItemIdx--
if path.Node(-1).ToNodeAddr != 0 {
if node.Addr != path.Node(-2).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path.Parent())
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
path.Node(-1).ToNodeAddr = node.Data.BodyInternal[path.Node(-1).FromItemIdx].BlockPtr
@@ -343,8 +350,10 @@ func (fs TreeOperatorImpl) prev(path TreePath, node *diskio.Ref[btrfsvol.Logical
// go down
for path.Node(-1).ToNodeAddr != 0 {
if node.Addr != path.Node(-1).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path)
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
}
@@ -369,8 +378,10 @@ func (fs TreeOperatorImpl) prev(path TreePath, node *diskio.Ref[btrfsvol.Logical
}
// return
if node.Addr != path.Node(-2).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path.Parent())
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
}
@@ -383,8 +394,10 @@ func (fs TreeOperatorImpl) next(path TreePath, node *diskio.Ref[btrfsvol.Logical
// go up
if node.Addr != path.Node(-2).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path.Parent())
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
path.Node(-2).ToNodeLevel = node.Data.Head.Level
@@ -395,8 +408,10 @@ func (fs TreeOperatorImpl) next(path TreePath, node *diskio.Ref[btrfsvol.Logical
return nil, nil, nil
}
if node.Addr != path.Node(-2).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path.Parent())
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
path.Node(-2).ToNodeLevel = node.Data.Head.Level
@@ -406,8 +421,10 @@ func (fs TreeOperatorImpl) next(path TreePath, node *diskio.Ref[btrfsvol.Logical
path.Node(-1).FromItemIdx++
if path.Node(-1).ToNodeAddr != 0 {
if node.Addr != path.Node(-2).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path.Parent())
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
path.Node(-1).ToNodeAddr = node.Data.BodyInternal[path.Node(-1).FromItemIdx].BlockPtr
@@ -416,8 +433,10 @@ func (fs TreeOperatorImpl) next(path TreePath, node *diskio.Ref[btrfsvol.Logical
// go down
for path.Node(-1).ToNodeAddr != 0 {
if node.Addr != path.Node(-1).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path)
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
path.Node(-1).ToNodeLevel = node.Data.Head.Level
@@ -447,8 +466,10 @@ func (fs TreeOperatorImpl) next(path TreePath, node *diskio.Ref[btrfsvol.Logical
}
// return
if node.Addr != path.Node(-2).ToNodeAddr {
+ FreeNodeRef(node)
node, err = fs.ReadNode(path.Parent())
if err != nil {
+ FreeNodeRef(node)
return nil, nil, err
}
}
@@ -469,7 +490,10 @@ func (fs TreeOperatorImpl) TreeSearch(treeID btrfsprim.ObjID, fn func(btrfsprim.
if err != nil {
return Item{}, err
}
- return node.Data.BodyLeaf[path.Node(-1).FromItemIdx], nil
+ item := node.Data.BodyLeaf[path.Node(-1).FromItemIdx]
+ item.Body = item.Body.CloneItem()
+ FreeNodeRef(node)
+ return item, nil
}
// KeySearch returns a comparator suitable to be passed to TreeSearch.
@@ -506,7 +530,8 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, fn func(btrfspr
ret := []Item{middleItem}
var errs derror.MultiError
- for prevPath, prevNode := middlePath, middleNode; true; {
+ prevPath, prevNode := middlePath, middleNode
+ for {
prevPath, prevNode, err = fs.prev(prevPath, prevNode)
if err != nil {
errs = append(errs, err)
@@ -519,10 +544,21 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, fn func(btrfspr
if fn(prevItem.Key, prevItem.BodySize) != 0 {
break
}
- ret = append(ret, prevItem)
+ item := prevItem
+ item.Body = item.Body.CloneItem()
+ ret = append(ret, item)
}
slices.Reverse(ret)
- for nextPath, nextNode := middlePath, middleNode; true; {
+ if prevNode.Addr != middlePath.Node(-1).ToNodeAddr {
+ FreeNodeRef(prevNode)
+ middleNode, err = fs.ReadNode(middlePath)
+ if err != nil {
+ FreeNodeRef(middleNode)
+ return nil, err
+ }
+ }
+ nextPath, nextNode := middlePath, middleNode
+ for {
nextPath, nextNode, err = fs.next(nextPath, nextNode)
if err != nil {
errs = append(errs, err)
@@ -535,8 +571,11 @@ func (fs TreeOperatorImpl) TreeSearchAll(treeID btrfsprim.ObjID, fn func(btrfspr
if fn(nextItem.Key, nextItem.BodySize) != 0 {
break
}
- ret = append(ret, nextItem)
+ item := nextItem
+ item.Body = item.Body.CloneItem()
+ ret = append(ret, item)
}
+ FreeNodeRef(nextNode)
if errs != nil {
err = errs
}