btrfs: introduce delayed_refs_rsv
[sfrench/cifs-2.6.git] / fs / btrfs / transaction.c
index d1eeef9ec5dac512faa62e50766602dc9f110223..e18eb75e6fa36ca3dba738d116c38e84dd3a8dae 100644 (file)
@@ -233,14 +233,12 @@ loop:
        extwriter_counter_init(cur_trans, type);
        init_waitqueue_head(&cur_trans->writer_wait);
        init_waitqueue_head(&cur_trans->commit_wait);
-       init_waitqueue_head(&cur_trans->pending_wait);
        cur_trans->state = TRANS_STATE_RUNNING;
        /*
         * One for this trans handle, one so it will live on until we
         * commit the transaction.
         */
        refcount_set(&cur_trans->use_count, 2);
-       atomic_set(&cur_trans->pending_ordered, 0);
        cur_trans->flags = 0;
        cur_trans->start_time = ktime_get_seconds();
 
@@ -456,7 +454,7 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
                  bool enforce_qgroups)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
-
+       struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv;
        struct btrfs_trans_handle *h;
        struct btrfs_transaction *cur_trans;
        u64 num_bytes = 0;
@@ -485,13 +483,28 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
         * the appropriate flushing if need be.
         */
        if (num_items && root != fs_info->chunk_root) {
+               struct btrfs_block_rsv *rsv = &fs_info->trans_block_rsv;
+               u64 delayed_refs_bytes = 0;
+
                qgroup_reserved = num_items * fs_info->nodesize;
                ret = btrfs_qgroup_reserve_meta_pertrans(root, qgroup_reserved,
                                enforce_qgroups);
                if (ret)
                        return ERR_PTR(ret);
 
+               /*
+                * We want to reserve all the bytes we may need all at once, so
+                * we only do 1 enospc flushing cycle per transaction start.  We
+                * accomplish this by simply assuming we'll do 2 x num_items
+                * worth of delayed refs updates in this trans handle, and
+                * refill that amount for whatever is missing in the reserve.
+                */
                num_bytes = btrfs_calc_trans_metadata_size(fs_info, num_items);
+               if (delayed_refs_rsv->full == 0) {
+                       delayed_refs_bytes = num_bytes;
+                       num_bytes <<= 1;
+               }
+
                /*
                 * Do the reservation for the relocation root creation
                 */
@@ -500,8 +513,24 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
                        reloc_reserved = true;
                }
 
-               ret = btrfs_block_rsv_add(root, &fs_info->trans_block_rsv,
-                                         num_bytes, flush);
+               ret = btrfs_block_rsv_add(root, rsv, num_bytes, flush);
+               if (ret)
+                       goto reserve_fail;
+               if (delayed_refs_bytes) {
+                       btrfs_migrate_to_delayed_refs_rsv(fs_info, rsv,
+                                                         delayed_refs_bytes);
+                       num_bytes -= delayed_refs_bytes;
+               }
+       } else if (num_items == 0 && flush == BTRFS_RESERVE_FLUSH_ALL &&
+                  !delayed_refs_rsv->full) {
+               /*
+                * Some people call with btrfs_start_transaction(root, 0)
+                * because they can be throttled, but have some other mechanism
+                * for reserving space.  We still want these guys to refill the
+                * delayed block_rsv so just add 1 items worth of reservation
+                * here.
+                */
+               ret = btrfs_delayed_refs_rsv_refill(fs_info, flush);
                if (ret)
                        goto reserve_fail;
        }
@@ -1842,7 +1871,6 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_transaction *cur_trans = trans->transaction;
-       DEFINE_WAIT(wait);
 
        WARN_ON(refcount_read(&trans->use_count) > 1);
 
@@ -1911,13 +1939,6 @@ static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
                btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
 }
 
-static inline void
-btrfs_wait_pending_ordered(struct btrfs_transaction *cur_trans)
-{
-       wait_event(cur_trans->pending_wait,
-                  atomic_read(&cur_trans->pending_ordered) == 0);
-}
-
 int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -2052,8 +2073,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 
        btrfs_wait_delalloc_flush(fs_info);
 
-       btrfs_wait_pending_ordered(cur_trans);
-
        btrfs_scrub_pause(fs_info);
        /*
         * Ok now we need to make sure to block out any other joins while we