btrfs: fix wrong reservation when doing delayed inode operations
[pandora-kernel.git] / fs / btrfs / delayed-inode.c
index 6462c29..fc515b7 100644 (file)
@@ -297,7 +297,6 @@ struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len)
                item->data_len = data_len;
                item->ins_or_del = 0;
                item->bytes_reserved = 0;
-               item->block_rsv = NULL;
                item->delayed_node = NULL;
                atomic_set(&item->refs, 1);
        }
@@ -593,10 +592,8 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
 
        num_bytes = btrfs_calc_trans_metadata_size(root, 1);
        ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
-       if (!ret) {
+       if (!ret)
                item->bytes_reserved = num_bytes;
-               item->block_rsv = dst_rsv;
-       }
 
        return ret;
 }
@@ -604,10 +601,13 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
 static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
                                                struct btrfs_delayed_item *item)
 {
+       struct btrfs_block_rsv *rsv;
+
        if (!item->bytes_reserved)
                return;
 
-       btrfs_block_rsv_release(root, item->block_rsv,
+       rsv = &root->fs_info->global_block_rsv;
+       btrfs_block_rsv_release(root, rsv,
                                item->bytes_reserved);
 }
 
@@ -1014,6 +1014,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
        struct btrfs_delayed_root *delayed_root;
        struct btrfs_delayed_node *curr_node, *prev_node;
        struct btrfs_path *path;
+       struct btrfs_block_rsv *block_rsv;
        int ret = 0;
 
        path = btrfs_alloc_path();
@@ -1021,6 +1022,9 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        path->leave_spinning = 1;
 
+       block_rsv = trans->block_rsv;
+       trans->block_rsv = &root->fs_info->global_block_rsv;
+
        delayed_root = btrfs_get_delayed_root(root);
 
        curr_node = btrfs_first_delayed_node(delayed_root);
@@ -1045,6 +1049,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
        }
 
        btrfs_free_path(path);
+       trans->block_rsv = block_rsv;
        return ret;
 }
 
@@ -1052,6 +1057,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
                                              struct btrfs_delayed_node *node)
 {
        struct btrfs_path *path;
+       struct btrfs_block_rsv *block_rsv;
        int ret;
 
        path = btrfs_alloc_path();
@@ -1059,6 +1065,9 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        path->leave_spinning = 1;
 
+       block_rsv = trans->block_rsv;
+       trans->block_rsv = &node->root->fs_info->global_block_rsv;
+
        ret = btrfs_insert_delayed_items(trans, path, node->root, node);
        if (!ret)
                ret = btrfs_delete_delayed_items(trans, path, node->root, node);
@@ -1066,6 +1075,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
                ret = btrfs_update_delayed_inode(trans, node->root, path, node);
        btrfs_free_path(path);
 
+       trans->block_rsv = block_rsv;
        return ret;
 }
 
@@ -1116,6 +1126,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
        struct btrfs_path *path;
        struct btrfs_delayed_node *delayed_node = NULL;
        struct btrfs_root *root;
+       struct btrfs_block_rsv *block_rsv;
        unsigned long nr = 0;
        int need_requeue = 0;
        int ret;
@@ -1134,6 +1145,9 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
        if (IS_ERR(trans))
                goto free_path;
 
+       block_rsv = trans->block_rsv;
+       trans->block_rsv = &root->fs_info->global_block_rsv;
+
        ret = btrfs_insert_delayed_items(trans, path, root, delayed_node);
        if (!ret)
                ret = btrfs_delete_delayed_items(trans, path, root,
@@ -1176,6 +1190,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
 
        nr = trans->blocks_used;
 
+       trans->block_rsv = block_rsv;
        btrfs_end_transaction_dmeta(trans, root);
        __btrfs_btree_balance_dirty(root, nr);
 free_path: