|
@@ -1980,6 +1980,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
|
|
int ret;
|
|
|
struct btrfs_root *log = root->log_root;
|
|
|
struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;
|
|
|
+ u64 log_transid = 0;
|
|
|
|
|
|
mutex_lock(&root->log_mutex);
|
|
|
index1 = root->log_transid % 2;
|
|
@@ -1994,12 +1995,13 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
|
|
if (atomic_read(&root->log_commit[(index1 + 1) % 2]))
|
|
|
wait_log_commit(trans, root, root->log_transid - 1);
|
|
|
|
|
|
- while (root->log_multiple_pids) {
|
|
|
+ while (1) {
|
|
|
unsigned long batch = root->log_batch;
|
|
|
- mutex_unlock(&root->log_mutex);
|
|
|
- schedule_timeout_uninterruptible(1);
|
|
|
- mutex_lock(&root->log_mutex);
|
|
|
-
|
|
|
+ if (root->log_multiple_pids) {
|
|
|
+ mutex_unlock(&root->log_mutex);
|
|
|
+ schedule_timeout_uninterruptible(1);
|
|
|
+ mutex_lock(&root->log_mutex);
|
|
|
+ }
|
|
|
wait_for_writer(trans, root);
|
|
|
if (batch == root->log_batch)
|
|
|
break;
|
|
@@ -2012,12 +2014,16 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages);
|
|
|
+ /* we start IO on all the marked extents here, but we don't actually
|
|
|
+ * wait for them until later.
|
|
|
+ */
|
|
|
+ ret = btrfs_write_marked_extents(log, &log->dirty_log_pages);
|
|
|
BUG_ON(ret);
|
|
|
|
|
|
btrfs_set_root_node(&log->root_item, log->node);
|
|
|
|
|
|
root->log_batch = 0;
|
|
|
+ log_transid = root->log_transid;
|
|
|
root->log_transid++;
|
|
|
log->log_transid = root->log_transid;
|
|
|
root->log_start_pid = 0;
|
|
@@ -2046,6 +2052,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
|
|
|
|
|
index2 = log_root_tree->log_transid % 2;
|
|
|
if (atomic_read(&log_root_tree->log_commit[index2])) {
|
|
|
+ btrfs_wait_marked_extents(log, &log->dirty_log_pages);
|
|
|
wait_log_commit(trans, log_root_tree,
|
|
|
log_root_tree->log_transid);
|
|
|
mutex_unlock(&log_root_tree->log_mutex);
|
|
@@ -2065,6 +2072,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
|
|
* check the full commit flag again
|
|
|
*/
|
|
|
if (root->fs_info->last_trans_log_full_commit == trans->transid) {
|
|
|
+ btrfs_wait_marked_extents(log, &log->dirty_log_pages);
|
|
|
mutex_unlock(&log_root_tree->log_mutex);
|
|
|
ret = -EAGAIN;
|
|
|
goto out_wake_log_root;
|
|
@@ -2073,6 +2081,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
|
|
ret = btrfs_write_and_wait_marked_extents(log_root_tree,
|
|
|
&log_root_tree->dirty_log_pages);
|
|
|
BUG_ON(ret);
|
|
|
+ btrfs_wait_marked_extents(log, &log->dirty_log_pages);
|
|
|
|
|
|
btrfs_set_super_log_root(&root->fs_info->super_for_commit,
|
|
|
log_root_tree->node->start);
|
|
@@ -2092,9 +2101,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
|
|
|
* the running transaction open, so a full commit can't hop
|
|
|
* in and cause problems either.
|
|
|
*/
|
|
|
- write_ctree_super(trans, root->fs_info->tree_root, 2);
|
|
|
+ write_ctree_super(trans, root->fs_info->tree_root, 1);
|
|
|
ret = 0;
|
|
|
|
|
|
+ mutex_lock(&root->log_mutex);
|
|
|
+ if (root->last_log_commit < log_transid)
|
|
|
+ root->last_log_commit = log_transid;
|
|
|
+ mutex_unlock(&root->log_mutex);
|
|
|
+
|
|
|
out_wake_log_root:
|
|
|
atomic_set(&log_root_tree->log_commit[index2], 0);
|
|
|
smp_mb();
|
|
@@ -2862,6 +2876,21 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int inode_in_log(struct btrfs_trans_handle *trans,
|
|
|
+ struct inode *inode)
|
|
|
+{
|
|
|
+ struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ mutex_lock(&root->log_mutex);
|
|
|
+ if (BTRFS_I(inode)->logged_trans == trans->transid &&
|
|
|
+ BTRFS_I(inode)->last_sub_trans <= root->last_log_commit)
|
|
|
+ ret = 1;
|
|
|
+ mutex_unlock(&root->log_mutex);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
* helper function around btrfs_log_inode to make sure newly created
|
|
|
* parent directories also end up in the log. A minimal inode and backref
|
|
@@ -2901,6 +2930,11 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
|
|
|
if (ret)
|
|
|
goto end_no_trans;
|
|
|
|
|
|
+ if (inode_in_log(trans, inode)) {
|
|
|
+ ret = BTRFS_NO_LOG_SYNC;
|
|
|
+ goto end_no_trans;
|
|
|
+ }
|
|
|
+
|
|
|
start_log_trans(trans, root);
|
|
|
|
|
|
ret = btrfs_log_inode(trans, root, inode, inode_only);
|