btrfs: introduce delayed_refs_rsv
[sfrench/cifs-2.6.git] / fs / btrfs / delayed-ref.c
index 48725fa757a3e28bb085731823fec315cff1421f..cad36c99a483ca8f6c508c32c3ad2ce94289f114 100644 (file)
@@ -473,12 +473,14 @@ inserted:
  * helper function to update the accounting in the head ref
  * existing and update must have the same bytenr
  */
-static noinline void
-update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs,
+static noinline void update_existing_head_ref(struct btrfs_trans_handle *trans,
                         struct btrfs_delayed_ref_head *existing,
                         struct btrfs_delayed_ref_head *update,
                         int *old_ref_mod_ret)
 {
+       struct btrfs_delayed_ref_root *delayed_refs =
+               &trans->transaction->delayed_refs;
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        int old_ref_mod;
 
        BUG_ON(existing->is_data != update->is_data);
@@ -536,10 +538,18 @@ update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs,
         * versa we need to make sure to adjust pending_csums accordingly.
         */
        if (existing->is_data) {
-               if (existing->total_ref_mod >= 0 && old_ref_mod < 0)
+               u64 csum_leaves =
+                       btrfs_csum_bytes_to_leaves(fs_info,
+                                                  existing->num_bytes);
+
+               if (existing->total_ref_mod >= 0 && old_ref_mod < 0) {
                        delayed_refs->pending_csums -= existing->num_bytes;
-               if (existing->total_ref_mod < 0 && old_ref_mod >= 0)
+                       btrfs_delayed_refs_rsv_release(fs_info, csum_leaves);
+               }
+               if (existing->total_ref_mod < 0 && old_ref_mod >= 0) {
                        delayed_refs->pending_csums += existing->num_bytes;
+                       trans->delayed_ref_updates += csum_leaves;
+               }
        }
        spin_unlock(&existing->lock);
 }
@@ -645,7 +655,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
                        && head_ref->qgroup_reserved
                        && existing->qgroup_ref_root
                        && existing->qgroup_reserved);
-               update_existing_head_ref(delayed_refs, existing, head_ref,
+               update_existing_head_ref(trans, existing, head_ref,
                                         old_ref_mod);
                /*
                 * we've updated the existing ref, free the newly
@@ -656,8 +666,12 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
        } else {
                if (old_ref_mod)
                        *old_ref_mod = 0;
-               if (head_ref->is_data && head_ref->ref_mod < 0)
+               if (head_ref->is_data && head_ref->ref_mod < 0) {
                        delayed_refs->pending_csums += head_ref->num_bytes;
+                       trans->delayed_ref_updates +=
+                               btrfs_csum_bytes_to_leaves(trans->fs_info,
+                                                          head_ref->num_bytes);
+               }
                delayed_refs->num_heads++;
                delayed_refs->num_heads_ready++;
                atomic_inc(&delayed_refs->num_entries);
@@ -793,6 +807,12 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
        ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node);
        spin_unlock(&delayed_refs->lock);
 
+       /*
+        * Need to update the delayed_refs_rsv with any changes we may have
+        * made.
+        */
+       btrfs_update_delayed_refs_rsv(trans);
+
        trace_add_delayed_tree_ref(fs_info, &ref->node, ref,
                                   action == BTRFS_ADD_DELAYED_EXTENT ?
                                   BTRFS_ADD_DELAYED_REF : action);
@@ -874,6 +894,12 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
        ret = insert_delayed_ref(trans, delayed_refs, head_ref, &ref->node);
        spin_unlock(&delayed_refs->lock);
 
+       /*
+        * Need to update the delayed_refs_rsv with any changes we may have
+        * made.
+        */
+       btrfs_update_delayed_refs_rsv(trans);
+
        trace_add_delayed_data_ref(trans->fs_info, &ref->node, ref,
                                   action == BTRFS_ADD_DELAYED_EXTENT ?
                                   BTRFS_ADD_DELAYED_REF : action);
@@ -910,6 +936,12 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
                             NULL, NULL, NULL);
 
        spin_unlock(&delayed_refs->lock);
+
+       /*
+        * Need to update the delayed_refs_rsv with any changes we may have
+        * made.
+        */
+       btrfs_update_delayed_refs_rsv(trans);
        return 0;
 }