@@ -740,6 +740,7 @@ struct btrfs_space_info {
struct list_head block_groups[BTRFS_NR_RAID_TYPES];
spinlock_t lock;
struct rw_semaphore groups_sem;
+ struct srcu_struct groups_srcu;
atomic_t caching_threads;
};
@@ -3003,6 +3003,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
for (i = 0; i < BTRFS_NR_RAID_TYPES; i++)
INIT_LIST_HEAD(&found->block_groups[i]);
init_rwsem(&found->groups_sem);
+ init_srcu_struct(&found->groups_srcu);
spin_lock_init(&found->lock);
found->flags = flags & (BTRFS_BLOCK_GROUP_DATA |
BTRFS_BLOCK_GROUP_SYSTEM |
@@ -4853,6 +4854,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
int data)
{
int ret = 0;
+ int idx;
struct btrfs_root *root = orig_root->fs_info->extent_root;
struct btrfs_free_cluster *last_ptr = NULL;
struct btrfs_block_group_cache *block_group = NULL;
@@ -4929,7 +4931,7 @@ ideal_cache:
if (block_group && block_group_bits(block_group, data) &&
(block_group->cached != BTRFS_CACHE_NO ||
search_start == ideal_cache_offset)) {
- down_read(&space_info->groups_sem);
+ idx = srcu_read_lock(&space_info->groups_srcu);
if (list_empty(&block_group->list) ||
block_group->ro) {
/*
@@ -4939,7 +4941,7 @@ ideal_cache:
* valid
*/
btrfs_put_block_group(block_group);
- up_read(&space_info->groups_sem);
+ srcu_read_unlock(&space_info->groups_srcu, idx);
} else {
index = get_block_group_index(block_group);
goto have_block_group;
@@ -4949,8 +4951,8 @@ ideal_cache:
}
}
search:
- down_read(&space_info->groups_sem);
- list_for_each_entry(block_group, &space_info->block_groups[index],
+ idx = srcu_read_lock(&space_info->groups_srcu);
+ list_for_each_entry_rcu(block_group, &space_info->block_groups[index],
list) {
u64 offset;
int cached;
@@ -5197,8 +5199,8 @@ loop:
BUG_ON(index != get_block_group_index(block_group));
btrfs_put_block_group(block_group);
}
- up_read(&space_info->groups_sem);
-
+ srcu_read_unlock(&space_info->groups_srcu, idx);
+
if (!ins->objectid && ++index < BTRFS_NR_RAID_TYPES)
goto search;