Commit 169aaaf2 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: introduce new "rescue=ignoremetacsums" mount option



Introduce "rescue=ignoremetacsums" to ignore metadata csums, all the
other metadata sanity checks are still kept as is.

This new mount option is mostly to allow the kernel to mount an
interrupted checksum conversion (at the metadata csum overwrite stage).

And since the main part of metadata sanity checks is inside
tree-checker, we shouldn't lose much safety, and the new mount option is
rescue mount option it requires full read-only mount.

Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent cf31b271
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -732,7 +732,7 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
		 * point, so they are handled as part of the no-checksum case.
		 */
		if (inode && !(inode->flags & BTRFS_INODE_NODATASUM) &&
		    !test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state) &&
		    !test_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state) &&
		    !btrfs_is_data_reloc_root(inode->root)) {
			if (should_async_write(bbio) &&
			    btrfs_wq_submit_bio(bbio, bioc, &smap, mirror_num))
+12 −6
Original line number Diff line number Diff line
@@ -367,6 +367,7 @@ int btrfs_validate_extent_buffer(struct extent_buffer *eb,
	u8 result[BTRFS_CSUM_SIZE];
	const u8 *header_csum;
	int ret = 0;
	const bool ignore_csum = btrfs_test_opt(fs_info, IGNOREMETACSUMS);

	ASSERT(check);

@@ -399,14 +400,17 @@ int btrfs_validate_extent_buffer(struct extent_buffer *eb,

	if (memcmp(result, header_csum, csum_size) != 0) {
		btrfs_warn_rl(fs_info,
"checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d",
"checksum verify failed on logical %llu mirror %u wanted " CSUM_FMT " found " CSUM_FMT " level %d%s",
			      eb->start, eb->read_mirror,
			      CSUM_FMT_VALUE(csum_size, header_csum),
			      CSUM_FMT_VALUE(csum_size, result),
			      btrfs_header_level(eb));
			      btrfs_header_level(eb),
			      ignore_csum ? ", ignored" : "");
		if (!ignore_csum) {
			ret = -EUCLEAN;
			goto out;
		}
	}

	if (found_level != check->level) {
		btrfs_err(fs_info,
@@ -2131,7 +2135,7 @@ static int load_global_roots_objectid(struct btrfs_root *tree_root,
	/* If we have IGNOREDATACSUMS skip loading these roots. */
	if (objectid == BTRFS_CSUM_TREE_OBJECTID &&
	    btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {
		set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
		set_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state);
		return 0;
	}

@@ -2184,7 +2188,7 @@ static int load_global_roots_objectid(struct btrfs_root *tree_root,

	if (!found || ret) {
		if (objectid == BTRFS_CSUM_TREE_OBJECTID)
			set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
			set_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state);

		if (!btrfs_test_opt(fs_info, IGNOREBADROOTS))
			ret = ret ? ret : -ENOENT;
@@ -2865,6 +2869,8 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block

	if (sb_rdonly(sb))
		set_bit(BTRFS_FS_STATE_RO, &fs_info->fs_state);
	if (btrfs_test_opt(fs_info, IGNOREMETACSUMS))
		set_bit(BTRFS_FS_STATE_SKIP_META_CSUMS, &fs_info->fs_state);

	return btrfs_alloc_stripe_hash_table(fs_info);
}
+1 −1
Original line number Diff line number Diff line
@@ -353,7 +353,7 @@ blk_status_t btrfs_lookup_bio_sums(struct btrfs_bio *bbio)
	u32 bio_offset = 0;

	if ((inode->flags & BTRFS_INODE_NODATASUM) ||
	    test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state))
	    test_bit(BTRFS_FS_STATE_NO_DATA_CSUMS, &fs_info->fs_state))
		return BLK_STS_OK;

	/*
+4 −1
Original line number Diff line number Diff line
@@ -98,7 +98,9 @@ enum {
	/* The btrfs_fs_info created for self-tests */
	BTRFS_FS_STATE_DUMMY_FS_INFO,

	BTRFS_FS_STATE_NO_CSUMS,
	/* Checksum errors are ignored. */
	BTRFS_FS_STATE_NO_DATA_CSUMS,
	BTRFS_FS_STATE_SKIP_META_CSUMS,

	/* Indicates there was an error cleaning up a log tree. */
	BTRFS_FS_STATE_LOG_CLEANUP_ERROR,
@@ -224,6 +226,7 @@ enum {
	BTRFS_MOUNT_IGNOREDATACSUMS		= (1UL << 28),
	BTRFS_MOUNT_NODISCARD			= (1UL << 29),
	BTRFS_MOUNT_NOSPACECACHE		= (1UL << 30),
	BTRFS_MOUNT_IGNOREMETACSUMS		= (1UL << 31),
};

/*
+2 −1
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@ static const char fs_state_chars[] = {
	[BTRFS_FS_STATE_TRANS_ABORTED]		= 'A',
	[BTRFS_FS_STATE_DEV_REPLACING]		= 'R',
	[BTRFS_FS_STATE_DUMMY_FS_INFO]		= 0,
	[BTRFS_FS_STATE_NO_CSUMS]		= 'C',
	[BTRFS_FS_STATE_NO_DATA_CSUMS]		= 'C',
	[BTRFS_FS_STATE_SKIP_META_CSUMS]	= 'S',
	[BTRFS_FS_STATE_LOG_CLEANUP_ERROR]	= 'L',
};

Loading