Btrfs: stop joining the log transaction if sync log fails
authorMiao Xie <miaox@cn.fujitsu.com>
Thu, 20 Feb 2014 10:08:57 +0000 (18:08 +0800)
committerJosef Bacik <jbacik@fb.com>
Mon, 10 Mar 2014 19:16:44 +0000 (15:16 -0400)
If the log sync fails, there is something wrong in the log tree, we
should not continue to join the log transaction and log the metadata.
What we should do is to do a full commit.

This patch fixes this problem by setting ->last_trans_log_full_commit
to the current transaction id, it will tell the tasks not to join
the log transaction, and do a full commit.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
fs/btrfs/tree-log.c

index 57d4ca7fd5558667779a6ef80cb6f30c4174784c..e2f45fc02610950ac2991faa534b90d4e0827934 100644 (file)
@@ -144,6 +144,12 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
 
        mutex_lock(&root->log_mutex);
        if (root->log_root) {
+               if (ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) ==
+                   trans->transid) {
+                       ret = -EAGAIN;
+                       goto out;
+               }
+
                if (!root->log_start_pid) {
                        root->log_start_pid = current->pid;
                        root->log_multiple_pids = false;
@@ -2527,6 +2533,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                blk_finish_plug(&plug);
                btrfs_abort_transaction(trans, root, ret);
                btrfs_free_logged_extents(log, log_transid);
+               ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) =
+                                                               trans->transid;
                mutex_unlock(&root->log_mutex);
                goto out;
        }
@@ -2569,13 +2577,13 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                        list_del_init(&root_log_ctx.list);
 
                blk_finish_plug(&plug);
+               ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) =
+                                                               trans->transid;
                if (ret != -ENOSPC) {
                        btrfs_abort_transaction(trans, root, ret);
                        mutex_unlock(&log_root_tree->log_mutex);
                        goto out;
                }
-               ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) =
-                                                               trans->transid;
                btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
                btrfs_free_logged_extents(log, log_transid);
                mutex_unlock(&log_root_tree->log_mutex);
@@ -2629,6 +2637,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
                                         EXTENT_DIRTY | EXTENT_NEW);
        blk_finish_plug(&plug);
        if (ret) {
+               ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) =
+                                                               trans->transid;
                btrfs_abort_transaction(trans, root, ret);
                btrfs_free_logged_extents(log, log_transid);
                mutex_unlock(&log_root_tree->log_mutex);
@@ -2657,6 +2667,8 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
         */
        ret = write_ctree_super(trans, root->fs_info->tree_root, 1);
        if (ret) {
+               ACCESS_ONCE(root->fs_info->last_trans_log_full_commit) =
+                                                               trans->transid;
                btrfs_abort_transaction(trans, root, ret);
                goto out_wake_log_root;
        }