Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+64 -14
+58
fs/btrfs/send.c
··· 5805 5805 int ret = 0; 5806 5806 5807 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 5866 inconsistent_snapshot_error(sctx, result, "extent"); 5809 5867 return -EIO; 5810 5868 }
+6 -14
fs/btrfs/tree-log.c
··· 2713 2713 int index, int error) 2714 2714 { 2715 2715 struct btrfs_log_ctx *ctx; 2716 + struct btrfs_log_ctx *safe; 2716 2717 2717 - if (!error) { 2718 - INIT_LIST_HEAD(&root->log_ctxs[index]); 2719 - return; 2720 - } 2721 - 2722 - list_for_each_entry(ctx, &root->log_ctxs[index], list) 2718 + list_for_each_entry_safe(ctx, safe, &root->log_ctxs[index], list) { 2719 + list_del_init(&ctx->list); 2723 2720 ctx->log_ret = error; 2721 + } 2724 2722 2725 2723 INIT_LIST_HEAD(&root->log_ctxs[index]); 2726 2724 } ··· 2959 2961 mutex_unlock(&root->log_mutex); 2960 2962 2961 2963 out_wake_log_root: 2962 - /* 2963 - * We needn't get log_mutex here because we are sure all 2964 - * the other tasks are blocked. 2965 - */ 2964 + mutex_lock(&log_root_tree->log_mutex); 2966 2965 btrfs_remove_all_log_ctxs(log_root_tree, index2, ret); 2967 2966 2968 - mutex_lock(&log_root_tree->log_mutex); 2969 2967 log_root_tree->log_transid_committed++; 2970 2968 atomic_set(&log_root_tree->log_commit[index2], 0); 2971 2969 mutex_unlock(&log_root_tree->log_mutex); ··· 2972 2978 if (waitqueue_active(&log_root_tree->log_commit_wait[index2])) 2973 2979 wake_up(&log_root_tree->log_commit_wait[index2]); 2974 2980 out: 2975 - /* See above. */ 2976 - btrfs_remove_all_log_ctxs(root, index1, ret); 2977 - 2978 2981 mutex_lock(&root->log_mutex); 2982 + btrfs_remove_all_log_ctxs(root, index1, ret); 2979 2983 root->log_transid_committed++; 2980 2984 atomic_set(&root->log_commit[index1], 0); 2981 2985 mutex_unlock(&root->log_mutex);