diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2023-03-14 21:31:30 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2023-03-14 21:31:30 -0600 |
commit | 9e9b4e8ac67052d667f6e7fae0a6620b6dbc50c7 (patch) | |
tree | 1aed8e061590b90a3158511a6e9a098851344516 /lib/btrfs/btrfstree/btree_forrest.go | |
parent | 34bf167ef33c57b4d6767273f1d265971a4693b9 (diff) | |
parent | e92796fed05143239733d3feec0231a69af2f617 (diff) |
Merge branch 'lukeshu/reorg'
Diffstat (limited to 'lib/btrfs/btrfstree/btree_forrest.go')
-rw-r--r-- | lib/btrfs/btrfstree/btree_forrest.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/btrfs/btrfstree/btree_forrest.go b/lib/btrfs/btrfstree/btree_forrest.go new file mode 100644 index 0000000..ace2b49 --- /dev/null +++ b/lib/btrfs/btrfstree/btree_forrest.go @@ -0,0 +1,88 @@ +// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com> +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package btrfstree + +import ( + "fmt" + + "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/btrfsvol" +) + +// A TreeRoot is more-or-less a btrfsitem.Root, but simpler; returned by +// LookupTreeRoot. +type TreeRoot struct { + TreeID btrfsprim.ObjID + RootNode btrfsvol.LogicalAddr + Level uint8 + Generation btrfsprim.Generation +} + +func RootItemSearchFn(treeID btrfsprim.ObjID) func(btrfsprim.Key, uint32) int { + return func(key btrfsprim.Key, _ uint32) int { + if key.ObjectID == treeID && key.ItemType == btrfsitem.ROOT_ITEM_KEY { + return 0 + } + return btrfsprim.Key{ + ObjectID: treeID, + ItemType: btrfsitem.ROOT_ITEM_KEY, + Offset: 0, + }.Compare(key) + } +} + +// LookupTreeRoot is a utility function to help with implementing the 'Trees' +// interface. +func LookupTreeRoot(fs TreeOperator, sb Superblock, treeID btrfsprim.ObjID) (*TreeRoot, error) { + switch treeID { + case btrfsprim.ROOT_TREE_OBJECTID: + return &TreeRoot{ + TreeID: treeID, + RootNode: sb.RootTree, + Level: sb.RootLevel, + Generation: sb.Generation, // XXX: same generation as LOG_TREE? + }, nil + case btrfsprim.CHUNK_TREE_OBJECTID: + return &TreeRoot{ + TreeID: treeID, + RootNode: sb.ChunkTree, + Level: sb.ChunkLevel, + Generation: sb.ChunkRootGeneration, + }, nil + case btrfsprim.TREE_LOG_OBJECTID: + return &TreeRoot{ + TreeID: treeID, + RootNode: sb.LogTree, + Level: sb.LogLevel, + Generation: sb.Generation, // XXX: same generation as ROOT_TREE? + }, nil + case btrfsprim.BLOCK_GROUP_TREE_OBJECTID: + return &TreeRoot{ + TreeID: treeID, + RootNode: sb.BlockGroupRoot, + Level: sb.BlockGroupRootLevel, + Generation: sb.BlockGroupRootGeneration, + }, nil + default: + rootItem, err := fs.TreeSearch(btrfsprim.ROOT_TREE_OBJECTID, RootItemSearchFn(treeID)) + if err != nil { + return nil, err + } + switch rootItemBody := rootItem.Body.(type) { + case *btrfsitem.Root: + return &TreeRoot{ + TreeID: treeID, + RootNode: rootItemBody.ByteNr, + Level: rootItemBody.Level, + Generation: rootItemBody.Generation, + }, nil + case *btrfsitem.Error: + return nil, fmt.Errorf("malformed ROOT_ITEM for tree %v: %w", treeID, rootItemBody.Err) + default: + panic(fmt.Errorf("should not happen: ROOT_ITEM has unexpected item type: %T", rootItemBody)) + } + } +} |