aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.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/disk-io.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/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7af9a1978a2f..6efaee8d7739 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4129,6 +4129,25 @@ again:
4129 return 0; 4129 return 0;
4130} 4130}
4131 4131
4132static void btrfs_free_pending_ordered(struct btrfs_transaction *cur_trans,
4133 struct btrfs_fs_info *fs_info)
4134{
4135 struct btrfs_ordered_extent *ordered;
4136
4137 spin_lock(&fs_info->trans_lock);
4138 while (!list_empty(&cur_trans->pending_ordered)) {
4139 ordered = list_first_entry(&cur_trans->pending_ordered,
4140 struct btrfs_ordered_extent,
4141 trans_list);
4142 list_del_init(&ordered->trans_list);
4143 spin_unlock(&fs_info->trans_lock);
4144
4145 btrfs_put_ordered_extent(ordered);
4146 spin_lock(&fs_info->trans_lock);
4147 }
4148 spin_unlock(&fs_info->trans_lock);
4149}
4150
4132void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, 4151void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
4133 struct btrfs_root *root) 4152 struct btrfs_root *root)
4134{ 4153{
@@ -4140,6 +4159,7 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
4140 cur_trans->state = TRANS_STATE_UNBLOCKED; 4159 cur_trans->state = TRANS_STATE_UNBLOCKED;
4141 wake_up(&root->fs_info->transaction_wait); 4160 wake_up(&root->fs_info->transaction_wait);
4142 4161
4162 btrfs_free_pending_ordered(cur_trans, root->fs_info);
4143 btrfs_destroy_delayed_inodes(root); 4163 btrfs_destroy_delayed_inodes(root);
4144 btrfs_assert_delayed_root_empty(root); 4164 btrfs_assert_delayed_root_empty(root);
4145 4165