aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-28 13:07:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-28 13:07:35 -0400
commitf6167514c819cb7794e60cf36b9466598a789013 (patch)
tree53cd063b30ad8314d57f1a58a4c2d27b968a55f2
parent2cd0b50a189febfe1855b13be98297a621864741 (diff)
parent570dd45042a7c8a7aba1ee029c5dd0f5ccf41b9b (diff)
Merge branch 'for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "My patch fixes the btrfs list_head abuse that we tracked down during Dave Jones' memory corruption investigation. With both Jens and my patches in place, I'm no longer able to trigger problems. Filipe is fixing a difficult old bug between snapshots, balance and send. Dave is cooking a few more for the next rc, but these are tested and ready" * 'for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: btrfs: fix races on root_log_ctx lists btrfs: fix incremental send failure caused by balance
-rw-r--r--fs/btrfs/send.c58
-rw-r--r--fs/btrfs/tree-log.c20
2 files changed, 64 insertions, 14 deletions
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 01bc36cec26e..71261b459863 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -5805,6 +5805,64 @@ static int changed_extent(struct send_ctx *sctx,
5805 int ret = 0; 5805 int ret = 0;
5806 5806
5807 if (sctx->cur_ino != sctx->cmp_key->objectid) { 5807 if (sctx->cur_ino != sctx->cmp_key->objectid) {
5808
5809 if (result == BTRFS_COMPARE_TREE_CHANGED) {
5810 struct extent_buffer *leaf_l;
5811 struct extent_buffer *leaf_r;
5812 struct btrfs_file_extent_item *ei_l;
5813 struct btrfs_file_extent_item *ei_r;
5814
5815 leaf_l = sctx->left_path->nodes[0];
5816 leaf_r = sctx->right_path->nodes[0];
5817 ei_l = btrfs_item_ptr(leaf_l,
5818 sctx->left_path->slots[0],
5819 struct btrfs_file_extent_item);
5820 ei_r = btrfs_item_ptr(leaf_r,
5821 sctx->right_path->slots[0],
5822 struct btrfs_file_extent_item);
5823
5824 /*
5825 * We may have found an extent item that has changed
5826 * only its disk_bytenr field and the corresponding
5827 * inode item was not updated. This case happens due to
5828 * very specific timings during relocation when a leaf
5829 * that contains file extent items is COWed while
5830 * relocation is ongoing and its in the stage where it
5831 * updates data pointers. So when this happens we can
5832 * safely ignore it since we know it's the same extent,
5833 * but just at different logical and physical locations
5834 * (when an extent is fully replaced with a new one, we
5835 * know the generation number must have changed too,
5836 * since snapshot creation implies committing the current
5837 * transaction, and the inode item must have been updated
5838 * as well).
5839 * This replacement of the disk_bytenr happens at
5840 * relocation.c:replace_file_extents() through
5841 * relocation.c:btrfs_reloc_cow_block().
5842 */
5843 if (btrfs_file_extent_generation(leaf_l, ei_l) ==
5844 btrfs_file_extent_generation(leaf_r, ei_r) &&
5845 btrfs_file_extent_ram_bytes(leaf_l, ei_l) ==
5846 btrfs_file_extent_ram_bytes(leaf_r, ei_r) &&
5847 btrfs_file_extent_compression(leaf_l, ei_l) ==
5848 btrfs_file_extent_compression(leaf_r, ei_r) &&
5849 btrfs_file_extent_encryption(leaf_l, ei_l) ==
5850 btrfs_file_extent_encryption(leaf_r, ei_r) &&
5851 btrfs_file_extent_other_encoding(leaf_l, ei_l) ==
5852 btrfs_file_extent_other_encoding(leaf_r, ei_r) &&
5853 btrfs_file_extent_type(leaf_l, ei_l) ==
5854 btrfs_file_extent_type(leaf_r, ei_r) &&
5855 btrfs_file_extent_disk_bytenr(leaf_l, ei_l) !=
5856 btrfs_file_extent_disk_bytenr(leaf_r, ei_r) &&
5857 btrfs_file_extent_disk_num_bytes(leaf_l, ei_l) ==
5858 btrfs_file_extent_disk_num_bytes(leaf_r, ei_r) &&
5859 btrfs_file_extent_offset(leaf_l, ei_l) ==
5860 btrfs_file_extent_offset(leaf_r, ei_r) &&
5861 btrfs_file_extent_num_bytes(leaf_l, ei_l) ==
5862 btrfs_file_extent_num_bytes(leaf_r, ei_r))
5863 return 0;
5864 }
5865
5808 inconsistent_snapshot_error(sctx, result, "extent"); 5866 inconsistent_snapshot_error(sctx, result, "extent");
5809 return -EIO; 5867 return -EIO;
5810 } 5868 }
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 528cae123dc9..3d33c4e41e5f 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2713,14 +2713,12 @@ static inline void btrfs_remove_all_log_ctxs(struct btrfs_root *root,
2713 int index, int error) 2713 int index, int error)
2714{ 2714{
2715 struct btrfs_log_ctx *ctx; 2715 struct btrfs_log_ctx *ctx;
2716 struct btrfs_log_ctx *safe;
2716 2717
2717 if (!error) { 2718 list_for_each_entry_safe(ctx, safe, &root->log_ctxs[index], list) {
2718 INIT_LIST_HEAD(&root->log_ctxs[index]); 2719 list_del_init(&ctx->list);
2719 return;
2720 }
2721
2722 list_for_each_entry(ctx, &root->log_ctxs[index], list)
2723 ctx->log_ret = error; 2720 ctx->log_ret = error;
2721 }
2724 2722
2725 INIT_LIST_HEAD(&root->log_ctxs[index]); 2723 INIT_LIST_HEAD(&root->log_ctxs[index]);
2726} 2724}
@@ -2961,13 +2959,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
2961 mutex_unlock(&root->log_mutex); 2959 mutex_unlock(&root->log_mutex);
2962 2960
2963out_wake_log_root: 2961out_wake_log_root:
2964 /* 2962 mutex_lock(&log_root_tree->log_mutex);
2965 * We needn't get log_mutex here because we are sure all
2966 * the other tasks are blocked.
2967 */
2968 btrfs_remove_all_log_ctxs(log_root_tree, index2, ret); 2963 btrfs_remove_all_log_ctxs(log_root_tree, index2, ret);
2969 2964
2970 mutex_lock(&log_root_tree->log_mutex);
2971 log_root_tree->log_transid_committed++; 2965 log_root_tree->log_transid_committed++;
2972 atomic_set(&log_root_tree->log_commit[index2], 0); 2966 atomic_set(&log_root_tree->log_commit[index2], 0);
2973 mutex_unlock(&log_root_tree->log_mutex); 2967 mutex_unlock(&log_root_tree->log_mutex);
@@ -2978,10 +2972,8 @@ out_wake_log_root:
2978 if (waitqueue_active(&log_root_tree->log_commit_wait[index2])) 2972 if (waitqueue_active(&log_root_tree->log_commit_wait[index2]))
2979 wake_up(&log_root_tree->log_commit_wait[index2]); 2973 wake_up(&log_root_tree->log_commit_wait[index2]);
2980out: 2974out:
2981 /* See above. */
2982 btrfs_remove_all_log_ctxs(root, index1, ret);
2983
2984 mutex_lock(&root->log_mutex); 2975 mutex_lock(&root->log_mutex);
2976 btrfs_remove_all_log_ctxs(root, index1, ret);
2985 root->log_transid_committed++; 2977 root->log_transid_committed++;
2986 atomic_set(&root->log_commit[index1], 0); 2978 atomic_set(&root->log_commit[index1], 0);
2987 mutex_unlock(&root->log_mutex); 2979 mutex_unlock(&root->log_mutex);