Message ID | 20200518111450.30771-1-fdmanana@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/4] Btrfs: fix corrupt log due to concurrent fsync of inodes with shared extents | expand |
On Mon, May 18, 2020 at 12:14:50PM +0100, fdmanana@kernel.org wrote: > From: Filipe Manana <fdmanana@suse.com> > CC: stable@vger.kernel.org # 4.4+ > Signed-off-by: Filipe Manana <fdmanana@suse.com> Thanks, 1-4 added to misc-next.
Hi [This is an automated email] This commit has been processed because it contains a -stable tag. The stable tag indicates that it's relevant for the following trees: 4.4+ The bot has tested the following trees: v5.6.13, v5.4.41, v4.19.123, v4.14.180, v4.9.223, v4.4.223. v5.6.13: Failed to apply! Possible dependencies: 0024652895e3 ("btrfs: rename btrfs_put_fs_root and btrfs_grab_fs_root") 02162a0265eb ("btrfs: hold a ref on the root in __btrfs_run_defrag_inode") 04734e844894 ("btrfs: hold a ref on the root in btrfs_ioctl_get_subvol_info") 0b530bc5e11f ("btrfs: hold a ref on the root in build_backref_tree") 0d4b0463011d ("btrfs: export and rename free_fs_info") 2a2b5d620266 ("btrfs: hold ref on root in btrfs_ioctl_default_subvol") 3ca35e839e94 ("btrfs: hold a ref on the root in search_ioctl") 3d7babdcf2cc ("btrfs: hold a ref on the root in find_data_references") 41a2ee75aab0 ("btrfs: introduce per-inode file extent tree") 442b1ac5244e ("btrfs: hold a ref on the root in record_reloc_root_in_trans") 4c78e9f59632 ("btrfs: hold a ref on the root in open_ctree") 76deacf02387 ("btrfs: hold a ref on the root in create_reloc_inode") 81f096edf047 ("btrfs: use btrfs_put_fs_root to free roots always") 8727002f7909 ("btrfs: hold a ref on the root in fixup_tree_root_location") 88234012beaa ("btrfs: hold a ref on the root in btrfs_search_path_in_tree") 9326f76f4bc4 ("btrfs: hold a ref on the root in resolve_indirect_ref") 9f583209f20a ("btrfs: push grab_fs_root into read_fs_root") ab9737bd7597 ("btrfs: hold a ref on the root in merge_reloc_roots") b8a49ae1913f ("btrfs: hold a ref on the root in btrfs_search_path_in_tree_user") bc44d7c4b2b1 ("btrfs: push btrfs_grab_fs_root into btrfs_get_fs_root") bdf70b9e75f5 ("btrfs: hold a root ref in btrfs_get_dentry") db2c2ca2db44 ("btrfs: hold a ref on the root in prepare_to_merge") fc92f79856aa ("btrfs: hold a ref on the root in create_subvol") v5.4.41: Failed to apply! Possible dependencies: 0024652895e3 ("btrfs: rename btrfs_put_fs_root and btrfs_grab_fs_root") 0d4b0463011d ("btrfs: export and rename free_fs_info") 33ca832fefa5 ("btrfs: separate out the extent leak code") 41a2ee75aab0 ("btrfs: introduce per-inode file extent tree") 6f0d04f8e72e ("btrfs: separate out the extent io init function") 81f096edf047 ("btrfs: use btrfs_put_fs_root to free roots always") 9326f76f4bc4 ("btrfs: hold a ref on the root in resolve_indirect_ref") 9c7d3a548331 ("btrfs: move extent_io_tree defs to their own header") v4.19.123: Failed to apply! Possible dependencies: 370a11b8114b ("btrfs: qgroup: Introduce per-root swapped blocks infrastructure") 43eb5f297584 ("btrfs: Introduce extent_io_tree::owner to distinguish different io_trees") 57ec5fb478a3 ("btrfs: tests: move testing members of struct btrfs_root to the end") 7b4397386fbd ("btrfs: switch extent_io_tree::track_uptodate to bool") c258d6e36442 ("btrfs: Introduce fs_info to extent_io_tree") e06a1fc99cc7 ("btrfs: Remove extent_io_ops::set_bit_hook extent_io callback") eede2bf34f4f ("Btrfs: prevent ioctls from interfering with a swap file") v4.14.180: Failed to apply! Possible dependencies: 370a11b8114b ("btrfs: qgroup: Introduce per-root swapped blocks infrastructure") 429d6275d501 ("btrfs: qgroup: Fix wrong qgroup reservation update for relationship modification") 57ec5fb478a3 ("btrfs: tests: move testing members of struct btrfs_root to the end") 64cfaef6362f ("btrfs: qgroup: Introduce function to convert META_PREALLOC into META_PERTRANS") 64ee4e751a1c ("btrfs: qgroup: Update trace events to use new separate rsv types") 733e03a0b26a ("btrfs: qgroup: Split meta rsv type into meta_prealloc and meta_pertrans") 8287475a2055 ("btrfs: qgroup: Use root::qgroup_meta_rsv_* to record qgroup meta reserved space") d4e5c92055d8 ("btrfs: qgroup: Skeleton to support separate qgroup reservation type") dba213242fbc ("btrfs: qgroup: Make qgroup_reserve and its callers to use separate reservation type") e1211d0e896b ("btrfs: qgroup: Don't use root->qgroup_meta_rsv for qgroup") eede2bf34f4f ("Btrfs: prevent ioctls from interfering with a swap file") f59c0347d4be ("btrfs: qgroup: Introduce helpers to update and access new qgroup rsv") fd708b81d972 ("Btrfs: add a extent ref verify tool") v4.9.223: Failed to apply! Possible dependencies: 0c476a5d7f63 ("btrfs: Ensure proper sector alignment for btrfs_free_reserved_data_space") 370a11b8114b ("btrfs: qgroup: Introduce per-root swapped blocks infrastructure") 4989d277eb4b ("btrfs: refactor __btrfs_lookup_bio_sums to use bio_for_each_segment_all") 62d1f9fe97dd ("btrfs: remove trivial helper btrfs_find_tree_block") da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") eede2bf34f4f ("Btrfs: prevent ioctls from interfering with a swap file") fd708b81d972 ("Btrfs: add a extent ref verify tool") v4.4.223: Failed to apply! Possible dependencies: 2f3165ecf103 ("btrfs: don't force mounts to wait for cleaner_kthread to delete one or more subvolumes") 370a11b8114b ("btrfs: qgroup: Introduce per-root swapped blocks infrastructure") 511711af91f2 ("btrfs: don't run delayed references while we are creating the free space tree") 70f6d82ec73c ("Btrfs: add free space tree mount option") 87241c2e6845 ("Btrfs: use root when checking need_async_flush") 90c711ab380d ("btrfs: avoid blocking open_ctree from cleaner_kthread") 9e7cc91a6d18 ("btrfs: fix fsfreeze hang caused by delayed iputs deal") a5ed91828518 ("Btrfs: implement the free space B-tree") afcdd129e05a ("Btrfs: add a flags field to btrfs_fs_info") d38b349c39a9 ("Btrfs: don't bother kicking async if there's nothing to reclaim") eede2bf34f4f ("Btrfs: prevent ioctls from interfering with a swap file") f376df2b7da3 ("Btrfs: add tracepoints for flush events") NOTE: The patch will not be queued to stable trees until it is upstream. How should we proceed with this patch?
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index e2ae26f6b9d0..69ee6400adc0 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1146,6 +1146,9 @@ struct btrfs_root { /* Record pairs of swapped blocks for qgroup */ struct btrfs_qgroup_swapped_blocks swapped_blocks; + /* Used only by log trees, when logging csum items. */ + struct extent_io_tree log_csum_range; + #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS u64 alloc_bytenr; #endif diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index d10c7be10f3b..91def9fd9456 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1137,9 +1137,12 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, root->log_transid = 0; root->log_transid_committed = -1; root->last_log_commit = 0; - if (!dummy) + if (!dummy) { extent_io_tree_init(fs_info, &root->dirty_log_pages, IO_TREE_ROOT_DIRTY_LOG_PAGES, NULL); + extent_io_tree_init(fs_info, &root->log_csum_range, + IO_TREE_LOG_CSUM_RANGE, NULL); + } memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_item, 0, sizeof(root->root_item)); diff --git a/fs/btrfs/extent-io-tree.h b/fs/btrfs/extent-io-tree.h index b4a7bad3e82e..b6561455b3c4 100644 --- a/fs/btrfs/extent-io-tree.h +++ b/fs/btrfs/extent-io-tree.h @@ -44,6 +44,7 @@ enum { IO_TREE_TRANS_DIRTY_PAGES, IO_TREE_ROOT_DIRTY_LOG_PAGES, IO_TREE_INODE_FILE_EXTENT, + IO_TREE_LOG_CSUM_RANGE, IO_TREE_SELFTEST, }; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1143f557141b..9e34d9fac6df 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3299,6 +3299,7 @@ static void free_log_tree(struct btrfs_trans_handle *trans, clear_extent_bits(&log->dirty_log_pages, 0, (u64)-1, EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT); + extent_io_tree_release(&log->log_csum_range); btrfs_put_root(log); } @@ -3916,9 +3917,21 @@ static int log_csums(struct btrfs_trans_handle *trans, struct btrfs_root *log_root, struct btrfs_ordered_sum *sums) { + const u64 lock_end = sums->bytenr + sums->len - 1; + struct extent_state *cached_state = NULL; int ret; /* + * Serialize logging for checksums. This is to avoid racing with the + * same checksum being logged by another task that is logging another + * file which happens to refer to the same extent as well. Such races + * can leave checksum items in the log with overlapping ranges. + */ + ret = lock_extent_bits(&log_root->log_csum_range, sums->bytenr, + lock_end, &cached_state); + if (ret) + return ret; + /* * Due to extent cloning, we might have logged a csum item that covers a * subrange of a cloned extent, and later we can end up logging a csum * item for a larger subrange of the same extent or the entire range. @@ -3928,10 +3941,13 @@ static int log_csums(struct btrfs_trans_handle *trans, * trim and adjust) any existing csum items in the log for this range. */ ret = btrfs_del_csums(trans, log_root, sums->bytenr, sums->len); - if (ret) - return ret; + if (!ret) + ret = btrfs_csum_file_blocks(trans, log_root, sums); - return btrfs_csum_file_blocks(trans, log_root, sums); + unlock_extent_cached(&log_root->log_csum_range, sums->bytenr, lock_end, + &cached_state); + + return ret; } static noinline int copy_items(struct btrfs_trans_handle *trans, diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h index bcbc763b8814..360b0f9d2220 100644 --- a/include/trace/events/btrfs.h +++ b/include/trace/events/btrfs.h @@ -89,6 +89,7 @@ TRACE_DEFINE_ENUM(COMMIT_TRANS); { IO_TREE_TRANS_DIRTY_PAGES, "TRANS_DIRTY_PAGES" }, \ { IO_TREE_ROOT_DIRTY_LOG_PAGES, "ROOT_DIRTY_LOG_PAGES" }, \ { IO_TREE_INODE_FILE_EXTENT, "INODE_FILE_EXTENT" }, \ + { IO_TREE_LOG_CSUM_RANGE, "LOG_CSUM_RANGE" }, \ { IO_TREE_SELFTEST, "SELFTEST" }) #define BTRFS_GROUP_FLAGS \