Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
[deliverable/linux.git] / fs / btrfs / transaction.c
index 8c8b80085e754e242f759f242a77289c54da2972..d58cce77fc6c581625c3dd0449c83b6836bf4894 100644 (file)
@@ -63,6 +63,14 @@ static void put_transaction(struct btrfs_transaction *transaction)
        if (atomic_dec_and_test(&transaction->use_count)) {
                BUG_ON(!list_empty(&transaction->list));
                WARN_ON(transaction->delayed_refs.root.rb_node);
+               while (!list_empty(&transaction->pending_chunks)) {
+                       struct extent_map *em;
+
+                       em = list_first_entry(&transaction->pending_chunks,
+                                             struct extent_map, list);
+                       list_del_init(&em->list);
+                       free_extent_map(em);
+               }
                kmem_cache_free(btrfs_transaction_cachep, transaction);
        }
 }
@@ -202,6 +210,7 @@ loop:
 
        INIT_LIST_HEAD(&cur_trans->pending_snapshots);
        INIT_LIST_HEAD(&cur_trans->ordered_operations);
+       INIT_LIST_HEAD(&cur_trans->pending_chunks);
        list_add_tail(&cur_trans->list, &fs_info->trans_list);
        extent_io_tree_init(&cur_trans->dirty_pages,
                             fs_info->btree_inode->i_mapping);
@@ -302,7 +311,8 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
 static inline int is_transaction_blocked(struct btrfs_transaction *trans)
 {
        return (trans->state >= TRANS_STATE_BLOCKED &&
-               trans->state < TRANS_STATE_UNBLOCKED);
+               trans->state < TRANS_STATE_UNBLOCKED &&
+               !trans->aborted);
 }
 
 /* wait for commit against the current transaction to become unblocked
@@ -320,7 +330,8 @@ static void wait_current_trans(struct btrfs_root *root)
                spin_unlock(&root->fs_info->trans_lock);
 
                wait_event(root->fs_info->transaction_wait,
-                          cur_trans->state >= TRANS_STATE_UNBLOCKED);
+                          cur_trans->state >= TRANS_STATE_UNBLOCKED ||
+                          cur_trans->aborted);
                put_transaction(cur_trans);
        } else {
                spin_unlock(&root->fs_info->trans_lock);
@@ -527,7 +538,7 @@ struct btrfs_trans_handle *btrfs_attach_transaction(struct btrfs_root *root)
 }
 
 /*
- * btrfs_attach_transaction() - catch the running transaction
+ * btrfs_attach_transaction_barrier() - catch the running transaction
  *
  * It is similar to the above function, the differentia is this one
  * will wait for all the inactive transactions until they fully
@@ -613,10 +624,11 @@ void btrfs_throttle(struct btrfs_root *root)
 static int should_end_transaction(struct btrfs_trans_handle *trans,
                                  struct btrfs_root *root)
 {
-       int ret;
+       if (root->fs_info->global_block_rsv.space_info->full &&
+           btrfs_should_throttle_delayed_refs(trans, root))
+               return 1;
 
-       ret = btrfs_block_rsv_check(root, &root->fs_info->global_block_rsv, 5);
-       return ret ? 1 : 0;
+       return !!btrfs_block_rsv_check(root, &root->fs_info->global_block_rsv, 5);
 }
 
 int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,
@@ -647,7 +659,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 {
        struct btrfs_transaction *cur_trans = trans->transaction;
        struct btrfs_fs_info *info = root->fs_info;
-       int count = 0;
+       unsigned long cur = trans->delayed_ref_updates;
        int lock = (trans->type != TRANS_JOIN_NOLOCK);
        int err = 0;
 
@@ -676,17 +688,11 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
        if (!list_empty(&trans->new_bgs))
                btrfs_create_pending_block_groups(trans, root);
 
-       while (count < 1) {
-               unsigned long cur = trans->delayed_ref_updates;
+       trans->delayed_ref_updates = 0;
+       if (btrfs_should_throttle_delayed_refs(trans, root)) {
+               cur = max_t(unsigned long, cur, 1);
                trans->delayed_ref_updates = 0;
-               if (cur &&
-                   trans->transaction->delayed_refs.num_heads_ready > 64) {
-                       trans->delayed_ref_updates = 0;
-                       btrfs_run_delayed_refs(trans, root, cur);
-               } else {
-                       break;
-               }
-               count++;
+               btrfs_run_delayed_refs(trans, root, cur);
        }
 
        btrfs_trans_release_metadata(trans, root);
@@ -1392,7 +1398,8 @@ static void wait_current_trans_commit_start(struct btrfs_root *root,
                                            struct btrfs_transaction *trans)
 {
        wait_event(root->fs_info->transaction_blocked_wait,
-                  trans->state >= TRANS_STATE_COMMIT_START);
+                  trans->state >= TRANS_STATE_COMMIT_START ||
+                  trans->aborted);
 }
 
 /*
@@ -1403,7 +1410,8 @@ static void wait_current_trans_commit_start_and_unblock(struct btrfs_root *root,
                                         struct btrfs_transaction *trans)
 {
        wait_event(root->fs_info->transaction_wait,
-                  trans->state >= TRANS_STATE_UNBLOCKED);
+                  trans->state >= TRANS_STATE_UNBLOCKED ||
+                  trans->aborted);
 }
 
 /*
@@ -1622,6 +1630,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
         * start sending their work down.
         */
        cur_trans->delayed_refs.flushing = 1;
+       smp_wmb();
 
        if (!list_empty(&trans->new_bgs))
                btrfs_create_pending_block_groups(trans, root);
This page took 0.026564 seconds and 5 git commands to generate.