@@ -11250,3 +11250,97 @@ static int compute_priority_level(struct btrfs_fs_info *fs_info,
return level;
}
+
+static inline bool
+is_priority_alloc_enabled(struct btrfs_fs_info *fs_info)
+{
+ if (btrfs_test_opt(fs_info, PRIORITY_USAGE))
+ return true;
+ return false;
+}
+
+static void init_priority_tree(struct btrfs_priority_tree *pt, int level)
+{
+ pt->block_groups = RB_ROOT;
+ init_rwsem(&pt->groups_sem);
+ pt->level = level;
+}
+
+static void remove_priority_trees(struct btrfs_fs_info *fs_info,
+ struct btrfs_space_info *space_info)
+{
+ struct rb_root *root;
+ struct btrfs_priority_tree *pt, *next_pt;
+ int i;
+
+ if (!is_priority_alloc_enabled(fs_info))
+ return;
+
+ for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
+ root = &space_info->priority_trees[i];
+ rbtree_postorder_for_each_entry_safe(pt, next_pt, root, node) {
+ kfree(pt);
+ }
+ space_info->priority_trees[i] = RB_ROOT;
+ }
+}
+
+static int insert_priority_tree(struct rb_root *root,
+ struct btrfs_priority_tree *pt)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct btrfs_priority_tree *tmp;
+
+ while (*p) {
+ parent = *p;
+ tmp = rb_entry(parent, struct btrfs_priority_tree, node);
+ if (pt->level > tmp->level)
+ p = &(*p)->rb_left;
+ else if (pt->level < tmp->level)
+ p = &(*p)->rb_right;
+ else
+ return -EEXIST;
+ }
+
+ rb_link_node(&pt->node, parent, p);
+ rb_insert_color(&pt->node, root);
+ return 0;
+}
+
+static int create_priority_trees(struct btrfs_fs_info *fs_info,
+ struct btrfs_space_info *space_info)
+{
+ struct rb_root *root;
+ struct btrfs_priority_tree *pt;
+ int ret = 0;
+ int i, level, max_level;
+ u64 priority;
+
+ if (!is_priority_alloc_enabled(fs_info))
+ return 0;
+
+ if (btrfs_test_opt(fs_info, PRIORITY_USAGE)) {
+ priority = (u8)100 << PRIORITY_USAGE_SHIFT;
+ max_level = compute_priority_level(fs_info, priority);
+ }
+ for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
+ root = &space_info->priority_trees[i];
+
+ for (level = 0; level <= max_level; level++) {
+ pt = kzalloc(sizeof(*pt), GFP_NOFS);
+ if (!pt) {
+ ret = -ENOMEM;
+ break;
+ }
+ init_priority_tree(pt, level);
+ ret = insert_priority_tree(root, pt);
+ if (ret)
+ break;
+ }
+ }
+
+ if (ret)
+ remove_priority_trees(fs_info, space_info);
+ return ret;
+}
Introduce create_priority_trees() to create priority trees in space_info. Introduce remove_priority_trees() to remove priority trees in space_info. Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com> --- fs/btrfs/extent-tree.c | 94 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)