1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
Patch from:
https://github.com/knorrie/python-btrfs/commit/7d8dca5bf1211843d8fd5c02b118afddaa53bee8
From 7d8dca5bf1211843d8fd5c02b118afddaa53bee8 Mon Sep 17 00:00:00 2001
From: Hans van Kranenburg <hans@knorrie.org>
Date: Sun, 21 May 2023 17:46:06 +0200
Subject: [PATCH] WIP ctree,ioctl,utils: Add Block Group Tree
When the block_group_tree feature is enabled on a filesystem, we have to
look up Block Group metadata items in the new Block Group Tree, instead
of the Extent Tree, where they always were located before.
WIP: We don't want to call the get_features ioctl *every* time we look
up 1 block group object, but we also cannot just cache the result of it,
since some feature flags can change while the fs is mounted.
So, this needs some extra work in the features department first to make
this more nice.
--- a/btrfs/ctree.py
+++ b/btrfs/ctree.py
@@ -91,6 +91,7 @@ def _struct_format(s):
QUOTA_TREE_OBJECTID = 8 #: Quota tree
UUID_TREE_OBJECTID = 9 #: Subvolume UUID tree
FREE_SPACE_TREE_OBJECTID = 10 #: Free space tree
+BLOCK_GROUP_TREE_OBJECTID = 11 #: Block group tree
DEV_STATS_OBJECTID = 0 #: Object ID of device statistics in the Device tree.
BALANCE_OBJECTID = ULL(-4) #: Object ID to store balance status. (-4)
@@ -346,6 +347,7 @@ def _qgroup_objectid(level, subvid):
QUOTA_TREE_OBJECTID: 'QUOTA_TREE',
UUID_TREE_OBJECTID: 'UUID_TREE',
FREE_SPACE_TREE_OBJECTID: 'FREE_SPACE_TREE',
+ BLOCK_GROUP_TREE_OBJECTID: 'BLOCK_GROUP_TREE',
BALANCE_OBJECTID: 'BALANCE',
ORPHAN_OBJECTID: 'ORPHAN',
TREE_LOG_OBJECTID: 'TREE_LOG',
@@ -765,6 +767,11 @@ def __init__(self, path):
self.fsid = _fs_info.fsid
self.nodesize = _fs_info.nodesize
self.sectorsize = _fs_info.sectorsize
+ # TEMP cached feature flag for block_group_tree TEMP
+ _features = self.features()
+ self._block_group_tree = self.features().compat_ro_flags & \
+ btrfs.ioctl.FEATURE_COMPAT_RO_BLOCK_GROUP_TREE != 0
+ # TEMP cached feature flag for block_group_tree TEMP
def __enter__(self):
return self
@@ -870,7 +877,10 @@ def block_group(self, vaddr, length=None):
:raises: :class:`ItemNotFoundError` if no Block Group Item can be found
at the address.
"""
- tree = EXTENT_TREE_OBJECTID
+ if not self._block_group_tree:
+ tree = EXTENT_TREE_OBJECTID
+ else:
+ tree = BLOCK_GROUP_TREE_OBJECTID
min_offset = length if length is not None else 0
max_offset = length if length is not None else ULLONG_MAX
min_key = Key(vaddr, BLOCK_GROUP_ITEM_KEY, min_offset)
@@ -1240,11 +1250,14 @@ class BlockGroupItem(ItemData):
The `Block Group` has a 1 to 1 relationship with a `Chunk` and tracks some
usage information about a range of virtual address space.
- * Tree: `EXTENT_TREE_OBJECTID` (2)
+ * Tree: `EXTENT_TREE_OBJECTID` (2) or `BLOCK_GROUP_TREE_OBJECTID` (11)
* Key objectid: Virtual address.
* Key type: `BLOCK_GROUP_ITEM_KEY` (192)
* Key offset: Block Group length.
+ If the block_group_tree feature is enabled on the filesystem, these items
+ can be found inside the Block Group Tree instead of the Extent Tree.
+
:ivar int vaddr: Virtual address where the Bock Group starts (taken from
the objectid field of the item key).
:ivar int length: Block Group length in bytes (taken from the offset field
--- a/btrfs/ioctl.py
+++ b/btrfs/ioctl.py
@@ -1325,10 +1325,12 @@ def _compat_flags_str(flags):
FEATURE_COMPAT_RO_FREE_SPACE_TREE = 1 << 0
FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID = 1 << 1
+FEATURE_COMPAT_RO_BLOCK_GROUP_TREE = 1 << 3
_feature_compat_ro_str_map = {
FEATURE_COMPAT_RO_FREE_SPACE_TREE: 'free_space_tree',
FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID: 'free_space_tree_valid',
+ FEATURE_COMPAT_RO_BLOCK_GROUP_TREE : 'block_group_tree',
}
@@ -1383,6 +1385,7 @@ class FeatureFlags(object):
- FEATURE_COMPAT_RO_FREE_SPACE_TREE
- FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID
+ - FEATURE_COMPAT_RO_BLOCK_GROUP_TREE
Known incompat_flags (available as attribute of this module) are:
--- a/btrfs/utils.py
+++ b/btrfs/utils.py
@@ -436,6 +436,7 @@ def embedded_text_for_str(text):
'quota': btrfs.ctree.QUOTA_TREE_OBJECTID,
'uuid': btrfs.ctree.UUID_TREE_OBJECTID,
'free_space': btrfs.ctree.FREE_SPACE_TREE_OBJECTID,
+ 'block_group': btrfs.ctree.BLOCK_GROUP_TREE_OBJECTID,
'tree_log': btrfs.ctree.TREE_LOG_OBJECTID,
'tree_log_fixup': btrfs.ctree.TREE_LOG_FIXUP_OBJECTID,
'tree_reloc': btrfs.ctree.TREE_RELOC_OBJECTID,
|