In origin design, the order of space_info::block_groups is changed only
when add/remove block group(s).
In design of priority aware allocator, block groups may be moved from
one priority tree to another one. What the operation is usually that
1) lock block_group
down_write first_tree
down_write second_tree
do unlink
....
do link
up_write second_tree
up_write first_tree
unlock blcok_group
However, the expected order in find_free_extent() is
2) down_read tree
lock block_group
...
unlock block_group
up_read tree
Obviously, orders of operation 1 and operation 2 are on the contrary
and will cause dead lock.
The ugly method is to introduce special status to mark block group
status.
Then:
1) After priority changed:
lock block_group
mark block_group to be updated
unlock blcok_group
down_write first_tree
down_write second_tree
lock block_group
check block group should be moved
do unlink
....
do link
unlock blcok_group
up_write second_tree
up_write first_tree
2) find_free_extent():
down_read tree
lock block_group
check the block group is not in special status
...
unlock block_group
up_read tree
This patch introduce three macros to represents block group is removing
/need to updated / busy.
Signed-off-by: Su Yue <suy.fnst@xxxxxxxxxxxxxx>
---
fs/btrfs/extent-tree.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d63078930a1e..5bae757786dc 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -31,6 +31,15 @@
#undef SCRAMBLE_DELAYED_REFS
+/* The block group is used by find_free_extent() */
+#define PRIORITY_BG_BUSY -1
+
+/* The block group is in remove or removed */
+#define PRIORITY_BG_DELETED -2
+
+/* The block group' priority needs to be updated */
+#define PRIORITY_BG_UPDATING -3
+
/*
* control flags for do_chunk_alloc's force field
* CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
--
2.19.1