aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2014-11-21 14:52:38 -0500
committerChris Mason <clm@fb.com>2014-11-21 14:58:32 -0500
commit50d9aa99bd35c77200e0e3dd7a72274f8304701f (patch)
tree346a80fdf2343a5c5e010b57b0213c989eed4ac8 /fs/btrfs/tree-log.c
parent9dba8cf128ef98257ca719722280c9634e7e9dc7 (diff)
Btrfs: make sure logged extents complete in the current transaction V3
Liu Bo pointed out that my previous fix would lose the generation update in the scenario I described. It is actually much worse than that, we could lose the entire extent if we lose power right after the transaction commits. Consider the following write extent 0-4k log extent in log tree commit transaction < power fail happens here ordered extent completes We would lose the 0-4k extent because it hasn't updated the actual fs tree, and the transaction commit will reset the log so it isn't replayed. If we lose power before the transaction commit we are save, otherwise we are not. Fix this by keeping track of all extents we logged in this transaction. Then when we go to commit the transaction make sure we wait for all of those ordered extents to complete before proceeding. This will make sure that if we lose power after the transaction commit we still have our data. This also fixes the problem of the improperly updated extent generation. Thanks, cc: stable@vger.kernel.org Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index fc715ff31d26..7d96cc961663 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2600,7 +2600,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2600 if (atomic_read(&log_root_tree->log_commit[index2])) { 2600 if (atomic_read(&log_root_tree->log_commit[index2])) {
2601 blk_finish_plug(&plug); 2601 blk_finish_plug(&plug);
2602 btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark); 2602 btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
2603 btrfs_wait_logged_extents(log, log_transid); 2603 btrfs_wait_logged_extents(trans, log, log_transid);
2604 wait_log_commit(trans, log_root_tree, 2604 wait_log_commit(trans, log_root_tree,
2605 root_log_ctx.log_transid); 2605 root_log_ctx.log_transid);
2606 mutex_unlock(&log_root_tree->log_mutex); 2606 mutex_unlock(&log_root_tree->log_mutex);
@@ -2645,7 +2645,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2645 btrfs_wait_marked_extents(log_root_tree, 2645 btrfs_wait_marked_extents(log_root_tree,
2646 &log_root_tree->dirty_log_pages, 2646 &log_root_tree->dirty_log_pages,
2647 EXTENT_NEW | EXTENT_DIRTY); 2647 EXTENT_NEW | EXTENT_DIRTY);
2648 btrfs_wait_logged_extents(log, log_transid); 2648 btrfs_wait_logged_extents(trans, log, log_transid);
2649 2649
2650 btrfs_set_super_log_root(root->fs_info->super_for_commit, 2650 btrfs_set_super_log_root(root->fs_info->super_for_commit,
2651 log_root_tree->node->start); 2651 log_root_tree->node->start);
@@ -3766,7 +3766,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
3766 fi = btrfs_item_ptr(leaf, path->slots[0], 3766 fi = btrfs_item_ptr(leaf, path->slots[0],
3767 struct btrfs_file_extent_item); 3767 struct btrfs_file_extent_item);
3768 3768
3769 btrfs_set_token_file_extent_generation(leaf, fi, em->generation, 3769 btrfs_set_token_file_extent_generation(leaf, fi, trans->transid,
3770 &token); 3770 &token);
3771 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) 3771 if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
3772 btrfs_set_token_file_extent_type(leaf, fi, 3772 btrfs_set_token_file_extent_type(leaf, fi,