int need_commit = 2;
int have_pinned_space;
int have_bg_delete_sem = 0;
- bool free_space_inode = btrfs_is_free_space_inode(inode);
/* make sure bytes are sectorsize aligned */
bytes = ALIGN(bytes, root->sectorsize);
- if (free_space_inode) {
+ if (btrfs_is_free_space_inode(inode)) {
need_commit = 0;
ASSERT(current->journal_info);
}
- /*
- * Here we shouldn't call down_read(bg_delete_sem) for free space inode,
- * there is lock order between bg_delete_sem and "wait current trans
- * finished". Meanwhile because we only do the data space reservation
- * for free space cache in the transaction context,
- * btrfs_delete_unused_bgs() will either have finished its job, or start
- * a new transaction waiting current transaction to complete, there will
- * be no unused block groups to be deleted, so it's safe to not call
- * down_read(bg_delete_sem).
- */
data_sinfo = fs_info->data_sinfo;
if (!data_sinfo) {
- if (!free_space_inode) {
- down_read(&root->fs_info->bg_delete_sem);
- have_bg_delete_sem = 1;
- }
+ down_read(&root->fs_info->bg_delete_sem);
+ have_bg_delete_sem = 1;
goto alloc;
}
* We may need to allocate new chunk, so we should block
* btrfs_delete_unused_bgs()
*/
- if (!have_bg_delete_sem && !free_space_inode) {
+ if (!have_bg_delete_sem) {
spin_unlock(&data_sinfo->lock);
down_read(&root->fs_info->bg_delete_sem);
have_bg_delete_sem = 1;
*/
trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) {
- ret = PTR_ERR(trans);
- goto out;
+ up_read(&root->fs_info->bg_delete_sem);
+ return PTR_ERR(trans);
}
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
CHUNK_ALLOC_NO_FORCE);
btrfs_end_transaction(trans, root);
if (ret < 0) {
- if (ret != -ENOSPC)
- goto out;
- else {
+ if (ret != -ENOSPC) {
+ up_read(&root->fs_info->bg_delete_sem);
+ return ret;
+ } else {
have_pinned_space = 1;
goto commit_trans;
}
trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) {
- ret = PTR_ERR(trans);
- goto out;
+ up_read(&root->fs_info->bg_delete_sem);
+ return PTR_ERR(trans);
}
if (have_pinned_space >= 0 ||
test_bit(BTRFS_TRANS_HAVE_FREE_BGS,
&trans->transaction->flags) ||
need_commit > 0) {
ret = btrfs_commit_transaction(trans, root);
- if (ret)
- goto out;
+ if (ret) {
+ up_read(&root->fs_info->bg_delete_sem);
+ return ret;
+ }
/*
* The cleaner kthread might still be doing iput
* operations. Wait for it to finish so that
trace_btrfs_space_reservation(root->fs_info,
"space_info:enospc",
data_sinfo->flags, bytes, 1);
- ret = -ENOSPC;
- goto out;
+ up_read(&root->fs_info->bg_delete_sem);
+ return -ENOSPC;
}
data_sinfo->bytes_may_use += bytes;
trace_btrfs_space_reservation(root->fs_info, "space_info",
data_sinfo->flags, bytes, 1);
spin_unlock(&data_sinfo->lock);
-out:
- if (have_bg_delete_sem && !free_space_inode)
+ if (have_bg_delete_sem)
up_read(&root->fs_info->bg_delete_sem);
return ret;