]> Pileus Git - ~andy/linux/blobdiff - fs/btrfs/transaction.c
Merge git://www.linux-watchdog.org/linux-watchdog
[~andy/linux] / fs / btrfs / transaction.c
index f21f39f0b1a1ccfdb42772752e078bf376ef4f58..87fac9a21ea56578625536ac1229678e854ec5f7 100644 (file)
@@ -30,6 +30,7 @@
 #include "tree-log.h"
 #include "inode-map.h"
 #include "volumes.h"
+#include "dev-replace.h"
 
 #define BTRFS_ROOT_TRANS_TAG 0
 
@@ -455,28 +456,31 @@ static noinline void wait_for_commit(struct btrfs_root *root,
 int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
 {
        struct btrfs_transaction *cur_trans = NULL, *t;
-       int ret;
+       int ret = 0;
 
-       ret = 0;
        if (transid) {
                if (transid <= root->fs_info->last_trans_committed)
                        goto out;
 
+               ret = -EINVAL;
                /* find specified transaction */
                spin_lock(&root->fs_info->trans_lock);
                list_for_each_entry(t, &root->fs_info->trans_list, list) {
                        if (t->transid == transid) {
                                cur_trans = t;
                                atomic_inc(&cur_trans->use_count);
+                               ret = 0;
                                break;
                        }
-                       if (t->transid > transid)
+                       if (t->transid > transid) {
+                               ret = 0;
                                break;
+                       }
                }
                spin_unlock(&root->fs_info->trans_lock);
-               ret = -EINVAL;
+               /* The specified transaction doesn't exist */
                if (!cur_trans)
-                       goto out;  /* bad transid */
+                       goto out;
        } else {
                /* find newest transaction that is committing | committed */
                spin_lock(&root->fs_info->trans_lock);
@@ -496,9 +500,7 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
        }
 
        wait_for_commit(root, cur_trans);
-
        put_transaction(cur_trans);
-       ret = 0;
 out:
        return ret;
 }
@@ -845,7 +847,9 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
                return ret;
 
        ret = btrfs_run_dev_stats(trans, root->fs_info);
-       BUG_ON(ret);
+       WARN_ON(ret);
+       ret = btrfs_run_dev_replace(trans, root->fs_info);
+       WARN_ON(ret);
 
        ret = btrfs_run_qgroups(trans, root->fs_info);
        BUG_ON(ret);
@@ -868,6 +872,8 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
        switch_commit_root(fs_info->extent_root);
        up_write(&fs_info->extent_commit_sem);
 
+       btrfs_after_dev_replace_commit(fs_info);
+
        return 0;
 }
 
@@ -952,7 +958,6 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
        struct btrfs_fs_info *info = root->fs_info;
        struct btrfs_trans_handle *trans;
        int ret;
-       unsigned long nr;
 
        if (xchg(&root->defrag_running, 1))
                return 0;
@@ -964,9 +969,8 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
 
                ret = btrfs_defrag_leaves(trans, root, cacheonly);
 
-               nr = trans->blocks_used;
                btrfs_end_transaction(trans, root);
-               btrfs_btree_balance_dirty(info->tree_root, nr);
+               btrfs_btree_balance_dirty(info->tree_root);
                cond_resched();
 
                if (btrfs_fs_closing(root->fs_info) || ret != -EAGAIN)
@@ -1186,7 +1190,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
                                    parent_inode, &key,
                                    BTRFS_FT_DIR, index);
        /* We have check then name at the beginning, so it is impossible. */
-       BUG_ON(ret == -EEXIST);
+       BUG_ON(ret == -EEXIST || ret == -EOVERFLOW);
        if (ret) {
                btrfs_abort_transaction(trans, root, ret);
                goto fail;
@@ -1304,9 +1308,10 @@ static void do_async_commit(struct work_struct *work)
         * We've got freeze protection passed with the transaction.
         * Tell lockdep about it.
         */
-       rwsem_acquire_read(
-               &ac->root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
-               0, 1, _THIS_IP_);
+       if (ac->newtrans->type < TRANS_JOIN_NOLOCK)
+               rwsem_acquire_read(
+                    &ac->root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
+                    0, 1, _THIS_IP_);
 
        current->journal_info = ac->newtrans;
 
@@ -1344,8 +1349,10 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
         * Tell lockdep we've released the freeze rwsem, since the
         * async commit thread will be the one to unlock it.
         */
-       rwsem_release(&root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
-                     1, _THIS_IP_);
+       if (trans->type < TRANS_JOIN_NOLOCK)
+               rwsem_release(
+                       &root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
+                       1, _THIS_IP_);
 
        schedule_delayed_work(&ac->work, 0);