|
@@ -3387,6 +3387,11 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans,
|
|
|
ret = btrfs_orphan_reserve_metadata(trans, inode);
|
|
|
ASSERT(!ret);
|
|
|
if (ret) {
|
|
|
+ /*
|
|
|
+ * dec doesn't need spin_lock as ->orphan_block_rsv
|
|
|
+ * would be released only if ->orphan_inodes is
|
|
|
+ * zero.
|
|
|
+ */
|
|
|
atomic_dec(&root->orphan_inodes);
|
|
|
clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
|
|
|
&inode->runtime_flags);
|
|
@@ -3401,12 +3406,17 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans,
|
|
|
if (insert >= 1) {
|
|
|
ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode));
|
|
|
if (ret) {
|
|
|
- atomic_dec(&root->orphan_inodes);
|
|
|
if (reserve) {
|
|
|
clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
|
|
|
&inode->runtime_flags);
|
|
|
btrfs_orphan_release_metadata(inode);
|
|
|
}
|
|
|
+ /*
|
|
|
+ * btrfs_orphan_commit_root may race with us and set
|
|
|
+ * ->orphan_block_rsv to zero, in order to avoid that,
|
|
|
+ * decrease ->orphan_inodes after everything is done.
|
|
|
+ */
|
|
|
+ atomic_dec(&root->orphan_inodes);
|
|
|
if (ret != -EEXIST) {
|
|
|
clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
|
|
|
&inode->runtime_flags);
|
|
@@ -3438,28 +3448,26 @@ static int btrfs_orphan_del(struct btrfs_trans_handle *trans,
|
|
|
{
|
|
|
struct btrfs_root *root = inode->root;
|
|
|
int delete_item = 0;
|
|
|
- int release_rsv = 0;
|
|
|
int ret = 0;
|
|
|
|
|
|
- spin_lock(&root->orphan_lock);
|
|
|
if (test_and_clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
|
|
|
&inode->runtime_flags))
|
|
|
delete_item = 1;
|
|
|
|
|
|
+ if (delete_item && trans)
|
|
|
+ ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode));
|
|
|
+
|
|
|
if (test_and_clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
|
|
|
&inode->runtime_flags))
|
|
|
- release_rsv = 1;
|
|
|
- spin_unlock(&root->orphan_lock);
|
|
|
+ btrfs_orphan_release_metadata(inode);
|
|
|
|
|
|
- if (delete_item) {
|
|
|
+ /*
|
|
|
+ * btrfs_orphan_commit_root may race with us and set ->orphan_block_rsv
|
|
|
+ * to zero, in order to avoid that, decrease ->orphan_inodes after
|
|
|
+ * everything is done.
|
|
|
+ */
|
|
|
+ if (delete_item)
|
|
|
atomic_dec(&root->orphan_inodes);
|
|
|
- if (trans)
|
|
|
- ret = btrfs_del_orphan_item(trans, root,
|
|
|
- btrfs_ino(inode));
|
|
|
- }
|
|
|
-
|
|
|
- if (release_rsv)
|
|
|
- btrfs_orphan_release_metadata(inode);
|
|
|
|
|
|
return ret;
|
|
|
}
|