}
btrfs_run_delayed_iputs(root);
+ btrfs_delete_unused_bgs(root->fs_info);
again = btrfs_clean_one_deleted_snapshot(root);
mutex_unlock(&root->fs_info->cleaner_mutex);
* needn't do anything special here.
*/
btrfs_run_defrag_inodes(root->fs_info);
-
- /*
- * Acquires fs_info->delete_unused_bgs_mutex to avoid racing
- * with relocation (btrfs_relocate_chunk) and relocation
- * acquires fs_info->cleaner_mutex (btrfs_relocate_block_group)
- * after acquiring fs_info->delete_unused_bgs_mutex. So we
- * can't hold, nor need to, fs_info->cleaner_mutex when deleting
- * unused block groups.
- */
- btrfs_delete_unused_bgs(root->fs_info);
sleep:
if (!try_to_freeze() && !again) {
set_current_state(TASK_INTERRUPTIBLE);
spin_lock_init(&fs_info->unused_bgs_lock);
rwlock_init(&fs_info->tree_mod_log_lock);
mutex_init(&fs_info->unused_bg_unpin_mutex);
- mutex_init(&fs_info->delete_unused_bgs_mutex);
mutex_init(&fs_info->reloc_mutex);
mutex_init(&fs_info->delalloc_root_mutex);
seqlock_init(&fs_info->profiles_lock);
root = root->fs_info->chunk_root;
extent_root = root->fs_info->extent_root;
- /*
- * Prevent races with automatic removal of unused block groups.
- * After we relocate and before we remove the chunk with offset
- * chunk_offset, automatic removal of the block group can kick in,
- * resulting in a failure when calling btrfs_remove_chunk() below.
- *
- * Make sure to acquire this mutex before doing a tree search (dev
- * or chunk trees) to find chunks. Otherwise the cleaner kthread might
- * call btrfs_remove_chunk() (through btrfs_delete_unused_bgs()) after
- * we release the path used to search the chunk/dev tree and before
- * the current task acquires this mutex and calls us.
- */
- ASSERT(mutex_is_locked(&root->fs_info->delete_unused_bgs_mutex));
-
ret = btrfs_can_relocate(extent_root, chunk_offset);
if (ret)
return -ENOSPC;
key.type = BTRFS_CHUNK_ITEM_KEY;
while (1) {
- mutex_lock(&root->fs_info->delete_unused_bgs_mutex);
ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
- if (ret < 0) {
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
+ if (ret < 0)
goto error;
- }
BUG_ON(ret == 0); /* Corruption */
ret = btrfs_previous_item(chunk_root, path, key.objectid,
key.type);
- if (ret)
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
if (ret < 0)
goto error;
if (ret > 0)
else
BUG_ON(ret);
}
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
if (found_key.offset == 0)
break;
goto error;
}
- mutex_lock(&fs_info->delete_unused_bgs_mutex);
ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
- if (ret < 0) {
- mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+ if (ret < 0)
goto error;
- }
/*
* this shouldn't happen, it means the last relocate
ret = btrfs_previous_item(chunk_root, path, 0,
BTRFS_CHUNK_ITEM_KEY);
if (ret) {
- mutex_unlock(&fs_info->delete_unused_bgs_mutex);
ret = 0;
break;
}
slot = path->slots[0];
btrfs_item_key_to_cpu(leaf, &found_key, slot);
- if (found_key.objectid != key.objectid) {
- mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+ if (found_key.objectid != key.objectid)
break;
- }
chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
ret = should_balance_chunk(chunk_root, leaf, chunk,
found_key.offset);
btrfs_release_path(path);
- if (!ret) {
- mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+ if (!ret)
goto loop;
- }
if (counting) {
- mutex_unlock(&fs_info->delete_unused_bgs_mutex);
spin_lock(&fs_info->balance_lock);
bctl->stat.expected++;
spin_unlock(&fs_info->balance_lock);
ret = btrfs_relocate_chunk(chunk_root,
found_key.objectid,
found_key.offset);
- mutex_unlock(&fs_info->delete_unused_bgs_mutex);
if (ret && ret != -ENOSPC)
goto error;
if (ret == -ENOSPC) {
key.type = BTRFS_DEV_EXTENT_KEY;
do {
- mutex_lock(&root->fs_info->delete_unused_bgs_mutex);
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
- if (ret < 0) {
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
+ if (ret < 0)
goto done;
- }
ret = btrfs_previous_item(root, path, 0, key.type);
- if (ret)
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
if (ret < 0)
goto done;
if (ret) {
btrfs_item_key_to_cpu(l, &key, path->slots[0]);
if (key.objectid != device->devid) {
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
btrfs_release_path(path);
break;
}
length = btrfs_dev_extent_length(l, dev_extent);
if (key.offset + length <= new_size) {
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
btrfs_release_path(path);
break;
}
btrfs_release_path(path);
ret = btrfs_relocate_chunk(root, chunk_objectid, chunk_offset);
- mutex_unlock(&root->fs_info->delete_unused_bgs_mutex);
if (ret && ret != -ENOSPC)
goto done;
if (ret == -ENOSPC)