162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) STRATO AG 2011.  All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/*
762306a36Sopenharmony_ci * This module can be used to catch cases when the btrfs kernel
862306a36Sopenharmony_ci * code executes write requests to the disk that bring the file
962306a36Sopenharmony_ci * system in an inconsistent state. In such a state, a power-loss
1062306a36Sopenharmony_ci * or kernel panic event would cause that the data on disk is
1162306a36Sopenharmony_ci * lost or at least damaged.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * Code is added that examines all block write requests during
1462306a36Sopenharmony_ci * runtime (including writes of the super block). Three rules
1562306a36Sopenharmony_ci * are verified and an error is printed on violation of the
1662306a36Sopenharmony_ci * rules:
1762306a36Sopenharmony_ci * 1. It is not allowed to write a disk block which is
1862306a36Sopenharmony_ci *    currently referenced by the super block (either directly
1962306a36Sopenharmony_ci *    or indirectly).
2062306a36Sopenharmony_ci * 2. When a super block is written, it is verified that all
2162306a36Sopenharmony_ci *    referenced (directly or indirectly) blocks fulfill the
2262306a36Sopenharmony_ci *    following requirements:
2362306a36Sopenharmony_ci *    2a. All referenced blocks have either been present when
2462306a36Sopenharmony_ci *        the file system was mounted, (i.e., they have been
2562306a36Sopenharmony_ci *        referenced by the super block) or they have been
2662306a36Sopenharmony_ci *        written since then and the write completion callback
2762306a36Sopenharmony_ci *        was called and no write error was indicated and a
2862306a36Sopenharmony_ci *        FLUSH request to the device where these blocks are
2962306a36Sopenharmony_ci *        located was received and completed.
3062306a36Sopenharmony_ci *    2b. All referenced blocks need to have a generation
3162306a36Sopenharmony_ci *        number which is equal to the parent's number.
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * One issue that was found using this module was that the log
3462306a36Sopenharmony_ci * tree on disk became temporarily corrupted because disk blocks
3562306a36Sopenharmony_ci * that had been in use for the log tree had been freed and
3662306a36Sopenharmony_ci * reused too early, while being referenced by the written super
3762306a36Sopenharmony_ci * block.
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci * The search term in the kernel log that can be used to filter
4062306a36Sopenharmony_ci * on the existence of detected integrity issues is
4162306a36Sopenharmony_ci * "btrfs: attempt".
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * The integrity check is enabled via mount options. These
4462306a36Sopenharmony_ci * mount options are only supported if the integrity check
4562306a36Sopenharmony_ci * tool is compiled by defining BTRFS_FS_CHECK_INTEGRITY.
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * Example #1, apply integrity checks to all metadata:
4862306a36Sopenharmony_ci * mount /dev/sdb1 /mnt -o check_int
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci * Example #2, apply integrity checks to all metadata and
5162306a36Sopenharmony_ci * to data extents:
5262306a36Sopenharmony_ci * mount /dev/sdb1 /mnt -o check_int_data
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci * Example #3, apply integrity checks to all metadata and dump
5562306a36Sopenharmony_ci * the tree that the super block references to kernel messages
5662306a36Sopenharmony_ci * each time after a super block was written:
5762306a36Sopenharmony_ci * mount /dev/sdb1 /mnt -o check_int,check_int_print_mask=263
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci * If the integrity check tool is included and activated in
6062306a36Sopenharmony_ci * the mount options, plenty of kernel memory is used, and
6162306a36Sopenharmony_ci * plenty of additional CPU cycles are spent. Enabling this
6262306a36Sopenharmony_ci * functionality is not intended for normal use. In most
6362306a36Sopenharmony_ci * cases, unless you are a btrfs developer who needs to verify
6462306a36Sopenharmony_ci * the integrity of (super)-block write requests, do not
6562306a36Sopenharmony_ci * enable the config option BTRFS_FS_CHECK_INTEGRITY to
6662306a36Sopenharmony_ci * include and compile the integrity check tool.
6762306a36Sopenharmony_ci *
6862306a36Sopenharmony_ci * Expect millions of lines of information in the kernel log with an
6962306a36Sopenharmony_ci * enabled check_int_print_mask. Therefore set LOG_BUF_SHIFT in the
7062306a36Sopenharmony_ci * kernel config to at least 26 (which is 64MB). Usually the value is
7162306a36Sopenharmony_ci * limited to 21 (which is 2MB) in init/Kconfig. The file needs to be
7262306a36Sopenharmony_ci * changed like this before LOG_BUF_SHIFT can be set to a high value:
7362306a36Sopenharmony_ci * config LOG_BUF_SHIFT
7462306a36Sopenharmony_ci *       int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
7562306a36Sopenharmony_ci *       range 12 30
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#include <linux/sched.h>
7962306a36Sopenharmony_ci#include <linux/slab.h>
8062306a36Sopenharmony_ci#include <linux/mutex.h>
8162306a36Sopenharmony_ci#include <linux/blkdev.h>
8262306a36Sopenharmony_ci#include <linux/mm.h>
8362306a36Sopenharmony_ci#include <linux/string.h>
8462306a36Sopenharmony_ci#include <crypto/hash.h>
8562306a36Sopenharmony_ci#include "messages.h"
8662306a36Sopenharmony_ci#include "ctree.h"
8762306a36Sopenharmony_ci#include "disk-io.h"
8862306a36Sopenharmony_ci#include "transaction.h"
8962306a36Sopenharmony_ci#include "extent_io.h"
9062306a36Sopenharmony_ci#include "volumes.h"
9162306a36Sopenharmony_ci#include "print-tree.h"
9262306a36Sopenharmony_ci#include "locking.h"
9362306a36Sopenharmony_ci#include "check-integrity.h"
9462306a36Sopenharmony_ci#include "rcu-string.h"
9562306a36Sopenharmony_ci#include "compression.h"
9662306a36Sopenharmony_ci#include "accessors.h"
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci#define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000
9962306a36Sopenharmony_ci#define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000
10062306a36Sopenharmony_ci#define BTRFSIC_DEV2STATE_HASHTABLE_SIZE 0x100
10162306a36Sopenharmony_ci#define BTRFSIC_BLOCK_MAGIC_NUMBER 0x14491051
10262306a36Sopenharmony_ci#define BTRFSIC_BLOCK_LINK_MAGIC_NUMBER 0x11070807
10362306a36Sopenharmony_ci#define BTRFSIC_DEV2STATE_MAGIC_NUMBER 0x20111530
10462306a36Sopenharmony_ci#define BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER 20111300
10562306a36Sopenharmony_ci#define BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL (200 - 6)	/* in characters,
10662306a36Sopenharmony_ci							 * excluding " [...]" */
10762306a36Sopenharmony_ci#define BTRFSIC_GENERATION_UNKNOWN ((u64)-1)
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/*
11062306a36Sopenharmony_ci * The definition of the bitmask fields for the print_mask.
11162306a36Sopenharmony_ci * They are specified with the mount option check_integrity_print_mask.
11262306a36Sopenharmony_ci */
11362306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE			0x00000001
11462306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION		0x00000002
11562306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE			0x00000004
11662306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE			0x00000008
11762306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH			0x00000010
11862306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_END_IO_BIO_BH			0x00000020
11962306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_VERBOSE				0x00000040
12062306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_VERY_VERBOSE				0x00000080
12162306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_INITIAL_TREE				0x00000100
12262306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES			0x00000200
12362306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_INITIAL_DATABASE			0x00000400
12462306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_NUM_COPIES				0x00000800
12562306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS		0x00001000
12662306a36Sopenharmony_ci#define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE		0x00002000
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistruct btrfsic_dev_state;
12962306a36Sopenharmony_cistruct btrfsic_state;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistruct btrfsic_block {
13262306a36Sopenharmony_ci	u32 magic_num;		/* only used for debug purposes */
13362306a36Sopenharmony_ci	unsigned int is_metadata:1;	/* if it is meta-data, not data-data */
13462306a36Sopenharmony_ci	unsigned int is_superblock:1;	/* if it is one of the superblocks */
13562306a36Sopenharmony_ci	unsigned int is_iodone:1;	/* if is done by lower subsystem */
13662306a36Sopenharmony_ci	unsigned int iodone_w_error:1;	/* error was indicated to endio */
13762306a36Sopenharmony_ci	unsigned int never_written:1;	/* block was added because it was
13862306a36Sopenharmony_ci					 * referenced, not because it was
13962306a36Sopenharmony_ci					 * written */
14062306a36Sopenharmony_ci	unsigned int mirror_num;	/* large enough to hold
14162306a36Sopenharmony_ci					 * BTRFS_SUPER_MIRROR_MAX */
14262306a36Sopenharmony_ci	struct btrfsic_dev_state *dev_state;
14362306a36Sopenharmony_ci	u64 dev_bytenr;		/* key, physical byte num on disk */
14462306a36Sopenharmony_ci	u64 logical_bytenr;	/* logical byte num on disk */
14562306a36Sopenharmony_ci	u64 generation;
14662306a36Sopenharmony_ci	struct btrfs_disk_key disk_key;	/* extra info to print in case of
14762306a36Sopenharmony_ci					 * issues, will not always be correct */
14862306a36Sopenharmony_ci	struct list_head collision_resolving_node;	/* list node */
14962306a36Sopenharmony_ci	struct list_head all_blocks_node;	/* list node */
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/* the following two lists contain block_link items */
15262306a36Sopenharmony_ci	struct list_head ref_to_list;	/* list */
15362306a36Sopenharmony_ci	struct list_head ref_from_list;	/* list */
15462306a36Sopenharmony_ci	struct btrfsic_block *next_in_same_bio;
15562306a36Sopenharmony_ci	void *orig_bio_private;
15662306a36Sopenharmony_ci	bio_end_io_t *orig_bio_end_io;
15762306a36Sopenharmony_ci	blk_opf_t submit_bio_bh_rw;
15862306a36Sopenharmony_ci	u64 flush_gen; /* only valid if !never_written */
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/*
16262306a36Sopenharmony_ci * Elements of this type are allocated dynamically and required because
16362306a36Sopenharmony_ci * each block object can refer to and can be ref from multiple blocks.
16462306a36Sopenharmony_ci * The key to lookup them in the hashtable is the dev_bytenr of
16562306a36Sopenharmony_ci * the block ref to plus the one from the block referred from.
16662306a36Sopenharmony_ci * The fact that they are searchable via a hashtable and that a
16762306a36Sopenharmony_ci * ref_cnt is maintained is not required for the btrfs integrity
16862306a36Sopenharmony_ci * check algorithm itself, it is only used to make the output more
16962306a36Sopenharmony_ci * beautiful in case that an error is detected (an error is defined
17062306a36Sopenharmony_ci * as a write operation to a block while that block is still referenced).
17162306a36Sopenharmony_ci */
17262306a36Sopenharmony_cistruct btrfsic_block_link {
17362306a36Sopenharmony_ci	u32 magic_num;		/* only used for debug purposes */
17462306a36Sopenharmony_ci	u32 ref_cnt;
17562306a36Sopenharmony_ci	struct list_head node_ref_to;	/* list node */
17662306a36Sopenharmony_ci	struct list_head node_ref_from;	/* list node */
17762306a36Sopenharmony_ci	struct list_head collision_resolving_node;	/* list node */
17862306a36Sopenharmony_ci	struct btrfsic_block *block_ref_to;
17962306a36Sopenharmony_ci	struct btrfsic_block *block_ref_from;
18062306a36Sopenharmony_ci	u64 parent_generation;
18162306a36Sopenharmony_ci};
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistruct btrfsic_dev_state {
18462306a36Sopenharmony_ci	u32 magic_num;		/* only used for debug purposes */
18562306a36Sopenharmony_ci	struct block_device *bdev;
18662306a36Sopenharmony_ci	struct btrfsic_state *state;
18762306a36Sopenharmony_ci	struct list_head collision_resolving_node;	/* list node */
18862306a36Sopenharmony_ci	struct btrfsic_block dummy_block_for_bio_bh_flush;
18962306a36Sopenharmony_ci	u64 last_flush_gen;
19062306a36Sopenharmony_ci};
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistruct btrfsic_block_hashtable {
19362306a36Sopenharmony_ci	struct list_head table[BTRFSIC_BLOCK_HASHTABLE_SIZE];
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistruct btrfsic_block_link_hashtable {
19762306a36Sopenharmony_ci	struct list_head table[BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE];
19862306a36Sopenharmony_ci};
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistruct btrfsic_dev_state_hashtable {
20162306a36Sopenharmony_ci	struct list_head table[BTRFSIC_DEV2STATE_HASHTABLE_SIZE];
20262306a36Sopenharmony_ci};
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistruct btrfsic_block_data_ctx {
20562306a36Sopenharmony_ci	u64 start;		/* virtual bytenr */
20662306a36Sopenharmony_ci	u64 dev_bytenr;		/* physical bytenr on device */
20762306a36Sopenharmony_ci	u32 len;
20862306a36Sopenharmony_ci	struct btrfsic_dev_state *dev;
20962306a36Sopenharmony_ci	char **datav;
21062306a36Sopenharmony_ci	struct page **pagev;
21162306a36Sopenharmony_ci	void *mem_to_free;
21262306a36Sopenharmony_ci};
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci/* This structure is used to implement recursion without occupying
21562306a36Sopenharmony_ci * any stack space, refer to btrfsic_process_metablock() */
21662306a36Sopenharmony_cistruct btrfsic_stack_frame {
21762306a36Sopenharmony_ci	u32 magic;
21862306a36Sopenharmony_ci	u32 nr;
21962306a36Sopenharmony_ci	int error;
22062306a36Sopenharmony_ci	int i;
22162306a36Sopenharmony_ci	int limit_nesting;
22262306a36Sopenharmony_ci	int num_copies;
22362306a36Sopenharmony_ci	int mirror_num;
22462306a36Sopenharmony_ci	struct btrfsic_block *block;
22562306a36Sopenharmony_ci	struct btrfsic_block_data_ctx *block_ctx;
22662306a36Sopenharmony_ci	struct btrfsic_block *next_block;
22762306a36Sopenharmony_ci	struct btrfsic_block_data_ctx next_block_ctx;
22862306a36Sopenharmony_ci	struct btrfs_header *hdr;
22962306a36Sopenharmony_ci	struct btrfsic_stack_frame *prev;
23062306a36Sopenharmony_ci};
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci/* Some state per mounted filesystem */
23362306a36Sopenharmony_cistruct btrfsic_state {
23462306a36Sopenharmony_ci	u32 print_mask;
23562306a36Sopenharmony_ci	int include_extent_data;
23662306a36Sopenharmony_ci	struct list_head all_blocks_list;
23762306a36Sopenharmony_ci	struct btrfsic_block_hashtable block_hashtable;
23862306a36Sopenharmony_ci	struct btrfsic_block_link_hashtable block_link_hashtable;
23962306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info;
24062306a36Sopenharmony_ci	u64 max_superblock_generation;
24162306a36Sopenharmony_ci	struct btrfsic_block *latest_superblock;
24262306a36Sopenharmony_ci	u32 metablock_size;
24362306a36Sopenharmony_ci	u32 datablock_size;
24462306a36Sopenharmony_ci};
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic int btrfsic_process_metablock(struct btrfsic_state *state,
24762306a36Sopenharmony_ci				     struct btrfsic_block *block,
24862306a36Sopenharmony_ci				     struct btrfsic_block_data_ctx *block_ctx,
24962306a36Sopenharmony_ci				     int limit_nesting, int force_iodone_flag);
25062306a36Sopenharmony_cistatic void btrfsic_read_from_block_data(
25162306a36Sopenharmony_ci	struct btrfsic_block_data_ctx *block_ctx,
25262306a36Sopenharmony_ci	void *dst, u32 offset, size_t len);
25362306a36Sopenharmony_cistatic int btrfsic_create_link_to_next_block(
25462306a36Sopenharmony_ci		struct btrfsic_state *state,
25562306a36Sopenharmony_ci		struct btrfsic_block *block,
25662306a36Sopenharmony_ci		struct btrfsic_block_data_ctx
25762306a36Sopenharmony_ci		*block_ctx, u64 next_bytenr,
25862306a36Sopenharmony_ci		int limit_nesting,
25962306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *next_block_ctx,
26062306a36Sopenharmony_ci		struct btrfsic_block **next_blockp,
26162306a36Sopenharmony_ci		int force_iodone_flag,
26262306a36Sopenharmony_ci		int *num_copiesp, int *mirror_nump,
26362306a36Sopenharmony_ci		struct btrfs_disk_key *disk_key,
26462306a36Sopenharmony_ci		u64 parent_generation);
26562306a36Sopenharmony_cistatic int btrfsic_handle_extent_data(struct btrfsic_state *state,
26662306a36Sopenharmony_ci				      struct btrfsic_block *block,
26762306a36Sopenharmony_ci				      struct btrfsic_block_data_ctx *block_ctx,
26862306a36Sopenharmony_ci				      u32 item_offset, int force_iodone_flag);
26962306a36Sopenharmony_cistatic int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
27062306a36Sopenharmony_ci			     struct btrfsic_block_data_ctx *block_ctx_out,
27162306a36Sopenharmony_ci			     int mirror_num);
27262306a36Sopenharmony_cistatic void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
27362306a36Sopenharmony_cistatic int btrfsic_read_block(struct btrfsic_state *state,
27462306a36Sopenharmony_ci			      struct btrfsic_block_data_ctx *block_ctx);
27562306a36Sopenharmony_cistatic int btrfsic_process_written_superblock(
27662306a36Sopenharmony_ci		struct btrfsic_state *state,
27762306a36Sopenharmony_ci		struct btrfsic_block *const block,
27862306a36Sopenharmony_ci		struct btrfs_super_block *const super_hdr);
27962306a36Sopenharmony_cistatic void btrfsic_bio_end_io(struct bio *bp);
28062306a36Sopenharmony_cistatic int btrfsic_is_block_ref_by_superblock(const struct btrfsic_state *state,
28162306a36Sopenharmony_ci					      const struct btrfsic_block *block,
28262306a36Sopenharmony_ci					      int recursion_level);
28362306a36Sopenharmony_cistatic int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
28462306a36Sopenharmony_ci					struct btrfsic_block *const block,
28562306a36Sopenharmony_ci					int recursion_level);
28662306a36Sopenharmony_cistatic void btrfsic_print_add_link(const struct btrfsic_state *state,
28762306a36Sopenharmony_ci				   const struct btrfsic_block_link *l);
28862306a36Sopenharmony_cistatic void btrfsic_print_rem_link(const struct btrfsic_state *state,
28962306a36Sopenharmony_ci				   const struct btrfsic_block_link *l);
29062306a36Sopenharmony_cistatic char btrfsic_get_block_type(const struct btrfsic_state *state,
29162306a36Sopenharmony_ci				   const struct btrfsic_block *block);
29262306a36Sopenharmony_cistatic void btrfsic_dump_tree(const struct btrfsic_state *state);
29362306a36Sopenharmony_cistatic void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
29462306a36Sopenharmony_ci				  const struct btrfsic_block *block,
29562306a36Sopenharmony_ci				  int indent_level);
29662306a36Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_lookup_or_add(
29762306a36Sopenharmony_ci		struct btrfsic_state *state,
29862306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *next_block_ctx,
29962306a36Sopenharmony_ci		struct btrfsic_block *next_block,
30062306a36Sopenharmony_ci		struct btrfsic_block *from_block,
30162306a36Sopenharmony_ci		u64 parent_generation);
30262306a36Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_lookup_or_add(
30362306a36Sopenharmony_ci		struct btrfsic_state *state,
30462306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *block_ctx,
30562306a36Sopenharmony_ci		const char *additional_string,
30662306a36Sopenharmony_ci		int is_metadata,
30762306a36Sopenharmony_ci		int is_iodone,
30862306a36Sopenharmony_ci		int never_written,
30962306a36Sopenharmony_ci		int mirror_num,
31062306a36Sopenharmony_ci		int *was_created);
31162306a36Sopenharmony_cistatic int btrfsic_process_superblock_dev_mirror(
31262306a36Sopenharmony_ci		struct btrfsic_state *state,
31362306a36Sopenharmony_ci		struct btrfsic_dev_state *dev_state,
31462306a36Sopenharmony_ci		struct btrfs_device *device,
31562306a36Sopenharmony_ci		int superblock_mirror_num,
31662306a36Sopenharmony_ci		struct btrfsic_dev_state **selected_dev_state,
31762306a36Sopenharmony_ci		struct btrfs_super_block *selected_super);
31862306a36Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_lookup(dev_t dev);
31962306a36Sopenharmony_cistatic void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
32062306a36Sopenharmony_ci					   u64 bytenr,
32162306a36Sopenharmony_ci					   struct btrfsic_dev_state *dev_state,
32262306a36Sopenharmony_ci					   u64 dev_bytenr);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic struct mutex btrfsic_mutex;
32562306a36Sopenharmony_cistatic int btrfsic_is_initialized;
32662306a36Sopenharmony_cistatic struct btrfsic_dev_state_hashtable btrfsic_dev_state_hashtable;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_cistatic void btrfsic_block_init(struct btrfsic_block *b)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	b->magic_num = BTRFSIC_BLOCK_MAGIC_NUMBER;
33262306a36Sopenharmony_ci	b->dev_state = NULL;
33362306a36Sopenharmony_ci	b->dev_bytenr = 0;
33462306a36Sopenharmony_ci	b->logical_bytenr = 0;
33562306a36Sopenharmony_ci	b->generation = BTRFSIC_GENERATION_UNKNOWN;
33662306a36Sopenharmony_ci	b->disk_key.objectid = 0;
33762306a36Sopenharmony_ci	b->disk_key.type = 0;
33862306a36Sopenharmony_ci	b->disk_key.offset = 0;
33962306a36Sopenharmony_ci	b->is_metadata = 0;
34062306a36Sopenharmony_ci	b->is_superblock = 0;
34162306a36Sopenharmony_ci	b->is_iodone = 0;
34262306a36Sopenharmony_ci	b->iodone_w_error = 0;
34362306a36Sopenharmony_ci	b->never_written = 0;
34462306a36Sopenharmony_ci	b->mirror_num = 0;
34562306a36Sopenharmony_ci	b->next_in_same_bio = NULL;
34662306a36Sopenharmony_ci	b->orig_bio_private = NULL;
34762306a36Sopenharmony_ci	b->orig_bio_end_io = NULL;
34862306a36Sopenharmony_ci	INIT_LIST_HEAD(&b->collision_resolving_node);
34962306a36Sopenharmony_ci	INIT_LIST_HEAD(&b->all_blocks_node);
35062306a36Sopenharmony_ci	INIT_LIST_HEAD(&b->ref_to_list);
35162306a36Sopenharmony_ci	INIT_LIST_HEAD(&b->ref_from_list);
35262306a36Sopenharmony_ci	b->submit_bio_bh_rw = 0;
35362306a36Sopenharmony_ci	b->flush_gen = 0;
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_alloc(void)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	struct btrfsic_block *b;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	b = kzalloc(sizeof(*b), GFP_NOFS);
36162306a36Sopenharmony_ci	if (NULL != b)
36262306a36Sopenharmony_ci		btrfsic_block_init(b);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	return b;
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic void btrfsic_block_free(struct btrfsic_block *b)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	BUG_ON(!(NULL == b || BTRFSIC_BLOCK_MAGIC_NUMBER == b->magic_num));
37062306a36Sopenharmony_ci	kfree(b);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic void btrfsic_block_link_init(struct btrfsic_block_link *l)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	l->magic_num = BTRFSIC_BLOCK_LINK_MAGIC_NUMBER;
37662306a36Sopenharmony_ci	l->ref_cnt = 1;
37762306a36Sopenharmony_ci	INIT_LIST_HEAD(&l->node_ref_to);
37862306a36Sopenharmony_ci	INIT_LIST_HEAD(&l->node_ref_from);
37962306a36Sopenharmony_ci	INIT_LIST_HEAD(&l->collision_resolving_node);
38062306a36Sopenharmony_ci	l->block_ref_to = NULL;
38162306a36Sopenharmony_ci	l->block_ref_from = NULL;
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_alloc(void)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	struct btrfsic_block_link *l;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	l = kzalloc(sizeof(*l), GFP_NOFS);
38962306a36Sopenharmony_ci	if (NULL != l)
39062306a36Sopenharmony_ci		btrfsic_block_link_init(l);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	return l;
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cistatic void btrfsic_block_link_free(struct btrfsic_block_link *l)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	BUG_ON(!(NULL == l || BTRFSIC_BLOCK_LINK_MAGIC_NUMBER == l->magic_num));
39862306a36Sopenharmony_ci	kfree(l);
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic void btrfsic_dev_state_init(struct btrfsic_dev_state *ds)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	ds->magic_num = BTRFSIC_DEV2STATE_MAGIC_NUMBER;
40462306a36Sopenharmony_ci	ds->bdev = NULL;
40562306a36Sopenharmony_ci	ds->state = NULL;
40662306a36Sopenharmony_ci	INIT_LIST_HEAD(&ds->collision_resolving_node);
40762306a36Sopenharmony_ci	ds->last_flush_gen = 0;
40862306a36Sopenharmony_ci	btrfsic_block_init(&ds->dummy_block_for_bio_bh_flush);
40962306a36Sopenharmony_ci	ds->dummy_block_for_bio_bh_flush.is_iodone = 1;
41062306a36Sopenharmony_ci	ds->dummy_block_for_bio_bh_flush.dev_state = ds;
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_alloc(void)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	struct btrfsic_dev_state *ds;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	ds = kzalloc(sizeof(*ds), GFP_NOFS);
41862306a36Sopenharmony_ci	if (NULL != ds)
41962306a36Sopenharmony_ci		btrfsic_dev_state_init(ds);
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	return ds;
42262306a36Sopenharmony_ci}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_cistatic void btrfsic_dev_state_free(struct btrfsic_dev_state *ds)
42562306a36Sopenharmony_ci{
42662306a36Sopenharmony_ci	BUG_ON(!(NULL == ds ||
42762306a36Sopenharmony_ci		 BTRFSIC_DEV2STATE_MAGIC_NUMBER == ds->magic_num));
42862306a36Sopenharmony_ci	kfree(ds);
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic void btrfsic_block_hashtable_init(struct btrfsic_block_hashtable *h)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	int i;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	for (i = 0; i < BTRFSIC_BLOCK_HASHTABLE_SIZE; i++)
43662306a36Sopenharmony_ci		INIT_LIST_HEAD(h->table + i);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic void btrfsic_block_hashtable_add(struct btrfsic_block *b,
44062306a36Sopenharmony_ci					struct btrfsic_block_hashtable *h)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	const unsigned int hashval =
44362306a36Sopenharmony_ci	    (((unsigned int)(b->dev_bytenr >> 16)) ^
44462306a36Sopenharmony_ci	     ((unsigned int)((uintptr_t)b->dev_state->bdev))) &
44562306a36Sopenharmony_ci	     (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	list_add(&b->collision_resolving_node, h->table + hashval);
44862306a36Sopenharmony_ci}
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_cistatic void btrfsic_block_hashtable_remove(struct btrfsic_block *b)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	list_del(&b->collision_resolving_node);
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_hashtable_lookup(
45662306a36Sopenharmony_ci		struct block_device *bdev,
45762306a36Sopenharmony_ci		u64 dev_bytenr,
45862306a36Sopenharmony_ci		struct btrfsic_block_hashtable *h)
45962306a36Sopenharmony_ci{
46062306a36Sopenharmony_ci	const unsigned int hashval =
46162306a36Sopenharmony_ci	    (((unsigned int)(dev_bytenr >> 16)) ^
46262306a36Sopenharmony_ci	     ((unsigned int)((uintptr_t)bdev))) &
46362306a36Sopenharmony_ci	     (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1);
46462306a36Sopenharmony_ci	struct btrfsic_block *b;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	list_for_each_entry(b, h->table + hashval, collision_resolving_node) {
46762306a36Sopenharmony_ci		if (b->dev_state->bdev == bdev && b->dev_bytenr == dev_bytenr)
46862306a36Sopenharmony_ci			return b;
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	return NULL;
47262306a36Sopenharmony_ci}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_cistatic void btrfsic_block_link_hashtable_init(
47562306a36Sopenharmony_ci		struct btrfsic_block_link_hashtable *h)
47662306a36Sopenharmony_ci{
47762306a36Sopenharmony_ci	int i;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	for (i = 0; i < BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE; i++)
48062306a36Sopenharmony_ci		INIT_LIST_HEAD(h->table + i);
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic void btrfsic_block_link_hashtable_add(
48462306a36Sopenharmony_ci		struct btrfsic_block_link *l,
48562306a36Sopenharmony_ci		struct btrfsic_block_link_hashtable *h)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	const unsigned int hashval =
48862306a36Sopenharmony_ci	    (((unsigned int)(l->block_ref_to->dev_bytenr >> 16)) ^
48962306a36Sopenharmony_ci	     ((unsigned int)(l->block_ref_from->dev_bytenr >> 16)) ^
49062306a36Sopenharmony_ci	     ((unsigned int)((uintptr_t)l->block_ref_to->dev_state->bdev)) ^
49162306a36Sopenharmony_ci	     ((unsigned int)((uintptr_t)l->block_ref_from->dev_state->bdev)))
49262306a36Sopenharmony_ci	     & (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	BUG_ON(NULL == l->block_ref_to);
49562306a36Sopenharmony_ci	BUG_ON(NULL == l->block_ref_from);
49662306a36Sopenharmony_ci	list_add(&l->collision_resolving_node, h->table + hashval);
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_cistatic void btrfsic_block_link_hashtable_remove(struct btrfsic_block_link *l)
50062306a36Sopenharmony_ci{
50162306a36Sopenharmony_ci	list_del(&l->collision_resolving_node);
50262306a36Sopenharmony_ci}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_hashtable_lookup(
50562306a36Sopenharmony_ci		struct block_device *bdev_ref_to,
50662306a36Sopenharmony_ci		u64 dev_bytenr_ref_to,
50762306a36Sopenharmony_ci		struct block_device *bdev_ref_from,
50862306a36Sopenharmony_ci		u64 dev_bytenr_ref_from,
50962306a36Sopenharmony_ci		struct btrfsic_block_link_hashtable *h)
51062306a36Sopenharmony_ci{
51162306a36Sopenharmony_ci	const unsigned int hashval =
51262306a36Sopenharmony_ci	    (((unsigned int)(dev_bytenr_ref_to >> 16)) ^
51362306a36Sopenharmony_ci	     ((unsigned int)(dev_bytenr_ref_from >> 16)) ^
51462306a36Sopenharmony_ci	     ((unsigned int)((uintptr_t)bdev_ref_to)) ^
51562306a36Sopenharmony_ci	     ((unsigned int)((uintptr_t)bdev_ref_from))) &
51662306a36Sopenharmony_ci	     (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1);
51762306a36Sopenharmony_ci	struct btrfsic_block_link *l;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	list_for_each_entry(l, h->table + hashval, collision_resolving_node) {
52062306a36Sopenharmony_ci		BUG_ON(NULL == l->block_ref_to);
52162306a36Sopenharmony_ci		BUG_ON(NULL == l->block_ref_from);
52262306a36Sopenharmony_ci		if (l->block_ref_to->dev_state->bdev == bdev_ref_to &&
52362306a36Sopenharmony_ci		    l->block_ref_to->dev_bytenr == dev_bytenr_ref_to &&
52462306a36Sopenharmony_ci		    l->block_ref_from->dev_state->bdev == bdev_ref_from &&
52562306a36Sopenharmony_ci		    l->block_ref_from->dev_bytenr == dev_bytenr_ref_from)
52662306a36Sopenharmony_ci			return l;
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	return NULL;
53062306a36Sopenharmony_ci}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_cistatic void btrfsic_dev_state_hashtable_init(
53362306a36Sopenharmony_ci		struct btrfsic_dev_state_hashtable *h)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	int i;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	for (i = 0; i < BTRFSIC_DEV2STATE_HASHTABLE_SIZE; i++)
53862306a36Sopenharmony_ci		INIT_LIST_HEAD(h->table + i);
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_cistatic void btrfsic_dev_state_hashtable_add(
54262306a36Sopenharmony_ci		struct btrfsic_dev_state *ds,
54362306a36Sopenharmony_ci		struct btrfsic_dev_state_hashtable *h)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	const unsigned int hashval =
54662306a36Sopenharmony_ci	    (((unsigned int)((uintptr_t)ds->bdev->bd_dev)) &
54762306a36Sopenharmony_ci	     (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1));
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	list_add(&ds->collision_resolving_node, h->table + hashval);
55062306a36Sopenharmony_ci}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_cistatic void btrfsic_dev_state_hashtable_remove(struct btrfsic_dev_state *ds)
55362306a36Sopenharmony_ci{
55462306a36Sopenharmony_ci	list_del(&ds->collision_resolving_node);
55562306a36Sopenharmony_ci}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(dev_t dev,
55862306a36Sopenharmony_ci		struct btrfsic_dev_state_hashtable *h)
55962306a36Sopenharmony_ci{
56062306a36Sopenharmony_ci	const unsigned int hashval =
56162306a36Sopenharmony_ci		dev & (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1);
56262306a36Sopenharmony_ci	struct btrfsic_dev_state *ds;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	list_for_each_entry(ds, h->table + hashval, collision_resolving_node) {
56562306a36Sopenharmony_ci		if (ds->bdev->bd_dev == dev)
56662306a36Sopenharmony_ci			return ds;
56762306a36Sopenharmony_ci	}
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	return NULL;
57062306a36Sopenharmony_ci}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_cistatic int btrfsic_process_superblock(struct btrfsic_state *state,
57362306a36Sopenharmony_ci				      struct btrfs_fs_devices *fs_devices)
57462306a36Sopenharmony_ci{
57562306a36Sopenharmony_ci	struct btrfs_super_block *selected_super;
57662306a36Sopenharmony_ci	struct list_head *dev_head = &fs_devices->devices;
57762306a36Sopenharmony_ci	struct btrfs_device *device;
57862306a36Sopenharmony_ci	struct btrfsic_dev_state *selected_dev_state = NULL;
57962306a36Sopenharmony_ci	int ret = 0;
58062306a36Sopenharmony_ci	int pass;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	selected_super = kzalloc(sizeof(*selected_super), GFP_NOFS);
58362306a36Sopenharmony_ci	if (!selected_super)
58462306a36Sopenharmony_ci		return -ENOMEM;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	list_for_each_entry(device, dev_head, dev_list) {
58762306a36Sopenharmony_ci		int i;
58862306a36Sopenharmony_ci		struct btrfsic_dev_state *dev_state;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci		if (!device->bdev || !device->name)
59162306a36Sopenharmony_ci			continue;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci		dev_state = btrfsic_dev_state_lookup(device->bdev->bd_dev);
59462306a36Sopenharmony_ci		BUG_ON(NULL == dev_state);
59562306a36Sopenharmony_ci		for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
59662306a36Sopenharmony_ci			ret = btrfsic_process_superblock_dev_mirror(
59762306a36Sopenharmony_ci					state, dev_state, device, i,
59862306a36Sopenharmony_ci					&selected_dev_state, selected_super);
59962306a36Sopenharmony_ci			if (0 != ret && 0 == i) {
60062306a36Sopenharmony_ci				kfree(selected_super);
60162306a36Sopenharmony_ci				return ret;
60262306a36Sopenharmony_ci			}
60362306a36Sopenharmony_ci		}
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	if (NULL == state->latest_superblock) {
60762306a36Sopenharmony_ci		pr_info("btrfsic: no superblock found!\n");
60862306a36Sopenharmony_ci		kfree(selected_super);
60962306a36Sopenharmony_ci		return -1;
61062306a36Sopenharmony_ci	}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	for (pass = 0; pass < 3; pass++) {
61362306a36Sopenharmony_ci		int num_copies;
61462306a36Sopenharmony_ci		int mirror_num;
61562306a36Sopenharmony_ci		u64 next_bytenr;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci		switch (pass) {
61862306a36Sopenharmony_ci		case 0:
61962306a36Sopenharmony_ci			next_bytenr = btrfs_super_root(selected_super);
62062306a36Sopenharmony_ci			if (state->print_mask &
62162306a36Sopenharmony_ci			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
62262306a36Sopenharmony_ci				pr_info("root@%llu\n", next_bytenr);
62362306a36Sopenharmony_ci			break;
62462306a36Sopenharmony_ci		case 1:
62562306a36Sopenharmony_ci			next_bytenr = btrfs_super_chunk_root(selected_super);
62662306a36Sopenharmony_ci			if (state->print_mask &
62762306a36Sopenharmony_ci			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
62862306a36Sopenharmony_ci				pr_info("chunk@%llu\n", next_bytenr);
62962306a36Sopenharmony_ci			break;
63062306a36Sopenharmony_ci		case 2:
63162306a36Sopenharmony_ci			next_bytenr = btrfs_super_log_root(selected_super);
63262306a36Sopenharmony_ci			if (0 == next_bytenr)
63362306a36Sopenharmony_ci				continue;
63462306a36Sopenharmony_ci			if (state->print_mask &
63562306a36Sopenharmony_ci			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
63662306a36Sopenharmony_ci				pr_info("log@%llu\n", next_bytenr);
63762306a36Sopenharmony_ci			break;
63862306a36Sopenharmony_ci		}
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		num_copies = btrfs_num_copies(state->fs_info, next_bytenr,
64162306a36Sopenharmony_ci					      state->metablock_size);
64262306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
64362306a36Sopenharmony_ci			pr_info("num_copies(log_bytenr=%llu) = %d\n",
64462306a36Sopenharmony_ci			       next_bytenr, num_copies);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
64762306a36Sopenharmony_ci			struct btrfsic_block *next_block;
64862306a36Sopenharmony_ci			struct btrfsic_block_data_ctx tmp_next_block_ctx;
64962306a36Sopenharmony_ci			struct btrfsic_block_link *l;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci			ret = btrfsic_map_block(state, next_bytenr,
65262306a36Sopenharmony_ci						state->metablock_size,
65362306a36Sopenharmony_ci						&tmp_next_block_ctx,
65462306a36Sopenharmony_ci						mirror_num);
65562306a36Sopenharmony_ci			if (ret) {
65662306a36Sopenharmony_ci				pr_info("btrfsic: btrfsic_map_block(root @%llu, mirror %d) failed!\n",
65762306a36Sopenharmony_ci				       next_bytenr, mirror_num);
65862306a36Sopenharmony_ci				kfree(selected_super);
65962306a36Sopenharmony_ci				return -1;
66062306a36Sopenharmony_ci			}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci			next_block = btrfsic_block_hashtable_lookup(
66362306a36Sopenharmony_ci					tmp_next_block_ctx.dev->bdev,
66462306a36Sopenharmony_ci					tmp_next_block_ctx.dev_bytenr,
66562306a36Sopenharmony_ci					&state->block_hashtable);
66662306a36Sopenharmony_ci			BUG_ON(NULL == next_block);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci			l = btrfsic_block_link_hashtable_lookup(
66962306a36Sopenharmony_ci					tmp_next_block_ctx.dev->bdev,
67062306a36Sopenharmony_ci					tmp_next_block_ctx.dev_bytenr,
67162306a36Sopenharmony_ci					state->latest_superblock->dev_state->
67262306a36Sopenharmony_ci					bdev,
67362306a36Sopenharmony_ci					state->latest_superblock->dev_bytenr,
67462306a36Sopenharmony_ci					&state->block_link_hashtable);
67562306a36Sopenharmony_ci			BUG_ON(NULL == l);
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci			ret = btrfsic_read_block(state, &tmp_next_block_ctx);
67862306a36Sopenharmony_ci			if (ret < (int)PAGE_SIZE) {
67962306a36Sopenharmony_ci				pr_info("btrfsic: read @logical %llu failed!\n",
68062306a36Sopenharmony_ci				       tmp_next_block_ctx.start);
68162306a36Sopenharmony_ci				btrfsic_release_block_ctx(&tmp_next_block_ctx);
68262306a36Sopenharmony_ci				kfree(selected_super);
68362306a36Sopenharmony_ci				return -1;
68462306a36Sopenharmony_ci			}
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci			ret = btrfsic_process_metablock(state,
68762306a36Sopenharmony_ci							next_block,
68862306a36Sopenharmony_ci							&tmp_next_block_ctx,
68962306a36Sopenharmony_ci							BTRFS_MAX_LEVEL + 3, 1);
69062306a36Sopenharmony_ci			btrfsic_release_block_ctx(&tmp_next_block_ctx);
69162306a36Sopenharmony_ci		}
69262306a36Sopenharmony_ci	}
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	kfree(selected_super);
69562306a36Sopenharmony_ci	return ret;
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_cistatic int btrfsic_process_superblock_dev_mirror(
69962306a36Sopenharmony_ci		struct btrfsic_state *state,
70062306a36Sopenharmony_ci		struct btrfsic_dev_state *dev_state,
70162306a36Sopenharmony_ci		struct btrfs_device *device,
70262306a36Sopenharmony_ci		int superblock_mirror_num,
70362306a36Sopenharmony_ci		struct btrfsic_dev_state **selected_dev_state,
70462306a36Sopenharmony_ci		struct btrfs_super_block *selected_super)
70562306a36Sopenharmony_ci{
70662306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = state->fs_info;
70762306a36Sopenharmony_ci	struct btrfs_super_block *super_tmp;
70862306a36Sopenharmony_ci	u64 dev_bytenr;
70962306a36Sopenharmony_ci	struct btrfsic_block *superblock_tmp;
71062306a36Sopenharmony_ci	int pass;
71162306a36Sopenharmony_ci	struct block_device *const superblock_bdev = device->bdev;
71262306a36Sopenharmony_ci	struct page *page;
71362306a36Sopenharmony_ci	struct address_space *mapping = superblock_bdev->bd_inode->i_mapping;
71462306a36Sopenharmony_ci	int ret = 0;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	/* super block bytenr is always the unmapped device bytenr */
71762306a36Sopenharmony_ci	dev_bytenr = btrfs_sb_offset(superblock_mirror_num);
71862306a36Sopenharmony_ci	if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes)
71962306a36Sopenharmony_ci		return -1;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	page = read_cache_page_gfp(mapping, dev_bytenr >> PAGE_SHIFT, GFP_NOFS);
72262306a36Sopenharmony_ci	if (IS_ERR(page))
72362306a36Sopenharmony_ci		return -1;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	super_tmp = page_address(page);
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	if (btrfs_super_bytenr(super_tmp) != dev_bytenr ||
72862306a36Sopenharmony_ci	    btrfs_super_magic(super_tmp) != BTRFS_MAGIC ||
72962306a36Sopenharmony_ci	    memcmp(device->uuid, super_tmp->dev_item.uuid, BTRFS_UUID_SIZE) ||
73062306a36Sopenharmony_ci	    btrfs_super_nodesize(super_tmp) != state->metablock_size ||
73162306a36Sopenharmony_ci	    btrfs_super_sectorsize(super_tmp) != state->datablock_size) {
73262306a36Sopenharmony_ci		ret = 0;
73362306a36Sopenharmony_ci		goto out;
73462306a36Sopenharmony_ci	}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	superblock_tmp =
73762306a36Sopenharmony_ci	    btrfsic_block_hashtable_lookup(superblock_bdev,
73862306a36Sopenharmony_ci					   dev_bytenr,
73962306a36Sopenharmony_ci					   &state->block_hashtable);
74062306a36Sopenharmony_ci	if (NULL == superblock_tmp) {
74162306a36Sopenharmony_ci		superblock_tmp = btrfsic_block_alloc();
74262306a36Sopenharmony_ci		if (NULL == superblock_tmp) {
74362306a36Sopenharmony_ci			ret = -1;
74462306a36Sopenharmony_ci			goto out;
74562306a36Sopenharmony_ci		}
74662306a36Sopenharmony_ci		/* for superblock, only the dev_bytenr makes sense */
74762306a36Sopenharmony_ci		superblock_tmp->dev_bytenr = dev_bytenr;
74862306a36Sopenharmony_ci		superblock_tmp->dev_state = dev_state;
74962306a36Sopenharmony_ci		superblock_tmp->logical_bytenr = dev_bytenr;
75062306a36Sopenharmony_ci		superblock_tmp->generation = btrfs_super_generation(super_tmp);
75162306a36Sopenharmony_ci		superblock_tmp->is_metadata = 1;
75262306a36Sopenharmony_ci		superblock_tmp->is_superblock = 1;
75362306a36Sopenharmony_ci		superblock_tmp->is_iodone = 1;
75462306a36Sopenharmony_ci		superblock_tmp->never_written = 0;
75562306a36Sopenharmony_ci		superblock_tmp->mirror_num = 1 + superblock_mirror_num;
75662306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
75762306a36Sopenharmony_ci			btrfs_info_in_rcu(fs_info,
75862306a36Sopenharmony_ci			"new initial S-block (bdev %p, %s) @%llu (%pg/%llu/%d)",
75962306a36Sopenharmony_ci				     superblock_bdev,
76062306a36Sopenharmony_ci				     btrfs_dev_name(device), dev_bytenr,
76162306a36Sopenharmony_ci				     dev_state->bdev, dev_bytenr,
76262306a36Sopenharmony_ci				     superblock_mirror_num);
76362306a36Sopenharmony_ci		list_add(&superblock_tmp->all_blocks_node,
76462306a36Sopenharmony_ci			 &state->all_blocks_list);
76562306a36Sopenharmony_ci		btrfsic_block_hashtable_add(superblock_tmp,
76662306a36Sopenharmony_ci					    &state->block_hashtable);
76762306a36Sopenharmony_ci	}
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	/* select the one with the highest generation field */
77062306a36Sopenharmony_ci	if (btrfs_super_generation(super_tmp) >
77162306a36Sopenharmony_ci	    state->max_superblock_generation ||
77262306a36Sopenharmony_ci	    0 == state->max_superblock_generation) {
77362306a36Sopenharmony_ci		memcpy(selected_super, super_tmp, sizeof(*selected_super));
77462306a36Sopenharmony_ci		*selected_dev_state = dev_state;
77562306a36Sopenharmony_ci		state->max_superblock_generation =
77662306a36Sopenharmony_ci		    btrfs_super_generation(super_tmp);
77762306a36Sopenharmony_ci		state->latest_superblock = superblock_tmp;
77862306a36Sopenharmony_ci	}
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	for (pass = 0; pass < 3; pass++) {
78162306a36Sopenharmony_ci		u64 next_bytenr;
78262306a36Sopenharmony_ci		int num_copies;
78362306a36Sopenharmony_ci		int mirror_num;
78462306a36Sopenharmony_ci		const char *additional_string = NULL;
78562306a36Sopenharmony_ci		struct btrfs_disk_key tmp_disk_key;
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci		tmp_disk_key.type = BTRFS_ROOT_ITEM_KEY;
78862306a36Sopenharmony_ci		tmp_disk_key.offset = 0;
78962306a36Sopenharmony_ci		switch (pass) {
79062306a36Sopenharmony_ci		case 0:
79162306a36Sopenharmony_ci			btrfs_set_disk_key_objectid(&tmp_disk_key,
79262306a36Sopenharmony_ci						    BTRFS_ROOT_TREE_OBJECTID);
79362306a36Sopenharmony_ci			additional_string = "initial root ";
79462306a36Sopenharmony_ci			next_bytenr = btrfs_super_root(super_tmp);
79562306a36Sopenharmony_ci			break;
79662306a36Sopenharmony_ci		case 1:
79762306a36Sopenharmony_ci			btrfs_set_disk_key_objectid(&tmp_disk_key,
79862306a36Sopenharmony_ci						    BTRFS_CHUNK_TREE_OBJECTID);
79962306a36Sopenharmony_ci			additional_string = "initial chunk ";
80062306a36Sopenharmony_ci			next_bytenr = btrfs_super_chunk_root(super_tmp);
80162306a36Sopenharmony_ci			break;
80262306a36Sopenharmony_ci		case 2:
80362306a36Sopenharmony_ci			btrfs_set_disk_key_objectid(&tmp_disk_key,
80462306a36Sopenharmony_ci						    BTRFS_TREE_LOG_OBJECTID);
80562306a36Sopenharmony_ci			additional_string = "initial log ";
80662306a36Sopenharmony_ci			next_bytenr = btrfs_super_log_root(super_tmp);
80762306a36Sopenharmony_ci			if (0 == next_bytenr)
80862306a36Sopenharmony_ci				continue;
80962306a36Sopenharmony_ci			break;
81062306a36Sopenharmony_ci		}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci		num_copies = btrfs_num_copies(fs_info, next_bytenr,
81362306a36Sopenharmony_ci					      state->metablock_size);
81462306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
81562306a36Sopenharmony_ci			pr_info("num_copies(log_bytenr=%llu) = %d\n",
81662306a36Sopenharmony_ci			       next_bytenr, num_copies);
81762306a36Sopenharmony_ci		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
81862306a36Sopenharmony_ci			struct btrfsic_block *next_block;
81962306a36Sopenharmony_ci			struct btrfsic_block_data_ctx tmp_next_block_ctx;
82062306a36Sopenharmony_ci			struct btrfsic_block_link *l;
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci			if (btrfsic_map_block(state, next_bytenr,
82362306a36Sopenharmony_ci					      state->metablock_size,
82462306a36Sopenharmony_ci					      &tmp_next_block_ctx,
82562306a36Sopenharmony_ci					      mirror_num)) {
82662306a36Sopenharmony_ci				pr_info("btrfsic: btrfsic_map_block(bytenr @%llu, mirror %d) failed!\n",
82762306a36Sopenharmony_ci				       next_bytenr, mirror_num);
82862306a36Sopenharmony_ci				ret = -1;
82962306a36Sopenharmony_ci				goto out;
83062306a36Sopenharmony_ci			}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci			next_block = btrfsic_block_lookup_or_add(
83362306a36Sopenharmony_ci					state, &tmp_next_block_ctx,
83462306a36Sopenharmony_ci					additional_string, 1, 1, 0,
83562306a36Sopenharmony_ci					mirror_num, NULL);
83662306a36Sopenharmony_ci			if (NULL == next_block) {
83762306a36Sopenharmony_ci				btrfsic_release_block_ctx(&tmp_next_block_ctx);
83862306a36Sopenharmony_ci				ret = -1;
83962306a36Sopenharmony_ci				goto out;
84062306a36Sopenharmony_ci			}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci			next_block->disk_key = tmp_disk_key;
84362306a36Sopenharmony_ci			next_block->generation = BTRFSIC_GENERATION_UNKNOWN;
84462306a36Sopenharmony_ci			l = btrfsic_block_link_lookup_or_add(
84562306a36Sopenharmony_ci					state, &tmp_next_block_ctx,
84662306a36Sopenharmony_ci					next_block, superblock_tmp,
84762306a36Sopenharmony_ci					BTRFSIC_GENERATION_UNKNOWN);
84862306a36Sopenharmony_ci			btrfsic_release_block_ctx(&tmp_next_block_ctx);
84962306a36Sopenharmony_ci			if (NULL == l) {
85062306a36Sopenharmony_ci				ret = -1;
85162306a36Sopenharmony_ci				goto out;
85262306a36Sopenharmony_ci			}
85362306a36Sopenharmony_ci		}
85462306a36Sopenharmony_ci	}
85562306a36Sopenharmony_ci	if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES)
85662306a36Sopenharmony_ci		btrfsic_dump_tree_sub(state, superblock_tmp, 0);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ciout:
85962306a36Sopenharmony_ci	put_page(page);
86062306a36Sopenharmony_ci	return ret;
86162306a36Sopenharmony_ci}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_cistatic struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void)
86462306a36Sopenharmony_ci{
86562306a36Sopenharmony_ci	struct btrfsic_stack_frame *sf;
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	sf = kzalloc(sizeof(*sf), GFP_NOFS);
86862306a36Sopenharmony_ci	if (sf)
86962306a36Sopenharmony_ci		sf->magic = BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER;
87062306a36Sopenharmony_ci	return sf;
87162306a36Sopenharmony_ci}
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_cistatic void btrfsic_stack_frame_free(struct btrfsic_stack_frame *sf)
87462306a36Sopenharmony_ci{
87562306a36Sopenharmony_ci	BUG_ON(!(NULL == sf ||
87662306a36Sopenharmony_ci		 BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER == sf->magic));
87762306a36Sopenharmony_ci	kfree(sf);
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic noinline_for_stack int btrfsic_process_metablock(
88162306a36Sopenharmony_ci		struct btrfsic_state *state,
88262306a36Sopenharmony_ci		struct btrfsic_block *const first_block,
88362306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *const first_block_ctx,
88462306a36Sopenharmony_ci		int first_limit_nesting, int force_iodone_flag)
88562306a36Sopenharmony_ci{
88662306a36Sopenharmony_ci	struct btrfsic_stack_frame initial_stack_frame = { 0 };
88762306a36Sopenharmony_ci	struct btrfsic_stack_frame *sf;
88862306a36Sopenharmony_ci	struct btrfsic_stack_frame *next_stack;
88962306a36Sopenharmony_ci	struct btrfs_header *const first_hdr =
89062306a36Sopenharmony_ci		(struct btrfs_header *)first_block_ctx->datav[0];
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	BUG_ON(!first_hdr);
89362306a36Sopenharmony_ci	sf = &initial_stack_frame;
89462306a36Sopenharmony_ci	sf->error = 0;
89562306a36Sopenharmony_ci	sf->i = -1;
89662306a36Sopenharmony_ci	sf->limit_nesting = first_limit_nesting;
89762306a36Sopenharmony_ci	sf->block = first_block;
89862306a36Sopenharmony_ci	sf->block_ctx = first_block_ctx;
89962306a36Sopenharmony_ci	sf->next_block = NULL;
90062306a36Sopenharmony_ci	sf->hdr = first_hdr;
90162306a36Sopenharmony_ci	sf->prev = NULL;
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_cicontinue_with_new_stack_frame:
90462306a36Sopenharmony_ci	sf->block->generation = btrfs_stack_header_generation(sf->hdr);
90562306a36Sopenharmony_ci	if (0 == sf->hdr->level) {
90662306a36Sopenharmony_ci		struct btrfs_leaf *const leafhdr =
90762306a36Sopenharmony_ci		    (struct btrfs_leaf *)sf->hdr;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci		if (-1 == sf->i) {
91062306a36Sopenharmony_ci			sf->nr = btrfs_stack_header_nritems(&leafhdr->header);
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
91362306a36Sopenharmony_ci				pr_info("leaf %llu items %d generation %llu owner %llu\n",
91462306a36Sopenharmony_ci				       sf->block_ctx->start, sf->nr,
91562306a36Sopenharmony_ci				       btrfs_stack_header_generation(
91662306a36Sopenharmony_ci					       &leafhdr->header),
91762306a36Sopenharmony_ci				       btrfs_stack_header_owner(
91862306a36Sopenharmony_ci					       &leafhdr->header));
91962306a36Sopenharmony_ci		}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_cicontinue_with_current_leaf_stack_frame:
92262306a36Sopenharmony_ci		if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) {
92362306a36Sopenharmony_ci			sf->i++;
92462306a36Sopenharmony_ci			sf->num_copies = 0;
92562306a36Sopenharmony_ci		}
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci		if (sf->i < sf->nr) {
92862306a36Sopenharmony_ci			struct btrfs_item disk_item;
92962306a36Sopenharmony_ci			u32 disk_item_offset =
93062306a36Sopenharmony_ci				(uintptr_t)(leafhdr->items + sf->i) -
93162306a36Sopenharmony_ci				(uintptr_t)leafhdr;
93262306a36Sopenharmony_ci			struct btrfs_disk_key *disk_key;
93362306a36Sopenharmony_ci			u8 type;
93462306a36Sopenharmony_ci			u32 item_offset;
93562306a36Sopenharmony_ci			u32 item_size;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci			if (disk_item_offset + sizeof(struct btrfs_item) >
93862306a36Sopenharmony_ci			    sf->block_ctx->len) {
93962306a36Sopenharmony_cileaf_item_out_of_bounce_error:
94062306a36Sopenharmony_ci				pr_info(
94162306a36Sopenharmony_ci		"btrfsic: leaf item out of bounce at logical %llu, dev %pg\n",
94262306a36Sopenharmony_ci				       sf->block_ctx->start,
94362306a36Sopenharmony_ci				       sf->block_ctx->dev->bdev);
94462306a36Sopenharmony_ci				goto one_stack_frame_backwards;
94562306a36Sopenharmony_ci			}
94662306a36Sopenharmony_ci			btrfsic_read_from_block_data(sf->block_ctx,
94762306a36Sopenharmony_ci						     &disk_item,
94862306a36Sopenharmony_ci						     disk_item_offset,
94962306a36Sopenharmony_ci						     sizeof(struct btrfs_item));
95062306a36Sopenharmony_ci			item_offset = btrfs_stack_item_offset(&disk_item);
95162306a36Sopenharmony_ci			item_size = btrfs_stack_item_size(&disk_item);
95262306a36Sopenharmony_ci			disk_key = &disk_item.key;
95362306a36Sopenharmony_ci			type = btrfs_disk_key_type(disk_key);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci			if (BTRFS_ROOT_ITEM_KEY == type) {
95662306a36Sopenharmony_ci				struct btrfs_root_item root_item;
95762306a36Sopenharmony_ci				u32 root_item_offset;
95862306a36Sopenharmony_ci				u64 next_bytenr;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci				root_item_offset = item_offset +
96162306a36Sopenharmony_ci					offsetof(struct btrfs_leaf, items);
96262306a36Sopenharmony_ci				if (root_item_offset + item_size >
96362306a36Sopenharmony_ci				    sf->block_ctx->len)
96462306a36Sopenharmony_ci					goto leaf_item_out_of_bounce_error;
96562306a36Sopenharmony_ci				btrfsic_read_from_block_data(
96662306a36Sopenharmony_ci					sf->block_ctx, &root_item,
96762306a36Sopenharmony_ci					root_item_offset,
96862306a36Sopenharmony_ci					item_size);
96962306a36Sopenharmony_ci				next_bytenr = btrfs_root_bytenr(&root_item);
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci				sf->error =
97262306a36Sopenharmony_ci				    btrfsic_create_link_to_next_block(
97362306a36Sopenharmony_ci						state,
97462306a36Sopenharmony_ci						sf->block,
97562306a36Sopenharmony_ci						sf->block_ctx,
97662306a36Sopenharmony_ci						next_bytenr,
97762306a36Sopenharmony_ci						sf->limit_nesting,
97862306a36Sopenharmony_ci						&sf->next_block_ctx,
97962306a36Sopenharmony_ci						&sf->next_block,
98062306a36Sopenharmony_ci						force_iodone_flag,
98162306a36Sopenharmony_ci						&sf->num_copies,
98262306a36Sopenharmony_ci						&sf->mirror_num,
98362306a36Sopenharmony_ci						disk_key,
98462306a36Sopenharmony_ci						btrfs_root_generation(
98562306a36Sopenharmony_ci						&root_item));
98662306a36Sopenharmony_ci				if (sf->error)
98762306a36Sopenharmony_ci					goto one_stack_frame_backwards;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci				if (NULL != sf->next_block) {
99062306a36Sopenharmony_ci					struct btrfs_header *const next_hdr =
99162306a36Sopenharmony_ci					    (struct btrfs_header *)
99262306a36Sopenharmony_ci					    sf->next_block_ctx.datav[0];
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci					next_stack =
99562306a36Sopenharmony_ci					    btrfsic_stack_frame_alloc();
99662306a36Sopenharmony_ci					if (NULL == next_stack) {
99762306a36Sopenharmony_ci						sf->error = -1;
99862306a36Sopenharmony_ci						btrfsic_release_block_ctx(
99962306a36Sopenharmony_ci								&sf->
100062306a36Sopenharmony_ci								next_block_ctx);
100162306a36Sopenharmony_ci						goto one_stack_frame_backwards;
100262306a36Sopenharmony_ci					}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci					next_stack->i = -1;
100562306a36Sopenharmony_ci					next_stack->block = sf->next_block;
100662306a36Sopenharmony_ci					next_stack->block_ctx =
100762306a36Sopenharmony_ci					    &sf->next_block_ctx;
100862306a36Sopenharmony_ci					next_stack->next_block = NULL;
100962306a36Sopenharmony_ci					next_stack->hdr = next_hdr;
101062306a36Sopenharmony_ci					next_stack->limit_nesting =
101162306a36Sopenharmony_ci					    sf->limit_nesting - 1;
101262306a36Sopenharmony_ci					next_stack->prev = sf;
101362306a36Sopenharmony_ci					sf = next_stack;
101462306a36Sopenharmony_ci					goto continue_with_new_stack_frame;
101562306a36Sopenharmony_ci				}
101662306a36Sopenharmony_ci			} else if (BTRFS_EXTENT_DATA_KEY == type &&
101762306a36Sopenharmony_ci				   state->include_extent_data) {
101862306a36Sopenharmony_ci				sf->error = btrfsic_handle_extent_data(
101962306a36Sopenharmony_ci						state,
102062306a36Sopenharmony_ci						sf->block,
102162306a36Sopenharmony_ci						sf->block_ctx,
102262306a36Sopenharmony_ci						item_offset,
102362306a36Sopenharmony_ci						force_iodone_flag);
102462306a36Sopenharmony_ci				if (sf->error)
102562306a36Sopenharmony_ci					goto one_stack_frame_backwards;
102662306a36Sopenharmony_ci			}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci			goto continue_with_current_leaf_stack_frame;
102962306a36Sopenharmony_ci		}
103062306a36Sopenharmony_ci	} else {
103162306a36Sopenharmony_ci		struct btrfs_node *const nodehdr = (struct btrfs_node *)sf->hdr;
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci		if (-1 == sf->i) {
103462306a36Sopenharmony_ci			sf->nr = btrfs_stack_header_nritems(&nodehdr->header);
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
103762306a36Sopenharmony_ci				pr_info("node %llu level %d items %d generation %llu owner %llu\n",
103862306a36Sopenharmony_ci				       sf->block_ctx->start,
103962306a36Sopenharmony_ci				       nodehdr->header.level, sf->nr,
104062306a36Sopenharmony_ci				       btrfs_stack_header_generation(
104162306a36Sopenharmony_ci				       &nodehdr->header),
104262306a36Sopenharmony_ci				       btrfs_stack_header_owner(
104362306a36Sopenharmony_ci				       &nodehdr->header));
104462306a36Sopenharmony_ci		}
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_cicontinue_with_current_node_stack_frame:
104762306a36Sopenharmony_ci		if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) {
104862306a36Sopenharmony_ci			sf->i++;
104962306a36Sopenharmony_ci			sf->num_copies = 0;
105062306a36Sopenharmony_ci		}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci		if (sf->i < sf->nr) {
105362306a36Sopenharmony_ci			struct btrfs_key_ptr key_ptr;
105462306a36Sopenharmony_ci			u32 key_ptr_offset;
105562306a36Sopenharmony_ci			u64 next_bytenr;
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci			key_ptr_offset = (uintptr_t)(nodehdr->ptrs + sf->i) -
105862306a36Sopenharmony_ci					  (uintptr_t)nodehdr;
105962306a36Sopenharmony_ci			if (key_ptr_offset + sizeof(struct btrfs_key_ptr) >
106062306a36Sopenharmony_ci			    sf->block_ctx->len) {
106162306a36Sopenharmony_ci				pr_info(
106262306a36Sopenharmony_ci		"btrfsic: node item out of bounce at logical %llu, dev %pg\n",
106362306a36Sopenharmony_ci				       sf->block_ctx->start,
106462306a36Sopenharmony_ci				       sf->block_ctx->dev->bdev);
106562306a36Sopenharmony_ci				goto one_stack_frame_backwards;
106662306a36Sopenharmony_ci			}
106762306a36Sopenharmony_ci			btrfsic_read_from_block_data(
106862306a36Sopenharmony_ci				sf->block_ctx, &key_ptr, key_ptr_offset,
106962306a36Sopenharmony_ci				sizeof(struct btrfs_key_ptr));
107062306a36Sopenharmony_ci			next_bytenr = btrfs_stack_key_blockptr(&key_ptr);
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci			sf->error = btrfsic_create_link_to_next_block(
107362306a36Sopenharmony_ci					state,
107462306a36Sopenharmony_ci					sf->block,
107562306a36Sopenharmony_ci					sf->block_ctx,
107662306a36Sopenharmony_ci					next_bytenr,
107762306a36Sopenharmony_ci					sf->limit_nesting,
107862306a36Sopenharmony_ci					&sf->next_block_ctx,
107962306a36Sopenharmony_ci					&sf->next_block,
108062306a36Sopenharmony_ci					force_iodone_flag,
108162306a36Sopenharmony_ci					&sf->num_copies,
108262306a36Sopenharmony_ci					&sf->mirror_num,
108362306a36Sopenharmony_ci					&key_ptr.key,
108462306a36Sopenharmony_ci					btrfs_stack_key_generation(&key_ptr));
108562306a36Sopenharmony_ci			if (sf->error)
108662306a36Sopenharmony_ci				goto one_stack_frame_backwards;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci			if (NULL != sf->next_block) {
108962306a36Sopenharmony_ci				struct btrfs_header *const next_hdr =
109062306a36Sopenharmony_ci				    (struct btrfs_header *)
109162306a36Sopenharmony_ci				    sf->next_block_ctx.datav[0];
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci				next_stack = btrfsic_stack_frame_alloc();
109462306a36Sopenharmony_ci				if (NULL == next_stack) {
109562306a36Sopenharmony_ci					sf->error = -1;
109662306a36Sopenharmony_ci					goto one_stack_frame_backwards;
109762306a36Sopenharmony_ci				}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci				next_stack->i = -1;
110062306a36Sopenharmony_ci				next_stack->block = sf->next_block;
110162306a36Sopenharmony_ci				next_stack->block_ctx = &sf->next_block_ctx;
110262306a36Sopenharmony_ci				next_stack->next_block = NULL;
110362306a36Sopenharmony_ci				next_stack->hdr = next_hdr;
110462306a36Sopenharmony_ci				next_stack->limit_nesting =
110562306a36Sopenharmony_ci				    sf->limit_nesting - 1;
110662306a36Sopenharmony_ci				next_stack->prev = sf;
110762306a36Sopenharmony_ci				sf = next_stack;
110862306a36Sopenharmony_ci				goto continue_with_new_stack_frame;
110962306a36Sopenharmony_ci			}
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci			goto continue_with_current_node_stack_frame;
111262306a36Sopenharmony_ci		}
111362306a36Sopenharmony_ci	}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cione_stack_frame_backwards:
111662306a36Sopenharmony_ci	if (NULL != sf->prev) {
111762306a36Sopenharmony_ci		struct btrfsic_stack_frame *const prev = sf->prev;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci		/* the one for the initial block is freed in the caller */
112062306a36Sopenharmony_ci		btrfsic_release_block_ctx(sf->block_ctx);
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci		if (sf->error) {
112362306a36Sopenharmony_ci			prev->error = sf->error;
112462306a36Sopenharmony_ci			btrfsic_stack_frame_free(sf);
112562306a36Sopenharmony_ci			sf = prev;
112662306a36Sopenharmony_ci			goto one_stack_frame_backwards;
112762306a36Sopenharmony_ci		}
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci		btrfsic_stack_frame_free(sf);
113062306a36Sopenharmony_ci		sf = prev;
113162306a36Sopenharmony_ci		goto continue_with_new_stack_frame;
113262306a36Sopenharmony_ci	} else {
113362306a36Sopenharmony_ci		BUG_ON(&initial_stack_frame != sf);
113462306a36Sopenharmony_ci	}
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	return sf->error;
113762306a36Sopenharmony_ci}
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_cistatic void btrfsic_read_from_block_data(
114062306a36Sopenharmony_ci	struct btrfsic_block_data_ctx *block_ctx,
114162306a36Sopenharmony_ci	void *dstv, u32 offset, size_t len)
114262306a36Sopenharmony_ci{
114362306a36Sopenharmony_ci	size_t cur;
114462306a36Sopenharmony_ci	size_t pgoff;
114562306a36Sopenharmony_ci	char *kaddr;
114662306a36Sopenharmony_ci	char *dst = (char *)dstv;
114762306a36Sopenharmony_ci	size_t start_offset = offset_in_page(block_ctx->start);
114862306a36Sopenharmony_ci	unsigned long i = (start_offset + offset) >> PAGE_SHIFT;
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	WARN_ON(offset + len > block_ctx->len);
115162306a36Sopenharmony_ci	pgoff = offset_in_page(start_offset + offset);
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	while (len > 0) {
115462306a36Sopenharmony_ci		cur = min(len, ((size_t)PAGE_SIZE - pgoff));
115562306a36Sopenharmony_ci		BUG_ON(i >= DIV_ROUND_UP(block_ctx->len, PAGE_SIZE));
115662306a36Sopenharmony_ci		kaddr = block_ctx->datav[i];
115762306a36Sopenharmony_ci		memcpy(dst, kaddr + pgoff, cur);
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci		dst += cur;
116062306a36Sopenharmony_ci		len -= cur;
116162306a36Sopenharmony_ci		pgoff = 0;
116262306a36Sopenharmony_ci		i++;
116362306a36Sopenharmony_ci	}
116462306a36Sopenharmony_ci}
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_cistatic int btrfsic_create_link_to_next_block(
116762306a36Sopenharmony_ci		struct btrfsic_state *state,
116862306a36Sopenharmony_ci		struct btrfsic_block *block,
116962306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *block_ctx,
117062306a36Sopenharmony_ci		u64 next_bytenr,
117162306a36Sopenharmony_ci		int limit_nesting,
117262306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *next_block_ctx,
117362306a36Sopenharmony_ci		struct btrfsic_block **next_blockp,
117462306a36Sopenharmony_ci		int force_iodone_flag,
117562306a36Sopenharmony_ci		int *num_copiesp, int *mirror_nump,
117662306a36Sopenharmony_ci		struct btrfs_disk_key *disk_key,
117762306a36Sopenharmony_ci		u64 parent_generation)
117862306a36Sopenharmony_ci{
117962306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = state->fs_info;
118062306a36Sopenharmony_ci	struct btrfsic_block *next_block = NULL;
118162306a36Sopenharmony_ci	int ret;
118262306a36Sopenharmony_ci	struct btrfsic_block_link *l;
118362306a36Sopenharmony_ci	int did_alloc_block_link;
118462306a36Sopenharmony_ci	int block_was_created;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	*next_blockp = NULL;
118762306a36Sopenharmony_ci	if (0 == *num_copiesp) {
118862306a36Sopenharmony_ci		*num_copiesp = btrfs_num_copies(fs_info, next_bytenr,
118962306a36Sopenharmony_ci						state->metablock_size);
119062306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
119162306a36Sopenharmony_ci			pr_info("num_copies(log_bytenr=%llu) = %d\n",
119262306a36Sopenharmony_ci			       next_bytenr, *num_copiesp);
119362306a36Sopenharmony_ci		*mirror_nump = 1;
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	if (*mirror_nump > *num_copiesp)
119762306a36Sopenharmony_ci		return 0;
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
120062306a36Sopenharmony_ci		pr_info("btrfsic_create_link_to_next_block(mirror_num=%d)\n",
120162306a36Sopenharmony_ci		       *mirror_nump);
120262306a36Sopenharmony_ci	ret = btrfsic_map_block(state, next_bytenr,
120362306a36Sopenharmony_ci				state->metablock_size,
120462306a36Sopenharmony_ci				next_block_ctx, *mirror_nump);
120562306a36Sopenharmony_ci	if (ret) {
120662306a36Sopenharmony_ci		pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
120762306a36Sopenharmony_ci		       next_bytenr, *mirror_nump);
120862306a36Sopenharmony_ci		btrfsic_release_block_ctx(next_block_ctx);
120962306a36Sopenharmony_ci		*next_blockp = NULL;
121062306a36Sopenharmony_ci		return -1;
121162306a36Sopenharmony_ci	}
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	next_block = btrfsic_block_lookup_or_add(state,
121462306a36Sopenharmony_ci						 next_block_ctx, "referenced ",
121562306a36Sopenharmony_ci						 1, force_iodone_flag,
121662306a36Sopenharmony_ci						 !force_iodone_flag,
121762306a36Sopenharmony_ci						 *mirror_nump,
121862306a36Sopenharmony_ci						 &block_was_created);
121962306a36Sopenharmony_ci	if (NULL == next_block) {
122062306a36Sopenharmony_ci		btrfsic_release_block_ctx(next_block_ctx);
122162306a36Sopenharmony_ci		*next_blockp = NULL;
122262306a36Sopenharmony_ci		return -1;
122362306a36Sopenharmony_ci	}
122462306a36Sopenharmony_ci	if (block_was_created) {
122562306a36Sopenharmony_ci		l = NULL;
122662306a36Sopenharmony_ci		next_block->generation = BTRFSIC_GENERATION_UNKNOWN;
122762306a36Sopenharmony_ci	} else {
122862306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) {
122962306a36Sopenharmony_ci			if (next_block->logical_bytenr != next_bytenr &&
123062306a36Sopenharmony_ci			    !(!next_block->is_metadata &&
123162306a36Sopenharmony_ci			      0 == next_block->logical_bytenr))
123262306a36Sopenharmony_ci				pr_info(
123362306a36Sopenharmony_ci"referenced block @%llu (%pg/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu)\n",
123462306a36Sopenharmony_ci				       next_bytenr, next_block_ctx->dev->bdev,
123562306a36Sopenharmony_ci				       next_block_ctx->dev_bytenr, *mirror_nump,
123662306a36Sopenharmony_ci				       btrfsic_get_block_type(state,
123762306a36Sopenharmony_ci							      next_block),
123862306a36Sopenharmony_ci				       next_block->logical_bytenr);
123962306a36Sopenharmony_ci			else
124062306a36Sopenharmony_ci				pr_info(
124162306a36Sopenharmony_ci		"referenced block @%llu (%pg/%llu/%d) found in hash table, %c\n",
124262306a36Sopenharmony_ci				       next_bytenr, next_block_ctx->dev->bdev,
124362306a36Sopenharmony_ci				       next_block_ctx->dev_bytenr, *mirror_nump,
124462306a36Sopenharmony_ci				       btrfsic_get_block_type(state,
124562306a36Sopenharmony_ci							      next_block));
124662306a36Sopenharmony_ci		}
124762306a36Sopenharmony_ci		next_block->logical_bytenr = next_bytenr;
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci		next_block->mirror_num = *mirror_nump;
125062306a36Sopenharmony_ci		l = btrfsic_block_link_hashtable_lookup(
125162306a36Sopenharmony_ci				next_block_ctx->dev->bdev,
125262306a36Sopenharmony_ci				next_block_ctx->dev_bytenr,
125362306a36Sopenharmony_ci				block_ctx->dev->bdev,
125462306a36Sopenharmony_ci				block_ctx->dev_bytenr,
125562306a36Sopenharmony_ci				&state->block_link_hashtable);
125662306a36Sopenharmony_ci	}
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	next_block->disk_key = *disk_key;
125962306a36Sopenharmony_ci	if (NULL == l) {
126062306a36Sopenharmony_ci		l = btrfsic_block_link_alloc();
126162306a36Sopenharmony_ci		if (NULL == l) {
126262306a36Sopenharmony_ci			btrfsic_release_block_ctx(next_block_ctx);
126362306a36Sopenharmony_ci			*next_blockp = NULL;
126462306a36Sopenharmony_ci			return -1;
126562306a36Sopenharmony_ci		}
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci		did_alloc_block_link = 1;
126862306a36Sopenharmony_ci		l->block_ref_to = next_block;
126962306a36Sopenharmony_ci		l->block_ref_from = block;
127062306a36Sopenharmony_ci		l->ref_cnt = 1;
127162306a36Sopenharmony_ci		l->parent_generation = parent_generation;
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
127462306a36Sopenharmony_ci			btrfsic_print_add_link(state, l);
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci		list_add(&l->node_ref_to, &block->ref_to_list);
127762306a36Sopenharmony_ci		list_add(&l->node_ref_from, &next_block->ref_from_list);
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci		btrfsic_block_link_hashtable_add(l,
128062306a36Sopenharmony_ci						 &state->block_link_hashtable);
128162306a36Sopenharmony_ci	} else {
128262306a36Sopenharmony_ci		did_alloc_block_link = 0;
128362306a36Sopenharmony_ci		if (0 == limit_nesting) {
128462306a36Sopenharmony_ci			l->ref_cnt++;
128562306a36Sopenharmony_ci			l->parent_generation = parent_generation;
128662306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
128762306a36Sopenharmony_ci				btrfsic_print_add_link(state, l);
128862306a36Sopenharmony_ci		}
128962306a36Sopenharmony_ci	}
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci	if (limit_nesting > 0 && did_alloc_block_link) {
129262306a36Sopenharmony_ci		ret = btrfsic_read_block(state, next_block_ctx);
129362306a36Sopenharmony_ci		if (ret < (int)next_block_ctx->len) {
129462306a36Sopenharmony_ci			pr_info("btrfsic: read block @logical %llu failed!\n",
129562306a36Sopenharmony_ci			       next_bytenr);
129662306a36Sopenharmony_ci			btrfsic_release_block_ctx(next_block_ctx);
129762306a36Sopenharmony_ci			*next_blockp = NULL;
129862306a36Sopenharmony_ci			return -1;
129962306a36Sopenharmony_ci		}
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci		*next_blockp = next_block;
130262306a36Sopenharmony_ci	} else {
130362306a36Sopenharmony_ci		*next_blockp = NULL;
130462306a36Sopenharmony_ci	}
130562306a36Sopenharmony_ci	(*mirror_nump)++;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	return 0;
130862306a36Sopenharmony_ci}
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_cistatic int btrfsic_handle_extent_data(
131162306a36Sopenharmony_ci		struct btrfsic_state *state,
131262306a36Sopenharmony_ci		struct btrfsic_block *block,
131362306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *block_ctx,
131462306a36Sopenharmony_ci		u32 item_offset, int force_iodone_flag)
131562306a36Sopenharmony_ci{
131662306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = state->fs_info;
131762306a36Sopenharmony_ci	struct btrfs_file_extent_item file_extent_item;
131862306a36Sopenharmony_ci	u64 file_extent_item_offset;
131962306a36Sopenharmony_ci	u64 next_bytenr;
132062306a36Sopenharmony_ci	u64 num_bytes;
132162306a36Sopenharmony_ci	u64 generation;
132262306a36Sopenharmony_ci	struct btrfsic_block_link *l;
132362306a36Sopenharmony_ci	int ret;
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	file_extent_item_offset = offsetof(struct btrfs_leaf, items) +
132662306a36Sopenharmony_ci				  item_offset;
132762306a36Sopenharmony_ci	if (file_extent_item_offset +
132862306a36Sopenharmony_ci	    offsetof(struct btrfs_file_extent_item, disk_num_bytes) >
132962306a36Sopenharmony_ci	    block_ctx->len) {
133062306a36Sopenharmony_ci		pr_info("btrfsic: file item out of bounce at logical %llu, dev %pg\n",
133162306a36Sopenharmony_ci		       block_ctx->start, block_ctx->dev->bdev);
133262306a36Sopenharmony_ci		return -1;
133362306a36Sopenharmony_ci	}
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	btrfsic_read_from_block_data(block_ctx, &file_extent_item,
133662306a36Sopenharmony_ci		file_extent_item_offset,
133762306a36Sopenharmony_ci		offsetof(struct btrfs_file_extent_item, disk_num_bytes));
133862306a36Sopenharmony_ci	if (BTRFS_FILE_EXTENT_REG != file_extent_item.type ||
133962306a36Sopenharmony_ci	    btrfs_stack_file_extent_disk_bytenr(&file_extent_item) == 0) {
134062306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
134162306a36Sopenharmony_ci			pr_info("extent_data: type %u, disk_bytenr = %llu\n",
134262306a36Sopenharmony_ci			       file_extent_item.type,
134362306a36Sopenharmony_ci			       btrfs_stack_file_extent_disk_bytenr(
134462306a36Sopenharmony_ci			       &file_extent_item));
134562306a36Sopenharmony_ci		return 0;
134662306a36Sopenharmony_ci	}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	if (file_extent_item_offset + sizeof(struct btrfs_file_extent_item) >
134962306a36Sopenharmony_ci	    block_ctx->len) {
135062306a36Sopenharmony_ci		pr_info("btrfsic: file item out of bounce at logical %llu, dev %pg\n",
135162306a36Sopenharmony_ci		       block_ctx->start, block_ctx->dev->bdev);
135262306a36Sopenharmony_ci		return -1;
135362306a36Sopenharmony_ci	}
135462306a36Sopenharmony_ci	btrfsic_read_from_block_data(block_ctx, &file_extent_item,
135562306a36Sopenharmony_ci				     file_extent_item_offset,
135662306a36Sopenharmony_ci				     sizeof(struct btrfs_file_extent_item));
135762306a36Sopenharmony_ci	next_bytenr = btrfs_stack_file_extent_disk_bytenr(&file_extent_item);
135862306a36Sopenharmony_ci	if (btrfs_stack_file_extent_compression(&file_extent_item) ==
135962306a36Sopenharmony_ci	    BTRFS_COMPRESS_NONE) {
136062306a36Sopenharmony_ci		next_bytenr += btrfs_stack_file_extent_offset(&file_extent_item);
136162306a36Sopenharmony_ci		num_bytes = btrfs_stack_file_extent_num_bytes(&file_extent_item);
136262306a36Sopenharmony_ci	} else {
136362306a36Sopenharmony_ci		num_bytes = btrfs_stack_file_extent_disk_num_bytes(&file_extent_item);
136462306a36Sopenharmony_ci	}
136562306a36Sopenharmony_ci	generation = btrfs_stack_file_extent_generation(&file_extent_item);
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci	if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
136862306a36Sopenharmony_ci		pr_info("extent_data: type %u, disk_bytenr = %llu, offset = %llu, num_bytes = %llu\n",
136962306a36Sopenharmony_ci		       file_extent_item.type,
137062306a36Sopenharmony_ci		       btrfs_stack_file_extent_disk_bytenr(&file_extent_item),
137162306a36Sopenharmony_ci		       btrfs_stack_file_extent_offset(&file_extent_item),
137262306a36Sopenharmony_ci		       num_bytes);
137362306a36Sopenharmony_ci	while (num_bytes > 0) {
137462306a36Sopenharmony_ci		u32 chunk_len;
137562306a36Sopenharmony_ci		int num_copies;
137662306a36Sopenharmony_ci		int mirror_num;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci		if (num_bytes > state->datablock_size)
137962306a36Sopenharmony_ci			chunk_len = state->datablock_size;
138062306a36Sopenharmony_ci		else
138162306a36Sopenharmony_ci			chunk_len = num_bytes;
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci		num_copies = btrfs_num_copies(fs_info, next_bytenr,
138462306a36Sopenharmony_ci					      state->datablock_size);
138562306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
138662306a36Sopenharmony_ci			pr_info("num_copies(log_bytenr=%llu) = %d\n",
138762306a36Sopenharmony_ci			       next_bytenr, num_copies);
138862306a36Sopenharmony_ci		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
138962306a36Sopenharmony_ci			struct btrfsic_block_data_ctx next_block_ctx;
139062306a36Sopenharmony_ci			struct btrfsic_block *next_block;
139162306a36Sopenharmony_ci			int block_was_created;
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
139462306a36Sopenharmony_ci				pr_info("btrfsic_handle_extent_data(mirror_num=%d)\n",
139562306a36Sopenharmony_ci					mirror_num);
139662306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
139762306a36Sopenharmony_ci				pr_info("\tdisk_bytenr = %llu, num_bytes %u\n",
139862306a36Sopenharmony_ci				       next_bytenr, chunk_len);
139962306a36Sopenharmony_ci			ret = btrfsic_map_block(state, next_bytenr,
140062306a36Sopenharmony_ci						chunk_len, &next_block_ctx,
140162306a36Sopenharmony_ci						mirror_num);
140262306a36Sopenharmony_ci			if (ret) {
140362306a36Sopenharmony_ci				pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
140462306a36Sopenharmony_ci				       next_bytenr, mirror_num);
140562306a36Sopenharmony_ci				return -1;
140662306a36Sopenharmony_ci			}
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci			next_block = btrfsic_block_lookup_or_add(
140962306a36Sopenharmony_ci					state,
141062306a36Sopenharmony_ci					&next_block_ctx,
141162306a36Sopenharmony_ci					"referenced ",
141262306a36Sopenharmony_ci					0,
141362306a36Sopenharmony_ci					force_iodone_flag,
141462306a36Sopenharmony_ci					!force_iodone_flag,
141562306a36Sopenharmony_ci					mirror_num,
141662306a36Sopenharmony_ci					&block_was_created);
141762306a36Sopenharmony_ci			if (NULL == next_block) {
141862306a36Sopenharmony_ci				btrfsic_release_block_ctx(&next_block_ctx);
141962306a36Sopenharmony_ci				return -1;
142062306a36Sopenharmony_ci			}
142162306a36Sopenharmony_ci			if (!block_was_created) {
142262306a36Sopenharmony_ci				if ((state->print_mask &
142362306a36Sopenharmony_ci				     BTRFSIC_PRINT_MASK_VERBOSE) &&
142462306a36Sopenharmony_ci				    next_block->logical_bytenr != next_bytenr &&
142562306a36Sopenharmony_ci				    !(!next_block->is_metadata &&
142662306a36Sopenharmony_ci				      0 == next_block->logical_bytenr)) {
142762306a36Sopenharmony_ci					pr_info(
142862306a36Sopenharmony_ci"referenced block @%llu (%pg/%llu/%d) found in hash table, D, bytenr mismatch (!= stored %llu)\n",
142962306a36Sopenharmony_ci					       next_bytenr,
143062306a36Sopenharmony_ci					       next_block_ctx.dev->bdev,
143162306a36Sopenharmony_ci					       next_block_ctx.dev_bytenr,
143262306a36Sopenharmony_ci					       mirror_num,
143362306a36Sopenharmony_ci					       next_block->logical_bytenr);
143462306a36Sopenharmony_ci				}
143562306a36Sopenharmony_ci				next_block->logical_bytenr = next_bytenr;
143662306a36Sopenharmony_ci				next_block->mirror_num = mirror_num;
143762306a36Sopenharmony_ci			}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci			l = btrfsic_block_link_lookup_or_add(state,
144062306a36Sopenharmony_ci							     &next_block_ctx,
144162306a36Sopenharmony_ci							     next_block, block,
144262306a36Sopenharmony_ci							     generation);
144362306a36Sopenharmony_ci			btrfsic_release_block_ctx(&next_block_ctx);
144462306a36Sopenharmony_ci			if (NULL == l)
144562306a36Sopenharmony_ci				return -1;
144662306a36Sopenharmony_ci		}
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci		next_bytenr += chunk_len;
144962306a36Sopenharmony_ci		num_bytes -= chunk_len;
145062306a36Sopenharmony_ci	}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci	return 0;
145362306a36Sopenharmony_ci}
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_cistatic int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
145662306a36Sopenharmony_ci			     struct btrfsic_block_data_ctx *block_ctx_out,
145762306a36Sopenharmony_ci			     int mirror_num)
145862306a36Sopenharmony_ci{
145962306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = state->fs_info;
146062306a36Sopenharmony_ci	int ret;
146162306a36Sopenharmony_ci	u64 length;
146262306a36Sopenharmony_ci	struct btrfs_io_context *bioc = NULL;
146362306a36Sopenharmony_ci	struct btrfs_io_stripe smap, *map;
146462306a36Sopenharmony_ci	struct btrfs_device *device;
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	length = len;
146762306a36Sopenharmony_ci	ret = btrfs_map_block(fs_info, BTRFS_MAP_READ, bytenr, &length, &bioc,
146862306a36Sopenharmony_ci			      NULL, &mirror_num, 0);
146962306a36Sopenharmony_ci	if (ret) {
147062306a36Sopenharmony_ci		block_ctx_out->start = 0;
147162306a36Sopenharmony_ci		block_ctx_out->dev_bytenr = 0;
147262306a36Sopenharmony_ci		block_ctx_out->len = 0;
147362306a36Sopenharmony_ci		block_ctx_out->dev = NULL;
147462306a36Sopenharmony_ci		block_ctx_out->datav = NULL;
147562306a36Sopenharmony_ci		block_ctx_out->pagev = NULL;
147662306a36Sopenharmony_ci		block_ctx_out->mem_to_free = NULL;
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci		return ret;
147962306a36Sopenharmony_ci	}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	if (bioc)
148262306a36Sopenharmony_ci		map = &bioc->stripes[0];
148362306a36Sopenharmony_ci	else
148462306a36Sopenharmony_ci		map = &smap;
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci	device = map->dev;
148762306a36Sopenharmony_ci	if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state) ||
148862306a36Sopenharmony_ci	    !device->bdev || !device->name)
148962306a36Sopenharmony_ci		block_ctx_out->dev = NULL;
149062306a36Sopenharmony_ci	else
149162306a36Sopenharmony_ci		block_ctx_out->dev = btrfsic_dev_state_lookup(
149262306a36Sopenharmony_ci							device->bdev->bd_dev);
149362306a36Sopenharmony_ci	block_ctx_out->dev_bytenr = map->physical;
149462306a36Sopenharmony_ci	block_ctx_out->start = bytenr;
149562306a36Sopenharmony_ci	block_ctx_out->len = len;
149662306a36Sopenharmony_ci	block_ctx_out->datav = NULL;
149762306a36Sopenharmony_ci	block_ctx_out->pagev = NULL;
149862306a36Sopenharmony_ci	block_ctx_out->mem_to_free = NULL;
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	kfree(bioc);
150162306a36Sopenharmony_ci	if (NULL == block_ctx_out->dev) {
150262306a36Sopenharmony_ci		ret = -ENXIO;
150362306a36Sopenharmony_ci		pr_info("btrfsic: error, cannot lookup dev (#1)!\n");
150462306a36Sopenharmony_ci	}
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci	return ret;
150762306a36Sopenharmony_ci}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_cistatic void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx)
151062306a36Sopenharmony_ci{
151162306a36Sopenharmony_ci	if (block_ctx->mem_to_free) {
151262306a36Sopenharmony_ci		unsigned int num_pages;
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci		BUG_ON(!block_ctx->datav);
151562306a36Sopenharmony_ci		BUG_ON(!block_ctx->pagev);
151662306a36Sopenharmony_ci		num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >>
151762306a36Sopenharmony_ci			    PAGE_SHIFT;
151862306a36Sopenharmony_ci		/* Pages must be unmapped in reverse order */
151962306a36Sopenharmony_ci		while (num_pages > 0) {
152062306a36Sopenharmony_ci			num_pages--;
152162306a36Sopenharmony_ci			if (block_ctx->datav[num_pages])
152262306a36Sopenharmony_ci				block_ctx->datav[num_pages] = NULL;
152362306a36Sopenharmony_ci			if (block_ctx->pagev[num_pages]) {
152462306a36Sopenharmony_ci				__free_page(block_ctx->pagev[num_pages]);
152562306a36Sopenharmony_ci				block_ctx->pagev[num_pages] = NULL;
152662306a36Sopenharmony_ci			}
152762306a36Sopenharmony_ci		}
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci		kfree(block_ctx->mem_to_free);
153062306a36Sopenharmony_ci		block_ctx->mem_to_free = NULL;
153162306a36Sopenharmony_ci		block_ctx->pagev = NULL;
153262306a36Sopenharmony_ci		block_ctx->datav = NULL;
153362306a36Sopenharmony_ci	}
153462306a36Sopenharmony_ci}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_cistatic int btrfsic_read_block(struct btrfsic_state *state,
153762306a36Sopenharmony_ci			      struct btrfsic_block_data_ctx *block_ctx)
153862306a36Sopenharmony_ci{
153962306a36Sopenharmony_ci	unsigned int num_pages;
154062306a36Sopenharmony_ci	unsigned int i;
154162306a36Sopenharmony_ci	size_t size;
154262306a36Sopenharmony_ci	u64 dev_bytenr;
154362306a36Sopenharmony_ci	int ret;
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci	BUG_ON(block_ctx->datav);
154662306a36Sopenharmony_ci	BUG_ON(block_ctx->pagev);
154762306a36Sopenharmony_ci	BUG_ON(block_ctx->mem_to_free);
154862306a36Sopenharmony_ci	if (!PAGE_ALIGNED(block_ctx->dev_bytenr)) {
154962306a36Sopenharmony_ci		pr_info("btrfsic: read_block() with unaligned bytenr %llu\n",
155062306a36Sopenharmony_ci		       block_ctx->dev_bytenr);
155162306a36Sopenharmony_ci		return -1;
155262306a36Sopenharmony_ci	}
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci	num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >>
155562306a36Sopenharmony_ci		    PAGE_SHIFT;
155662306a36Sopenharmony_ci	size = sizeof(*block_ctx->datav) + sizeof(*block_ctx->pagev);
155762306a36Sopenharmony_ci	block_ctx->mem_to_free = kcalloc(num_pages, size, GFP_NOFS);
155862306a36Sopenharmony_ci	if (!block_ctx->mem_to_free)
155962306a36Sopenharmony_ci		return -ENOMEM;
156062306a36Sopenharmony_ci	block_ctx->datav = block_ctx->mem_to_free;
156162306a36Sopenharmony_ci	block_ctx->pagev = (struct page **)(block_ctx->datav + num_pages);
156262306a36Sopenharmony_ci	ret = btrfs_alloc_page_array(num_pages, block_ctx->pagev);
156362306a36Sopenharmony_ci	if (ret)
156462306a36Sopenharmony_ci		return ret;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	dev_bytenr = block_ctx->dev_bytenr;
156762306a36Sopenharmony_ci	for (i = 0; i < num_pages;) {
156862306a36Sopenharmony_ci		struct bio *bio;
156962306a36Sopenharmony_ci		unsigned int j;
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci		bio = bio_alloc(block_ctx->dev->bdev, num_pages - i,
157262306a36Sopenharmony_ci				REQ_OP_READ, GFP_NOFS);
157362306a36Sopenharmony_ci		bio->bi_iter.bi_sector = dev_bytenr >> SECTOR_SHIFT;
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci		for (j = i; j < num_pages; j++) {
157662306a36Sopenharmony_ci			ret = bio_add_page(bio, block_ctx->pagev[j],
157762306a36Sopenharmony_ci					   PAGE_SIZE, 0);
157862306a36Sopenharmony_ci			if (PAGE_SIZE != ret)
157962306a36Sopenharmony_ci				break;
158062306a36Sopenharmony_ci		}
158162306a36Sopenharmony_ci		if (j == i) {
158262306a36Sopenharmony_ci			pr_info("btrfsic: error, failed to add a single page!\n");
158362306a36Sopenharmony_ci			return -1;
158462306a36Sopenharmony_ci		}
158562306a36Sopenharmony_ci		if (submit_bio_wait(bio)) {
158662306a36Sopenharmony_ci			pr_info("btrfsic: read error at logical %llu dev %pg!\n",
158762306a36Sopenharmony_ci			       block_ctx->start, block_ctx->dev->bdev);
158862306a36Sopenharmony_ci			bio_put(bio);
158962306a36Sopenharmony_ci			return -1;
159062306a36Sopenharmony_ci		}
159162306a36Sopenharmony_ci		bio_put(bio);
159262306a36Sopenharmony_ci		dev_bytenr += (j - i) * PAGE_SIZE;
159362306a36Sopenharmony_ci		i = j;
159462306a36Sopenharmony_ci	}
159562306a36Sopenharmony_ci	for (i = 0; i < num_pages; i++)
159662306a36Sopenharmony_ci		block_ctx->datav[i] = page_address(block_ctx->pagev[i]);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	return block_ctx->len;
159962306a36Sopenharmony_ci}
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_cistatic void btrfsic_dump_database(struct btrfsic_state *state)
160262306a36Sopenharmony_ci{
160362306a36Sopenharmony_ci	const struct btrfsic_block *b_all;
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci	BUG_ON(NULL == state);
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci	pr_info("all_blocks_list:\n");
160862306a36Sopenharmony_ci	list_for_each_entry(b_all, &state->all_blocks_list, all_blocks_node) {
160962306a36Sopenharmony_ci		const struct btrfsic_block_link *l;
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci		pr_info("%c-block @%llu (%pg/%llu/%d)\n",
161262306a36Sopenharmony_ci		       btrfsic_get_block_type(state, b_all),
161362306a36Sopenharmony_ci		       b_all->logical_bytenr, b_all->dev_state->bdev,
161462306a36Sopenharmony_ci		       b_all->dev_bytenr, b_all->mirror_num);
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci		list_for_each_entry(l, &b_all->ref_to_list, node_ref_to) {
161762306a36Sopenharmony_ci			pr_info(
161862306a36Sopenharmony_ci		" %c @%llu (%pg/%llu/%d) refers %u* to %c @%llu (%pg/%llu/%d)\n",
161962306a36Sopenharmony_ci			       btrfsic_get_block_type(state, b_all),
162062306a36Sopenharmony_ci			       b_all->logical_bytenr, b_all->dev_state->bdev,
162162306a36Sopenharmony_ci			       b_all->dev_bytenr, b_all->mirror_num,
162262306a36Sopenharmony_ci			       l->ref_cnt,
162362306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_to),
162462306a36Sopenharmony_ci			       l->block_ref_to->logical_bytenr,
162562306a36Sopenharmony_ci			       l->block_ref_to->dev_state->bdev,
162662306a36Sopenharmony_ci			       l->block_ref_to->dev_bytenr,
162762306a36Sopenharmony_ci			       l->block_ref_to->mirror_num);
162862306a36Sopenharmony_ci		}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci		list_for_each_entry(l, &b_all->ref_from_list, node_ref_from) {
163162306a36Sopenharmony_ci			pr_info(
163262306a36Sopenharmony_ci		" %c @%llu (%pg/%llu/%d) is ref %u* from %c @%llu (%pg/%llu/%d)\n",
163362306a36Sopenharmony_ci			       btrfsic_get_block_type(state, b_all),
163462306a36Sopenharmony_ci			       b_all->logical_bytenr, b_all->dev_state->bdev,
163562306a36Sopenharmony_ci			       b_all->dev_bytenr, b_all->mirror_num,
163662306a36Sopenharmony_ci			       l->ref_cnt,
163762306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_from),
163862306a36Sopenharmony_ci			       l->block_ref_from->logical_bytenr,
163962306a36Sopenharmony_ci			       l->block_ref_from->dev_state->bdev,
164062306a36Sopenharmony_ci			       l->block_ref_from->dev_bytenr,
164162306a36Sopenharmony_ci			       l->block_ref_from->mirror_num);
164262306a36Sopenharmony_ci		}
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci		pr_info("\n");
164562306a36Sopenharmony_ci	}
164662306a36Sopenharmony_ci}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci/*
164962306a36Sopenharmony_ci * Test whether the disk block contains a tree block (leaf or node)
165062306a36Sopenharmony_ci * (note that this test fails for the super block)
165162306a36Sopenharmony_ci */
165262306a36Sopenharmony_cistatic noinline_for_stack int btrfsic_test_for_metadata(
165362306a36Sopenharmony_ci		struct btrfsic_state *state,
165462306a36Sopenharmony_ci		char **datav, unsigned int num_pages)
165562306a36Sopenharmony_ci{
165662306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = state->fs_info;
165762306a36Sopenharmony_ci	SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
165862306a36Sopenharmony_ci	struct btrfs_header *h;
165962306a36Sopenharmony_ci	u8 csum[BTRFS_CSUM_SIZE];
166062306a36Sopenharmony_ci	unsigned int i;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	if (num_pages * PAGE_SIZE < state->metablock_size)
166362306a36Sopenharmony_ci		return 1; /* not metadata */
166462306a36Sopenharmony_ci	num_pages = state->metablock_size >> PAGE_SHIFT;
166562306a36Sopenharmony_ci	h = (struct btrfs_header *)datav[0];
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	if (memcmp(h->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE))
166862306a36Sopenharmony_ci		return 1;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	shash->tfm = fs_info->csum_shash;
167162306a36Sopenharmony_ci	crypto_shash_init(shash);
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci	for (i = 0; i < num_pages; i++) {
167462306a36Sopenharmony_ci		u8 *data = i ? datav[i] : (datav[i] + BTRFS_CSUM_SIZE);
167562306a36Sopenharmony_ci		size_t sublen = i ? PAGE_SIZE :
167662306a36Sopenharmony_ci				    (PAGE_SIZE - BTRFS_CSUM_SIZE);
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_ci		crypto_shash_update(shash, data, sublen);
167962306a36Sopenharmony_ci	}
168062306a36Sopenharmony_ci	crypto_shash_final(shash, csum);
168162306a36Sopenharmony_ci	if (memcmp(csum, h->csum, fs_info->csum_size))
168262306a36Sopenharmony_ci		return 1;
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	return 0; /* is metadata */
168562306a36Sopenharmony_ci}
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_cistatic void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
168862306a36Sopenharmony_ci					  u64 dev_bytenr, char **mapped_datav,
168962306a36Sopenharmony_ci					  unsigned int num_pages,
169062306a36Sopenharmony_ci					  struct bio *bio, int *bio_is_patched,
169162306a36Sopenharmony_ci					  blk_opf_t submit_bio_bh_rw)
169262306a36Sopenharmony_ci{
169362306a36Sopenharmony_ci	int is_metadata;
169462306a36Sopenharmony_ci	struct btrfsic_block *block;
169562306a36Sopenharmony_ci	struct btrfsic_block_data_ctx block_ctx;
169662306a36Sopenharmony_ci	int ret;
169762306a36Sopenharmony_ci	struct btrfsic_state *state = dev_state->state;
169862306a36Sopenharmony_ci	struct block_device *bdev = dev_state->bdev;
169962306a36Sopenharmony_ci	unsigned int processed_len;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	if (NULL != bio_is_patched)
170262306a36Sopenharmony_ci		*bio_is_patched = 0;
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ciagain:
170562306a36Sopenharmony_ci	if (num_pages == 0)
170662306a36Sopenharmony_ci		return;
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	processed_len = 0;
170962306a36Sopenharmony_ci	is_metadata = (0 == btrfsic_test_for_metadata(state, mapped_datav,
171062306a36Sopenharmony_ci						      num_pages));
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr,
171362306a36Sopenharmony_ci					       &state->block_hashtable);
171462306a36Sopenharmony_ci	if (NULL != block) {
171562306a36Sopenharmony_ci		u64 bytenr = 0;
171662306a36Sopenharmony_ci		struct btrfsic_block_link *l, *tmp;
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci		if (block->is_superblock) {
171962306a36Sopenharmony_ci			bytenr = btrfs_super_bytenr((struct btrfs_super_block *)
172062306a36Sopenharmony_ci						    mapped_datav[0]);
172162306a36Sopenharmony_ci			if (num_pages * PAGE_SIZE <
172262306a36Sopenharmony_ci			    BTRFS_SUPER_INFO_SIZE) {
172362306a36Sopenharmony_ci				pr_info("btrfsic: cannot work with too short bios!\n");
172462306a36Sopenharmony_ci				return;
172562306a36Sopenharmony_ci			}
172662306a36Sopenharmony_ci			is_metadata = 1;
172762306a36Sopenharmony_ci			BUG_ON(!PAGE_ALIGNED(BTRFS_SUPER_INFO_SIZE));
172862306a36Sopenharmony_ci			processed_len = BTRFS_SUPER_INFO_SIZE;
172962306a36Sopenharmony_ci			if (state->print_mask &
173062306a36Sopenharmony_ci			    BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE) {
173162306a36Sopenharmony_ci				pr_info("[before new superblock is written]:\n");
173262306a36Sopenharmony_ci				btrfsic_dump_tree_sub(state, block, 0);
173362306a36Sopenharmony_ci			}
173462306a36Sopenharmony_ci		}
173562306a36Sopenharmony_ci		if (is_metadata) {
173662306a36Sopenharmony_ci			if (!block->is_superblock) {
173762306a36Sopenharmony_ci				if (num_pages * PAGE_SIZE <
173862306a36Sopenharmony_ci				    state->metablock_size) {
173962306a36Sopenharmony_ci					pr_info("btrfsic: cannot work with too short bios!\n");
174062306a36Sopenharmony_ci					return;
174162306a36Sopenharmony_ci				}
174262306a36Sopenharmony_ci				processed_len = state->metablock_size;
174362306a36Sopenharmony_ci				bytenr = btrfs_stack_header_bytenr(
174462306a36Sopenharmony_ci						(struct btrfs_header *)
174562306a36Sopenharmony_ci						mapped_datav[0]);
174662306a36Sopenharmony_ci				btrfsic_cmp_log_and_dev_bytenr(state, bytenr,
174762306a36Sopenharmony_ci							       dev_state,
174862306a36Sopenharmony_ci							       dev_bytenr);
174962306a36Sopenharmony_ci			}
175062306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) {
175162306a36Sopenharmony_ci				if (block->logical_bytenr != bytenr &&
175262306a36Sopenharmony_ci				    !(!block->is_metadata &&
175362306a36Sopenharmony_ci				      block->logical_bytenr == 0))
175462306a36Sopenharmony_ci					pr_info(
175562306a36Sopenharmony_ci"written block @%llu (%pg/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu)\n",
175662306a36Sopenharmony_ci					       bytenr, dev_state->bdev,
175762306a36Sopenharmony_ci					       dev_bytenr,
175862306a36Sopenharmony_ci					       block->mirror_num,
175962306a36Sopenharmony_ci					       btrfsic_get_block_type(state,
176062306a36Sopenharmony_ci								      block),
176162306a36Sopenharmony_ci					       block->logical_bytenr);
176262306a36Sopenharmony_ci				else
176362306a36Sopenharmony_ci					pr_info(
176462306a36Sopenharmony_ci		"written block @%llu (%pg/%llu/%d) found in hash table, %c\n",
176562306a36Sopenharmony_ci					       bytenr, dev_state->bdev,
176662306a36Sopenharmony_ci					       dev_bytenr, block->mirror_num,
176762306a36Sopenharmony_ci					       btrfsic_get_block_type(state,
176862306a36Sopenharmony_ci								      block));
176962306a36Sopenharmony_ci			}
177062306a36Sopenharmony_ci			block->logical_bytenr = bytenr;
177162306a36Sopenharmony_ci		} else {
177262306a36Sopenharmony_ci			if (num_pages * PAGE_SIZE <
177362306a36Sopenharmony_ci			    state->datablock_size) {
177462306a36Sopenharmony_ci				pr_info("btrfsic: cannot work with too short bios!\n");
177562306a36Sopenharmony_ci				return;
177662306a36Sopenharmony_ci			}
177762306a36Sopenharmony_ci			processed_len = state->datablock_size;
177862306a36Sopenharmony_ci			bytenr = block->logical_bytenr;
177962306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
178062306a36Sopenharmony_ci				pr_info(
178162306a36Sopenharmony_ci		"written block @%llu (%pg/%llu/%d) found in hash table, %c\n",
178262306a36Sopenharmony_ci				       bytenr, dev_state->bdev, dev_bytenr,
178362306a36Sopenharmony_ci				       block->mirror_num,
178462306a36Sopenharmony_ci				       btrfsic_get_block_type(state, block));
178562306a36Sopenharmony_ci		}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
178862306a36Sopenharmony_ci			pr_info("ref_to_list: %cE, ref_from_list: %cE\n",
178962306a36Sopenharmony_ci			       list_empty(&block->ref_to_list) ? ' ' : '!',
179062306a36Sopenharmony_ci			       list_empty(&block->ref_from_list) ? ' ' : '!');
179162306a36Sopenharmony_ci		if (btrfsic_is_block_ref_by_superblock(state, block, 0)) {
179262306a36Sopenharmony_ci			pr_info(
179362306a36Sopenharmony_ci"btrfs: attempt to overwrite %c-block @%llu (%pg/%llu/%d), old(gen=%llu, objectid=%llu, type=%d, offset=%llu), new(gen=%llu), which is referenced by most recent superblock (superblockgen=%llu)!\n",
179462306a36Sopenharmony_ci			       btrfsic_get_block_type(state, block), bytenr,
179562306a36Sopenharmony_ci			       dev_state->bdev, dev_bytenr, block->mirror_num,
179662306a36Sopenharmony_ci			       block->generation,
179762306a36Sopenharmony_ci			       btrfs_disk_key_objectid(&block->disk_key),
179862306a36Sopenharmony_ci			       block->disk_key.type,
179962306a36Sopenharmony_ci			       btrfs_disk_key_offset(&block->disk_key),
180062306a36Sopenharmony_ci			       btrfs_stack_header_generation(
180162306a36Sopenharmony_ci				       (struct btrfs_header *) mapped_datav[0]),
180262306a36Sopenharmony_ci			       state->max_superblock_generation);
180362306a36Sopenharmony_ci			btrfsic_dump_tree(state);
180462306a36Sopenharmony_ci		}
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci		if (!block->is_iodone && !block->never_written) {
180762306a36Sopenharmony_ci			pr_info(
180862306a36Sopenharmony_ci"btrfs: attempt to overwrite %c-block @%llu (%pg/%llu/%d), oldgen=%llu, newgen=%llu, which is not yet iodone!\n",
180962306a36Sopenharmony_ci			       btrfsic_get_block_type(state, block), bytenr,
181062306a36Sopenharmony_ci			       dev_state->bdev, dev_bytenr, block->mirror_num,
181162306a36Sopenharmony_ci			       block->generation,
181262306a36Sopenharmony_ci			       btrfs_stack_header_generation(
181362306a36Sopenharmony_ci				       (struct btrfs_header *)
181462306a36Sopenharmony_ci				       mapped_datav[0]));
181562306a36Sopenharmony_ci			/* it would not be safe to go on */
181662306a36Sopenharmony_ci			btrfsic_dump_tree(state);
181762306a36Sopenharmony_ci			goto continue_loop;
181862306a36Sopenharmony_ci		}
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci		/*
182162306a36Sopenharmony_ci		 * Clear all references of this block. Do not free
182262306a36Sopenharmony_ci		 * the block itself even if is not referenced anymore
182362306a36Sopenharmony_ci		 * because it still carries valuable information
182462306a36Sopenharmony_ci		 * like whether it was ever written and IO completed.
182562306a36Sopenharmony_ci		 */
182662306a36Sopenharmony_ci		list_for_each_entry_safe(l, tmp, &block->ref_to_list,
182762306a36Sopenharmony_ci					 node_ref_to) {
182862306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
182962306a36Sopenharmony_ci				btrfsic_print_rem_link(state, l);
183062306a36Sopenharmony_ci			l->ref_cnt--;
183162306a36Sopenharmony_ci			if (0 == l->ref_cnt) {
183262306a36Sopenharmony_ci				list_del(&l->node_ref_to);
183362306a36Sopenharmony_ci				list_del(&l->node_ref_from);
183462306a36Sopenharmony_ci				btrfsic_block_link_hashtable_remove(l);
183562306a36Sopenharmony_ci				btrfsic_block_link_free(l);
183662306a36Sopenharmony_ci			}
183762306a36Sopenharmony_ci		}
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci		block_ctx.dev = dev_state;
184062306a36Sopenharmony_ci		block_ctx.dev_bytenr = dev_bytenr;
184162306a36Sopenharmony_ci		block_ctx.start = bytenr;
184262306a36Sopenharmony_ci		block_ctx.len = processed_len;
184362306a36Sopenharmony_ci		block_ctx.pagev = NULL;
184462306a36Sopenharmony_ci		block_ctx.mem_to_free = NULL;
184562306a36Sopenharmony_ci		block_ctx.datav = mapped_datav;
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci		if (is_metadata || state->include_extent_data) {
184862306a36Sopenharmony_ci			block->never_written = 0;
184962306a36Sopenharmony_ci			block->iodone_w_error = 0;
185062306a36Sopenharmony_ci			if (NULL != bio) {
185162306a36Sopenharmony_ci				block->is_iodone = 0;
185262306a36Sopenharmony_ci				BUG_ON(NULL == bio_is_patched);
185362306a36Sopenharmony_ci				if (!*bio_is_patched) {
185462306a36Sopenharmony_ci					block->orig_bio_private =
185562306a36Sopenharmony_ci					    bio->bi_private;
185662306a36Sopenharmony_ci					block->orig_bio_end_io =
185762306a36Sopenharmony_ci					    bio->bi_end_io;
185862306a36Sopenharmony_ci					block->next_in_same_bio = NULL;
185962306a36Sopenharmony_ci					bio->bi_private = block;
186062306a36Sopenharmony_ci					bio->bi_end_io = btrfsic_bio_end_io;
186162306a36Sopenharmony_ci					*bio_is_patched = 1;
186262306a36Sopenharmony_ci				} else {
186362306a36Sopenharmony_ci					struct btrfsic_block *chained_block =
186462306a36Sopenharmony_ci					    (struct btrfsic_block *)
186562306a36Sopenharmony_ci					    bio->bi_private;
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci					BUG_ON(NULL == chained_block);
186862306a36Sopenharmony_ci					block->orig_bio_private =
186962306a36Sopenharmony_ci					    chained_block->orig_bio_private;
187062306a36Sopenharmony_ci					block->orig_bio_end_io =
187162306a36Sopenharmony_ci					    chained_block->orig_bio_end_io;
187262306a36Sopenharmony_ci					block->next_in_same_bio = chained_block;
187362306a36Sopenharmony_ci					bio->bi_private = block;
187462306a36Sopenharmony_ci				}
187562306a36Sopenharmony_ci			} else {
187662306a36Sopenharmony_ci				block->is_iodone = 1;
187762306a36Sopenharmony_ci				block->orig_bio_private = NULL;
187862306a36Sopenharmony_ci				block->orig_bio_end_io = NULL;
187962306a36Sopenharmony_ci				block->next_in_same_bio = NULL;
188062306a36Sopenharmony_ci			}
188162306a36Sopenharmony_ci		}
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci		block->flush_gen = dev_state->last_flush_gen + 1;
188462306a36Sopenharmony_ci		block->submit_bio_bh_rw = submit_bio_bh_rw;
188562306a36Sopenharmony_ci		if (is_metadata) {
188662306a36Sopenharmony_ci			block->logical_bytenr = bytenr;
188762306a36Sopenharmony_ci			block->is_metadata = 1;
188862306a36Sopenharmony_ci			if (block->is_superblock) {
188962306a36Sopenharmony_ci				BUG_ON(PAGE_SIZE !=
189062306a36Sopenharmony_ci				       BTRFS_SUPER_INFO_SIZE);
189162306a36Sopenharmony_ci				ret = btrfsic_process_written_superblock(
189262306a36Sopenharmony_ci						state,
189362306a36Sopenharmony_ci						block,
189462306a36Sopenharmony_ci						(struct btrfs_super_block *)
189562306a36Sopenharmony_ci						mapped_datav[0]);
189662306a36Sopenharmony_ci				if (state->print_mask &
189762306a36Sopenharmony_ci				    BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE) {
189862306a36Sopenharmony_ci					pr_info("[after new superblock is written]:\n");
189962306a36Sopenharmony_ci					btrfsic_dump_tree_sub(state, block, 0);
190062306a36Sopenharmony_ci				}
190162306a36Sopenharmony_ci			} else {
190262306a36Sopenharmony_ci				block->mirror_num = 0;	/* unknown */
190362306a36Sopenharmony_ci				ret = btrfsic_process_metablock(
190462306a36Sopenharmony_ci						state,
190562306a36Sopenharmony_ci						block,
190662306a36Sopenharmony_ci						&block_ctx,
190762306a36Sopenharmony_ci						0, 0);
190862306a36Sopenharmony_ci			}
190962306a36Sopenharmony_ci			if (ret)
191062306a36Sopenharmony_ci				pr_info("btrfsic: btrfsic_process_metablock(root @%llu) failed!\n",
191162306a36Sopenharmony_ci				       dev_bytenr);
191262306a36Sopenharmony_ci		} else {
191362306a36Sopenharmony_ci			block->is_metadata = 0;
191462306a36Sopenharmony_ci			block->mirror_num = 0;	/* unknown */
191562306a36Sopenharmony_ci			block->generation = BTRFSIC_GENERATION_UNKNOWN;
191662306a36Sopenharmony_ci			if (!state->include_extent_data
191762306a36Sopenharmony_ci			    && list_empty(&block->ref_from_list)) {
191862306a36Sopenharmony_ci				/*
191962306a36Sopenharmony_ci				 * disk block is overwritten with extent
192062306a36Sopenharmony_ci				 * data (not meta data) and we are configured
192162306a36Sopenharmony_ci				 * to not include extent data: take the
192262306a36Sopenharmony_ci				 * chance and free the block's memory
192362306a36Sopenharmony_ci				 */
192462306a36Sopenharmony_ci				btrfsic_block_hashtable_remove(block);
192562306a36Sopenharmony_ci				list_del(&block->all_blocks_node);
192662306a36Sopenharmony_ci				btrfsic_block_free(block);
192762306a36Sopenharmony_ci			}
192862306a36Sopenharmony_ci		}
192962306a36Sopenharmony_ci		btrfsic_release_block_ctx(&block_ctx);
193062306a36Sopenharmony_ci	} else {
193162306a36Sopenharmony_ci		/* block has not been found in hash table */
193262306a36Sopenharmony_ci		u64 bytenr;
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci		if (!is_metadata) {
193562306a36Sopenharmony_ci			processed_len = state->datablock_size;
193662306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
193762306a36Sopenharmony_ci				pr_info(
193862306a36Sopenharmony_ci			"written block (%pg/%llu/?) !found in hash table, D\n",
193962306a36Sopenharmony_ci				       dev_state->bdev, dev_bytenr);
194062306a36Sopenharmony_ci			if (!state->include_extent_data) {
194162306a36Sopenharmony_ci				/* ignore that written D block */
194262306a36Sopenharmony_ci				goto continue_loop;
194362306a36Sopenharmony_ci			}
194462306a36Sopenharmony_ci
194562306a36Sopenharmony_ci			/* this is getting ugly for the
194662306a36Sopenharmony_ci			 * include_extent_data case... */
194762306a36Sopenharmony_ci			bytenr = 0;	/* unknown */
194862306a36Sopenharmony_ci		} else {
194962306a36Sopenharmony_ci			processed_len = state->metablock_size;
195062306a36Sopenharmony_ci			bytenr = btrfs_stack_header_bytenr(
195162306a36Sopenharmony_ci					(struct btrfs_header *)
195262306a36Sopenharmony_ci					mapped_datav[0]);
195362306a36Sopenharmony_ci			btrfsic_cmp_log_and_dev_bytenr(state, bytenr, dev_state,
195462306a36Sopenharmony_ci						       dev_bytenr);
195562306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
195662306a36Sopenharmony_ci				pr_info(
195762306a36Sopenharmony_ci			"written block @%llu (%pg/%llu/?) !found in hash table, M\n",
195862306a36Sopenharmony_ci				       bytenr, dev_state->bdev, dev_bytenr);
195962306a36Sopenharmony_ci		}
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci		block_ctx.dev = dev_state;
196262306a36Sopenharmony_ci		block_ctx.dev_bytenr = dev_bytenr;
196362306a36Sopenharmony_ci		block_ctx.start = bytenr;
196462306a36Sopenharmony_ci		block_ctx.len = processed_len;
196562306a36Sopenharmony_ci		block_ctx.pagev = NULL;
196662306a36Sopenharmony_ci		block_ctx.mem_to_free = NULL;
196762306a36Sopenharmony_ci		block_ctx.datav = mapped_datav;
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci		block = btrfsic_block_alloc();
197062306a36Sopenharmony_ci		if (NULL == block) {
197162306a36Sopenharmony_ci			btrfsic_release_block_ctx(&block_ctx);
197262306a36Sopenharmony_ci			goto continue_loop;
197362306a36Sopenharmony_ci		}
197462306a36Sopenharmony_ci		block->dev_state = dev_state;
197562306a36Sopenharmony_ci		block->dev_bytenr = dev_bytenr;
197662306a36Sopenharmony_ci		block->logical_bytenr = bytenr;
197762306a36Sopenharmony_ci		block->is_metadata = is_metadata;
197862306a36Sopenharmony_ci		block->never_written = 0;
197962306a36Sopenharmony_ci		block->iodone_w_error = 0;
198062306a36Sopenharmony_ci		block->mirror_num = 0;	/* unknown */
198162306a36Sopenharmony_ci		block->flush_gen = dev_state->last_flush_gen + 1;
198262306a36Sopenharmony_ci		block->submit_bio_bh_rw = submit_bio_bh_rw;
198362306a36Sopenharmony_ci		if (NULL != bio) {
198462306a36Sopenharmony_ci			block->is_iodone = 0;
198562306a36Sopenharmony_ci			BUG_ON(NULL == bio_is_patched);
198662306a36Sopenharmony_ci			if (!*bio_is_patched) {
198762306a36Sopenharmony_ci				block->orig_bio_private = bio->bi_private;
198862306a36Sopenharmony_ci				block->orig_bio_end_io = bio->bi_end_io;
198962306a36Sopenharmony_ci				block->next_in_same_bio = NULL;
199062306a36Sopenharmony_ci				bio->bi_private = block;
199162306a36Sopenharmony_ci				bio->bi_end_io = btrfsic_bio_end_io;
199262306a36Sopenharmony_ci				*bio_is_patched = 1;
199362306a36Sopenharmony_ci			} else {
199462306a36Sopenharmony_ci				struct btrfsic_block *chained_block =
199562306a36Sopenharmony_ci				    (struct btrfsic_block *)
199662306a36Sopenharmony_ci				    bio->bi_private;
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci				BUG_ON(NULL == chained_block);
199962306a36Sopenharmony_ci				block->orig_bio_private =
200062306a36Sopenharmony_ci				    chained_block->orig_bio_private;
200162306a36Sopenharmony_ci				block->orig_bio_end_io =
200262306a36Sopenharmony_ci				    chained_block->orig_bio_end_io;
200362306a36Sopenharmony_ci				block->next_in_same_bio = chained_block;
200462306a36Sopenharmony_ci				bio->bi_private = block;
200562306a36Sopenharmony_ci			}
200662306a36Sopenharmony_ci		} else {
200762306a36Sopenharmony_ci			block->is_iodone = 1;
200862306a36Sopenharmony_ci			block->orig_bio_private = NULL;
200962306a36Sopenharmony_ci			block->orig_bio_end_io = NULL;
201062306a36Sopenharmony_ci			block->next_in_same_bio = NULL;
201162306a36Sopenharmony_ci		}
201262306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
201362306a36Sopenharmony_ci			pr_info("new written %c-block @%llu (%pg/%llu/%d)\n",
201462306a36Sopenharmony_ci			       is_metadata ? 'M' : 'D',
201562306a36Sopenharmony_ci			       block->logical_bytenr, block->dev_state->bdev,
201662306a36Sopenharmony_ci			       block->dev_bytenr, block->mirror_num);
201762306a36Sopenharmony_ci		list_add(&block->all_blocks_node, &state->all_blocks_list);
201862306a36Sopenharmony_ci		btrfsic_block_hashtable_add(block, &state->block_hashtable);
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci		if (is_metadata) {
202162306a36Sopenharmony_ci			ret = btrfsic_process_metablock(state, block,
202262306a36Sopenharmony_ci							&block_ctx, 0, 0);
202362306a36Sopenharmony_ci			if (ret)
202462306a36Sopenharmony_ci				pr_info("btrfsic: process_metablock(root @%llu) failed!\n",
202562306a36Sopenharmony_ci				       dev_bytenr);
202662306a36Sopenharmony_ci		}
202762306a36Sopenharmony_ci		btrfsic_release_block_ctx(&block_ctx);
202862306a36Sopenharmony_ci	}
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_cicontinue_loop:
203162306a36Sopenharmony_ci	BUG_ON(!processed_len);
203262306a36Sopenharmony_ci	dev_bytenr += processed_len;
203362306a36Sopenharmony_ci	mapped_datav += processed_len >> PAGE_SHIFT;
203462306a36Sopenharmony_ci	num_pages -= processed_len >> PAGE_SHIFT;
203562306a36Sopenharmony_ci	goto again;
203662306a36Sopenharmony_ci}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_cistatic void btrfsic_bio_end_io(struct bio *bp)
203962306a36Sopenharmony_ci{
204062306a36Sopenharmony_ci	struct btrfsic_block *block = bp->bi_private;
204162306a36Sopenharmony_ci	int iodone_w_error;
204262306a36Sopenharmony_ci
204362306a36Sopenharmony_ci	/* mutex is not held! This is not save if IO is not yet completed
204462306a36Sopenharmony_ci	 * on umount */
204562306a36Sopenharmony_ci	iodone_w_error = 0;
204662306a36Sopenharmony_ci	if (bp->bi_status)
204762306a36Sopenharmony_ci		iodone_w_error = 1;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	BUG_ON(NULL == block);
205062306a36Sopenharmony_ci	bp->bi_private = block->orig_bio_private;
205162306a36Sopenharmony_ci	bp->bi_end_io = block->orig_bio_end_io;
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci	do {
205462306a36Sopenharmony_ci		struct btrfsic_block *next_block;
205562306a36Sopenharmony_ci		struct btrfsic_dev_state *const dev_state = block->dev_state;
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci		if ((dev_state->state->print_mask &
205862306a36Sopenharmony_ci		     BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
205962306a36Sopenharmony_ci			pr_info("bio_end_io(err=%d) for %c @%llu (%pg/%llu/%d)\n",
206062306a36Sopenharmony_ci			       bp->bi_status,
206162306a36Sopenharmony_ci			       btrfsic_get_block_type(dev_state->state, block),
206262306a36Sopenharmony_ci			       block->logical_bytenr, dev_state->bdev,
206362306a36Sopenharmony_ci			       block->dev_bytenr, block->mirror_num);
206462306a36Sopenharmony_ci		next_block = block->next_in_same_bio;
206562306a36Sopenharmony_ci		block->iodone_w_error = iodone_w_error;
206662306a36Sopenharmony_ci		if (block->submit_bio_bh_rw & REQ_PREFLUSH) {
206762306a36Sopenharmony_ci			dev_state->last_flush_gen++;
206862306a36Sopenharmony_ci			if ((dev_state->state->print_mask &
206962306a36Sopenharmony_ci			     BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
207062306a36Sopenharmony_ci				pr_info("bio_end_io() new %pg flush_gen=%llu\n",
207162306a36Sopenharmony_ci				       dev_state->bdev,
207262306a36Sopenharmony_ci				       dev_state->last_flush_gen);
207362306a36Sopenharmony_ci		}
207462306a36Sopenharmony_ci		if (block->submit_bio_bh_rw & REQ_FUA)
207562306a36Sopenharmony_ci			block->flush_gen = 0; /* FUA completed means block is
207662306a36Sopenharmony_ci					       * on disk */
207762306a36Sopenharmony_ci		block->is_iodone = 1; /* for FLUSH, this releases the block */
207862306a36Sopenharmony_ci		block = next_block;
207962306a36Sopenharmony_ci	} while (NULL != block);
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	bp->bi_end_io(bp);
208262306a36Sopenharmony_ci}
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_cistatic int btrfsic_process_written_superblock(
208562306a36Sopenharmony_ci		struct btrfsic_state *state,
208662306a36Sopenharmony_ci		struct btrfsic_block *const superblock,
208762306a36Sopenharmony_ci		struct btrfs_super_block *const super_hdr)
208862306a36Sopenharmony_ci{
208962306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = state->fs_info;
209062306a36Sopenharmony_ci	int pass;
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	superblock->generation = btrfs_super_generation(super_hdr);
209362306a36Sopenharmony_ci	if (!(superblock->generation > state->max_superblock_generation ||
209462306a36Sopenharmony_ci	      0 == state->max_superblock_generation)) {
209562306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
209662306a36Sopenharmony_ci			pr_info(
209762306a36Sopenharmony_ci	"btrfsic: superblock @%llu (%pg/%llu/%d) with old gen %llu <= %llu\n",
209862306a36Sopenharmony_ci			       superblock->logical_bytenr,
209962306a36Sopenharmony_ci			       superblock->dev_state->bdev,
210062306a36Sopenharmony_ci			       superblock->dev_bytenr, superblock->mirror_num,
210162306a36Sopenharmony_ci			       btrfs_super_generation(super_hdr),
210262306a36Sopenharmony_ci			       state->max_superblock_generation);
210362306a36Sopenharmony_ci	} else {
210462306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
210562306a36Sopenharmony_ci			pr_info(
210662306a36Sopenharmony_ci	"btrfsic: got new superblock @%llu (%pg/%llu/%d) with new gen %llu > %llu\n",
210762306a36Sopenharmony_ci			       superblock->logical_bytenr,
210862306a36Sopenharmony_ci			       superblock->dev_state->bdev,
210962306a36Sopenharmony_ci			       superblock->dev_bytenr, superblock->mirror_num,
211062306a36Sopenharmony_ci			       btrfs_super_generation(super_hdr),
211162306a36Sopenharmony_ci			       state->max_superblock_generation);
211262306a36Sopenharmony_ci
211362306a36Sopenharmony_ci		state->max_superblock_generation =
211462306a36Sopenharmony_ci		    btrfs_super_generation(super_hdr);
211562306a36Sopenharmony_ci		state->latest_superblock = superblock;
211662306a36Sopenharmony_ci	}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	for (pass = 0; pass < 3; pass++) {
211962306a36Sopenharmony_ci		int ret;
212062306a36Sopenharmony_ci		u64 next_bytenr;
212162306a36Sopenharmony_ci		struct btrfsic_block *next_block;
212262306a36Sopenharmony_ci		struct btrfsic_block_data_ctx tmp_next_block_ctx;
212362306a36Sopenharmony_ci		struct btrfsic_block_link *l;
212462306a36Sopenharmony_ci		int num_copies;
212562306a36Sopenharmony_ci		int mirror_num;
212662306a36Sopenharmony_ci		const char *additional_string = NULL;
212762306a36Sopenharmony_ci		struct btrfs_disk_key tmp_disk_key = {0};
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci		btrfs_set_disk_key_objectid(&tmp_disk_key,
213062306a36Sopenharmony_ci					    BTRFS_ROOT_ITEM_KEY);
213162306a36Sopenharmony_ci		btrfs_set_disk_key_objectid(&tmp_disk_key, 0);
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ci		switch (pass) {
213462306a36Sopenharmony_ci		case 0:
213562306a36Sopenharmony_ci			btrfs_set_disk_key_objectid(&tmp_disk_key,
213662306a36Sopenharmony_ci						    BTRFS_ROOT_TREE_OBJECTID);
213762306a36Sopenharmony_ci			additional_string = "root ";
213862306a36Sopenharmony_ci			next_bytenr = btrfs_super_root(super_hdr);
213962306a36Sopenharmony_ci			if (state->print_mask &
214062306a36Sopenharmony_ci			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
214162306a36Sopenharmony_ci				pr_info("root@%llu\n", next_bytenr);
214262306a36Sopenharmony_ci			break;
214362306a36Sopenharmony_ci		case 1:
214462306a36Sopenharmony_ci			btrfs_set_disk_key_objectid(&tmp_disk_key,
214562306a36Sopenharmony_ci						    BTRFS_CHUNK_TREE_OBJECTID);
214662306a36Sopenharmony_ci			additional_string = "chunk ";
214762306a36Sopenharmony_ci			next_bytenr = btrfs_super_chunk_root(super_hdr);
214862306a36Sopenharmony_ci			if (state->print_mask &
214962306a36Sopenharmony_ci			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
215062306a36Sopenharmony_ci				pr_info("chunk@%llu\n", next_bytenr);
215162306a36Sopenharmony_ci			break;
215262306a36Sopenharmony_ci		case 2:
215362306a36Sopenharmony_ci			btrfs_set_disk_key_objectid(&tmp_disk_key,
215462306a36Sopenharmony_ci						    BTRFS_TREE_LOG_OBJECTID);
215562306a36Sopenharmony_ci			additional_string = "log ";
215662306a36Sopenharmony_ci			next_bytenr = btrfs_super_log_root(super_hdr);
215762306a36Sopenharmony_ci			if (0 == next_bytenr)
215862306a36Sopenharmony_ci				continue;
215962306a36Sopenharmony_ci			if (state->print_mask &
216062306a36Sopenharmony_ci			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
216162306a36Sopenharmony_ci				pr_info("log@%llu\n", next_bytenr);
216262306a36Sopenharmony_ci			break;
216362306a36Sopenharmony_ci		}
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci		num_copies = btrfs_num_copies(fs_info, next_bytenr,
216662306a36Sopenharmony_ci					      BTRFS_SUPER_INFO_SIZE);
216762306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
216862306a36Sopenharmony_ci			pr_info("num_copies(log_bytenr=%llu) = %d\n",
216962306a36Sopenharmony_ci			       next_bytenr, num_copies);
217062306a36Sopenharmony_ci		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
217162306a36Sopenharmony_ci			int was_created;
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
217462306a36Sopenharmony_ci				pr_info("btrfsic_process_written_superblock(mirror_num=%d)\n", mirror_num);
217562306a36Sopenharmony_ci			ret = btrfsic_map_block(state, next_bytenr,
217662306a36Sopenharmony_ci						BTRFS_SUPER_INFO_SIZE,
217762306a36Sopenharmony_ci						&tmp_next_block_ctx,
217862306a36Sopenharmony_ci						mirror_num);
217962306a36Sopenharmony_ci			if (ret) {
218062306a36Sopenharmony_ci				pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
218162306a36Sopenharmony_ci				       next_bytenr, mirror_num);
218262306a36Sopenharmony_ci				return -1;
218362306a36Sopenharmony_ci			}
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci			next_block = btrfsic_block_lookup_or_add(
218662306a36Sopenharmony_ci					state,
218762306a36Sopenharmony_ci					&tmp_next_block_ctx,
218862306a36Sopenharmony_ci					additional_string,
218962306a36Sopenharmony_ci					1, 0, 1,
219062306a36Sopenharmony_ci					mirror_num,
219162306a36Sopenharmony_ci					&was_created);
219262306a36Sopenharmony_ci			if (NULL == next_block) {
219362306a36Sopenharmony_ci				btrfsic_release_block_ctx(&tmp_next_block_ctx);
219462306a36Sopenharmony_ci				return -1;
219562306a36Sopenharmony_ci			}
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci			next_block->disk_key = tmp_disk_key;
219862306a36Sopenharmony_ci			if (was_created)
219962306a36Sopenharmony_ci				next_block->generation =
220062306a36Sopenharmony_ci				    BTRFSIC_GENERATION_UNKNOWN;
220162306a36Sopenharmony_ci			l = btrfsic_block_link_lookup_or_add(
220262306a36Sopenharmony_ci					state,
220362306a36Sopenharmony_ci					&tmp_next_block_ctx,
220462306a36Sopenharmony_ci					next_block,
220562306a36Sopenharmony_ci					superblock,
220662306a36Sopenharmony_ci					BTRFSIC_GENERATION_UNKNOWN);
220762306a36Sopenharmony_ci			btrfsic_release_block_ctx(&tmp_next_block_ctx);
220862306a36Sopenharmony_ci			if (NULL == l)
220962306a36Sopenharmony_ci				return -1;
221062306a36Sopenharmony_ci		}
221162306a36Sopenharmony_ci	}
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci	if (WARN_ON(-1 == btrfsic_check_all_ref_blocks(state, superblock, 0)))
221462306a36Sopenharmony_ci		btrfsic_dump_tree(state);
221562306a36Sopenharmony_ci
221662306a36Sopenharmony_ci	return 0;
221762306a36Sopenharmony_ci}
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_cistatic int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
222062306a36Sopenharmony_ci					struct btrfsic_block *const block,
222162306a36Sopenharmony_ci					int recursion_level)
222262306a36Sopenharmony_ci{
222362306a36Sopenharmony_ci	const struct btrfsic_block_link *l;
222462306a36Sopenharmony_ci	int ret = 0;
222562306a36Sopenharmony_ci
222662306a36Sopenharmony_ci	if (recursion_level >= 3 + BTRFS_MAX_LEVEL) {
222762306a36Sopenharmony_ci		/*
222862306a36Sopenharmony_ci		 * Note that this situation can happen and does not
222962306a36Sopenharmony_ci		 * indicate an error in regular cases. It happens
223062306a36Sopenharmony_ci		 * when disk blocks are freed and later reused.
223162306a36Sopenharmony_ci		 * The check-integrity module is not aware of any
223262306a36Sopenharmony_ci		 * block free operations, it just recognizes block
223362306a36Sopenharmony_ci		 * write operations. Therefore it keeps the linkage
223462306a36Sopenharmony_ci		 * information for a block until a block is
223562306a36Sopenharmony_ci		 * rewritten. This can temporarily cause incorrect
223662306a36Sopenharmony_ci		 * and even circular linkage information. This
223762306a36Sopenharmony_ci		 * causes no harm unless such blocks are referenced
223862306a36Sopenharmony_ci		 * by the most recent super block.
223962306a36Sopenharmony_ci		 */
224062306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
224162306a36Sopenharmony_ci			pr_info("btrfsic: abort cyclic linkage (case 1).\n");
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_ci		return ret;
224462306a36Sopenharmony_ci	}
224562306a36Sopenharmony_ci
224662306a36Sopenharmony_ci	/*
224762306a36Sopenharmony_ci	 * This algorithm is recursive because the amount of used stack
224862306a36Sopenharmony_ci	 * space is very small and the max recursion depth is limited.
224962306a36Sopenharmony_ci	 */
225062306a36Sopenharmony_ci	list_for_each_entry(l, &block->ref_to_list, node_ref_to) {
225162306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
225262306a36Sopenharmony_ci			pr_info(
225362306a36Sopenharmony_ci		"rl=%d, %c @%llu (%pg/%llu/%d) %u* refers to %c @%llu (%pg/%llu/%d)\n",
225462306a36Sopenharmony_ci			       recursion_level,
225562306a36Sopenharmony_ci			       btrfsic_get_block_type(state, block),
225662306a36Sopenharmony_ci			       block->logical_bytenr, block->dev_state->bdev,
225762306a36Sopenharmony_ci			       block->dev_bytenr, block->mirror_num,
225862306a36Sopenharmony_ci			       l->ref_cnt,
225962306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_to),
226062306a36Sopenharmony_ci			       l->block_ref_to->logical_bytenr,
226162306a36Sopenharmony_ci			       l->block_ref_to->dev_state->bdev,
226262306a36Sopenharmony_ci			       l->block_ref_to->dev_bytenr,
226362306a36Sopenharmony_ci			       l->block_ref_to->mirror_num);
226462306a36Sopenharmony_ci		if (l->block_ref_to->never_written) {
226562306a36Sopenharmony_ci			pr_info(
226662306a36Sopenharmony_ci"btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) which is never written!\n",
226762306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_to),
226862306a36Sopenharmony_ci			       l->block_ref_to->logical_bytenr,
226962306a36Sopenharmony_ci			       l->block_ref_to->dev_state->bdev,
227062306a36Sopenharmony_ci			       l->block_ref_to->dev_bytenr,
227162306a36Sopenharmony_ci			       l->block_ref_to->mirror_num);
227262306a36Sopenharmony_ci			ret = -1;
227362306a36Sopenharmony_ci		} else if (!l->block_ref_to->is_iodone) {
227462306a36Sopenharmony_ci			pr_info(
227562306a36Sopenharmony_ci"btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) which is not yet iodone!\n",
227662306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_to),
227762306a36Sopenharmony_ci			       l->block_ref_to->logical_bytenr,
227862306a36Sopenharmony_ci			       l->block_ref_to->dev_state->bdev,
227962306a36Sopenharmony_ci			       l->block_ref_to->dev_bytenr,
228062306a36Sopenharmony_ci			       l->block_ref_to->mirror_num);
228162306a36Sopenharmony_ci			ret = -1;
228262306a36Sopenharmony_ci		} else if (l->block_ref_to->iodone_w_error) {
228362306a36Sopenharmony_ci			pr_info(
228462306a36Sopenharmony_ci"btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) which has write error!\n",
228562306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_to),
228662306a36Sopenharmony_ci			       l->block_ref_to->logical_bytenr,
228762306a36Sopenharmony_ci			       l->block_ref_to->dev_state->bdev,
228862306a36Sopenharmony_ci			       l->block_ref_to->dev_bytenr,
228962306a36Sopenharmony_ci			       l->block_ref_to->mirror_num);
229062306a36Sopenharmony_ci			ret = -1;
229162306a36Sopenharmony_ci		} else if (l->parent_generation !=
229262306a36Sopenharmony_ci			   l->block_ref_to->generation &&
229362306a36Sopenharmony_ci			   BTRFSIC_GENERATION_UNKNOWN !=
229462306a36Sopenharmony_ci			   l->parent_generation &&
229562306a36Sopenharmony_ci			   BTRFSIC_GENERATION_UNKNOWN !=
229662306a36Sopenharmony_ci			   l->block_ref_to->generation) {
229762306a36Sopenharmony_ci			pr_info(
229862306a36Sopenharmony_ci"btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) with generation %llu != parent generation %llu!\n",
229962306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_to),
230062306a36Sopenharmony_ci			       l->block_ref_to->logical_bytenr,
230162306a36Sopenharmony_ci			       l->block_ref_to->dev_state->bdev,
230262306a36Sopenharmony_ci			       l->block_ref_to->dev_bytenr,
230362306a36Sopenharmony_ci			       l->block_ref_to->mirror_num,
230462306a36Sopenharmony_ci			       l->block_ref_to->generation,
230562306a36Sopenharmony_ci			       l->parent_generation);
230662306a36Sopenharmony_ci			ret = -1;
230762306a36Sopenharmony_ci		} else if (l->block_ref_to->flush_gen >
230862306a36Sopenharmony_ci			   l->block_ref_to->dev_state->last_flush_gen) {
230962306a36Sopenharmony_ci			pr_info(
231062306a36Sopenharmony_ci"btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) which is not flushed out of disk's write cache (block flush_gen=%llu, dev->flush_gen=%llu)!\n",
231162306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_to),
231262306a36Sopenharmony_ci			       l->block_ref_to->logical_bytenr,
231362306a36Sopenharmony_ci			       l->block_ref_to->dev_state->bdev,
231462306a36Sopenharmony_ci			       l->block_ref_to->dev_bytenr,
231562306a36Sopenharmony_ci			       l->block_ref_to->mirror_num, block->flush_gen,
231662306a36Sopenharmony_ci			       l->block_ref_to->dev_state->last_flush_gen);
231762306a36Sopenharmony_ci			ret = -1;
231862306a36Sopenharmony_ci		} else if (-1 == btrfsic_check_all_ref_blocks(state,
231962306a36Sopenharmony_ci							      l->block_ref_to,
232062306a36Sopenharmony_ci							      recursion_level +
232162306a36Sopenharmony_ci							      1)) {
232262306a36Sopenharmony_ci			ret = -1;
232362306a36Sopenharmony_ci		}
232462306a36Sopenharmony_ci	}
232562306a36Sopenharmony_ci
232662306a36Sopenharmony_ci	return ret;
232762306a36Sopenharmony_ci}
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_cistatic int btrfsic_is_block_ref_by_superblock(
233062306a36Sopenharmony_ci		const struct btrfsic_state *state,
233162306a36Sopenharmony_ci		const struct btrfsic_block *block,
233262306a36Sopenharmony_ci		int recursion_level)
233362306a36Sopenharmony_ci{
233462306a36Sopenharmony_ci	const struct btrfsic_block_link *l;
233562306a36Sopenharmony_ci
233662306a36Sopenharmony_ci	if (recursion_level >= 3 + BTRFS_MAX_LEVEL) {
233762306a36Sopenharmony_ci		/* refer to comment at "abort cyclic linkage (case 1)" */
233862306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
233962306a36Sopenharmony_ci			pr_info("btrfsic: abort cyclic linkage (case 2).\n");
234062306a36Sopenharmony_ci
234162306a36Sopenharmony_ci		return 0;
234262306a36Sopenharmony_ci	}
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_ci	/*
234562306a36Sopenharmony_ci	 * This algorithm is recursive because the amount of used stack space
234662306a36Sopenharmony_ci	 * is very small and the max recursion depth is limited.
234762306a36Sopenharmony_ci	 */
234862306a36Sopenharmony_ci	list_for_each_entry(l, &block->ref_from_list, node_ref_from) {
234962306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
235062306a36Sopenharmony_ci			pr_info(
235162306a36Sopenharmony_ci	"rl=%d, %c @%llu (%pg/%llu/%d) is ref %u* from %c @%llu (%pg/%llu/%d)\n",
235262306a36Sopenharmony_ci			       recursion_level,
235362306a36Sopenharmony_ci			       btrfsic_get_block_type(state, block),
235462306a36Sopenharmony_ci			       block->logical_bytenr, block->dev_state->bdev,
235562306a36Sopenharmony_ci			       block->dev_bytenr, block->mirror_num,
235662306a36Sopenharmony_ci			       l->ref_cnt,
235762306a36Sopenharmony_ci			       btrfsic_get_block_type(state, l->block_ref_from),
235862306a36Sopenharmony_ci			       l->block_ref_from->logical_bytenr,
235962306a36Sopenharmony_ci			       l->block_ref_from->dev_state->bdev,
236062306a36Sopenharmony_ci			       l->block_ref_from->dev_bytenr,
236162306a36Sopenharmony_ci			       l->block_ref_from->mirror_num);
236262306a36Sopenharmony_ci		if (l->block_ref_from->is_superblock &&
236362306a36Sopenharmony_ci		    state->latest_superblock->dev_bytenr ==
236462306a36Sopenharmony_ci		    l->block_ref_from->dev_bytenr &&
236562306a36Sopenharmony_ci		    state->latest_superblock->dev_state->bdev ==
236662306a36Sopenharmony_ci		    l->block_ref_from->dev_state->bdev)
236762306a36Sopenharmony_ci			return 1;
236862306a36Sopenharmony_ci		else if (btrfsic_is_block_ref_by_superblock(state,
236962306a36Sopenharmony_ci							    l->block_ref_from,
237062306a36Sopenharmony_ci							    recursion_level +
237162306a36Sopenharmony_ci							    1))
237262306a36Sopenharmony_ci			return 1;
237362306a36Sopenharmony_ci	}
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci	return 0;
237662306a36Sopenharmony_ci}
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_cistatic void btrfsic_print_add_link(const struct btrfsic_state *state,
237962306a36Sopenharmony_ci				   const struct btrfsic_block_link *l)
238062306a36Sopenharmony_ci{
238162306a36Sopenharmony_ci	pr_info("add %u* link from %c @%llu (%pg/%llu/%d) to %c @%llu (%pg/%llu/%d)\n",
238262306a36Sopenharmony_ci	       l->ref_cnt,
238362306a36Sopenharmony_ci	       btrfsic_get_block_type(state, l->block_ref_from),
238462306a36Sopenharmony_ci	       l->block_ref_from->logical_bytenr,
238562306a36Sopenharmony_ci	       l->block_ref_from->dev_state->bdev,
238662306a36Sopenharmony_ci	       l->block_ref_from->dev_bytenr, l->block_ref_from->mirror_num,
238762306a36Sopenharmony_ci	       btrfsic_get_block_type(state, l->block_ref_to),
238862306a36Sopenharmony_ci	       l->block_ref_to->logical_bytenr,
238962306a36Sopenharmony_ci	       l->block_ref_to->dev_state->bdev, l->block_ref_to->dev_bytenr,
239062306a36Sopenharmony_ci	       l->block_ref_to->mirror_num);
239162306a36Sopenharmony_ci}
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_cistatic void btrfsic_print_rem_link(const struct btrfsic_state *state,
239462306a36Sopenharmony_ci				   const struct btrfsic_block_link *l)
239562306a36Sopenharmony_ci{
239662306a36Sopenharmony_ci	pr_info("rem %u* link from %c @%llu (%pg/%llu/%d) to %c @%llu (%pg/%llu/%d)\n",
239762306a36Sopenharmony_ci	       l->ref_cnt,
239862306a36Sopenharmony_ci	       btrfsic_get_block_type(state, l->block_ref_from),
239962306a36Sopenharmony_ci	       l->block_ref_from->logical_bytenr,
240062306a36Sopenharmony_ci	       l->block_ref_from->dev_state->bdev,
240162306a36Sopenharmony_ci	       l->block_ref_from->dev_bytenr, l->block_ref_from->mirror_num,
240262306a36Sopenharmony_ci	       btrfsic_get_block_type(state, l->block_ref_to),
240362306a36Sopenharmony_ci	       l->block_ref_to->logical_bytenr,
240462306a36Sopenharmony_ci	       l->block_ref_to->dev_state->bdev, l->block_ref_to->dev_bytenr,
240562306a36Sopenharmony_ci	       l->block_ref_to->mirror_num);
240662306a36Sopenharmony_ci}
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_cistatic char btrfsic_get_block_type(const struct btrfsic_state *state,
240962306a36Sopenharmony_ci				   const struct btrfsic_block *block)
241062306a36Sopenharmony_ci{
241162306a36Sopenharmony_ci	if (block->is_superblock &&
241262306a36Sopenharmony_ci	    state->latest_superblock->dev_bytenr == block->dev_bytenr &&
241362306a36Sopenharmony_ci	    state->latest_superblock->dev_state->bdev == block->dev_state->bdev)
241462306a36Sopenharmony_ci		return 'S';
241562306a36Sopenharmony_ci	else if (block->is_superblock)
241662306a36Sopenharmony_ci		return 's';
241762306a36Sopenharmony_ci	else if (block->is_metadata)
241862306a36Sopenharmony_ci		return 'M';
241962306a36Sopenharmony_ci	else
242062306a36Sopenharmony_ci		return 'D';
242162306a36Sopenharmony_ci}
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_cistatic void btrfsic_dump_tree(const struct btrfsic_state *state)
242462306a36Sopenharmony_ci{
242562306a36Sopenharmony_ci	btrfsic_dump_tree_sub(state, state->latest_superblock, 0);
242662306a36Sopenharmony_ci}
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_cistatic void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
242962306a36Sopenharmony_ci				  const struct btrfsic_block *block,
243062306a36Sopenharmony_ci				  int indent_level)
243162306a36Sopenharmony_ci{
243262306a36Sopenharmony_ci	const struct btrfsic_block_link *l;
243362306a36Sopenharmony_ci	int indent_add;
243462306a36Sopenharmony_ci	static char buf[80];
243562306a36Sopenharmony_ci	int cursor_position;
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_ci	/*
243862306a36Sopenharmony_ci	 * Should better fill an on-stack buffer with a complete line and
243962306a36Sopenharmony_ci	 * dump it at once when it is time to print a newline character.
244062306a36Sopenharmony_ci	 */
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	/*
244362306a36Sopenharmony_ci	 * This algorithm is recursive because the amount of used stack space
244462306a36Sopenharmony_ci	 * is very small and the max recursion depth is limited.
244562306a36Sopenharmony_ci	 */
244662306a36Sopenharmony_ci	indent_add = sprintf(buf, "%c-%llu(%pg/%llu/%u)",
244762306a36Sopenharmony_ci			     btrfsic_get_block_type(state, block),
244862306a36Sopenharmony_ci			     block->logical_bytenr, block->dev_state->bdev,
244962306a36Sopenharmony_ci			     block->dev_bytenr, block->mirror_num);
245062306a36Sopenharmony_ci	if (indent_level + indent_add > BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) {
245162306a36Sopenharmony_ci		printk("[...]\n");
245262306a36Sopenharmony_ci		return;
245362306a36Sopenharmony_ci	}
245462306a36Sopenharmony_ci	printk(buf);
245562306a36Sopenharmony_ci	indent_level += indent_add;
245662306a36Sopenharmony_ci	if (list_empty(&block->ref_to_list)) {
245762306a36Sopenharmony_ci		printk("\n");
245862306a36Sopenharmony_ci		return;
245962306a36Sopenharmony_ci	}
246062306a36Sopenharmony_ci	if (block->mirror_num > 1 &&
246162306a36Sopenharmony_ci	    !(state->print_mask & BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS)) {
246262306a36Sopenharmony_ci		printk(" [...]\n");
246362306a36Sopenharmony_ci		return;
246462306a36Sopenharmony_ci	}
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_ci	cursor_position = indent_level;
246762306a36Sopenharmony_ci	list_for_each_entry(l, &block->ref_to_list, node_ref_to) {
246862306a36Sopenharmony_ci		while (cursor_position < indent_level) {
246962306a36Sopenharmony_ci			printk(" ");
247062306a36Sopenharmony_ci			cursor_position++;
247162306a36Sopenharmony_ci		}
247262306a36Sopenharmony_ci		if (l->ref_cnt > 1)
247362306a36Sopenharmony_ci			indent_add = sprintf(buf, " %d*--> ", l->ref_cnt);
247462306a36Sopenharmony_ci		else
247562306a36Sopenharmony_ci			indent_add = sprintf(buf, " --> ");
247662306a36Sopenharmony_ci		if (indent_level + indent_add >
247762306a36Sopenharmony_ci		    BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) {
247862306a36Sopenharmony_ci			printk("[...]\n");
247962306a36Sopenharmony_ci			cursor_position = 0;
248062306a36Sopenharmony_ci			continue;
248162306a36Sopenharmony_ci		}
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci		printk(buf);
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci		btrfsic_dump_tree_sub(state, l->block_ref_to,
248662306a36Sopenharmony_ci				      indent_level + indent_add);
248762306a36Sopenharmony_ci		cursor_position = 0;
248862306a36Sopenharmony_ci	}
248962306a36Sopenharmony_ci}
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_lookup_or_add(
249262306a36Sopenharmony_ci		struct btrfsic_state *state,
249362306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *next_block_ctx,
249462306a36Sopenharmony_ci		struct btrfsic_block *next_block,
249562306a36Sopenharmony_ci		struct btrfsic_block *from_block,
249662306a36Sopenharmony_ci		u64 parent_generation)
249762306a36Sopenharmony_ci{
249862306a36Sopenharmony_ci	struct btrfsic_block_link *l;
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	l = btrfsic_block_link_hashtable_lookup(next_block_ctx->dev->bdev,
250162306a36Sopenharmony_ci						next_block_ctx->dev_bytenr,
250262306a36Sopenharmony_ci						from_block->dev_state->bdev,
250362306a36Sopenharmony_ci						from_block->dev_bytenr,
250462306a36Sopenharmony_ci						&state->block_link_hashtable);
250562306a36Sopenharmony_ci	if (NULL == l) {
250662306a36Sopenharmony_ci		l = btrfsic_block_link_alloc();
250762306a36Sopenharmony_ci		if (!l)
250862306a36Sopenharmony_ci			return NULL;
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_ci		l->block_ref_to = next_block;
251162306a36Sopenharmony_ci		l->block_ref_from = from_block;
251262306a36Sopenharmony_ci		l->ref_cnt = 1;
251362306a36Sopenharmony_ci		l->parent_generation = parent_generation;
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
251662306a36Sopenharmony_ci			btrfsic_print_add_link(state, l);
251762306a36Sopenharmony_ci
251862306a36Sopenharmony_ci		list_add(&l->node_ref_to, &from_block->ref_to_list);
251962306a36Sopenharmony_ci		list_add(&l->node_ref_from, &next_block->ref_from_list);
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci		btrfsic_block_link_hashtable_add(l,
252262306a36Sopenharmony_ci						 &state->block_link_hashtable);
252362306a36Sopenharmony_ci	} else {
252462306a36Sopenharmony_ci		l->ref_cnt++;
252562306a36Sopenharmony_ci		l->parent_generation = parent_generation;
252662306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
252762306a36Sopenharmony_ci			btrfsic_print_add_link(state, l);
252862306a36Sopenharmony_ci	}
252962306a36Sopenharmony_ci
253062306a36Sopenharmony_ci	return l;
253162306a36Sopenharmony_ci}
253262306a36Sopenharmony_ci
253362306a36Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_lookup_or_add(
253462306a36Sopenharmony_ci		struct btrfsic_state *state,
253562306a36Sopenharmony_ci		struct btrfsic_block_data_ctx *block_ctx,
253662306a36Sopenharmony_ci		const char *additional_string,
253762306a36Sopenharmony_ci		int is_metadata,
253862306a36Sopenharmony_ci		int is_iodone,
253962306a36Sopenharmony_ci		int never_written,
254062306a36Sopenharmony_ci		int mirror_num,
254162306a36Sopenharmony_ci		int *was_created)
254262306a36Sopenharmony_ci{
254362306a36Sopenharmony_ci	struct btrfsic_block *block;
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci	block = btrfsic_block_hashtable_lookup(block_ctx->dev->bdev,
254662306a36Sopenharmony_ci					       block_ctx->dev_bytenr,
254762306a36Sopenharmony_ci					       &state->block_hashtable);
254862306a36Sopenharmony_ci	if (NULL == block) {
254962306a36Sopenharmony_ci		struct btrfsic_dev_state *dev_state;
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci		block = btrfsic_block_alloc();
255262306a36Sopenharmony_ci		if (!block)
255362306a36Sopenharmony_ci			return NULL;
255462306a36Sopenharmony_ci
255562306a36Sopenharmony_ci		dev_state = btrfsic_dev_state_lookup(block_ctx->dev->bdev->bd_dev);
255662306a36Sopenharmony_ci		if (NULL == dev_state) {
255762306a36Sopenharmony_ci			pr_info("btrfsic: error, lookup dev_state failed!\n");
255862306a36Sopenharmony_ci			btrfsic_block_free(block);
255962306a36Sopenharmony_ci			return NULL;
256062306a36Sopenharmony_ci		}
256162306a36Sopenharmony_ci		block->dev_state = dev_state;
256262306a36Sopenharmony_ci		block->dev_bytenr = block_ctx->dev_bytenr;
256362306a36Sopenharmony_ci		block->logical_bytenr = block_ctx->start;
256462306a36Sopenharmony_ci		block->is_metadata = is_metadata;
256562306a36Sopenharmony_ci		block->is_iodone = is_iodone;
256662306a36Sopenharmony_ci		block->never_written = never_written;
256762306a36Sopenharmony_ci		block->mirror_num = mirror_num;
256862306a36Sopenharmony_ci		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
256962306a36Sopenharmony_ci			pr_info("New %s%c-block @%llu (%pg/%llu/%d)\n",
257062306a36Sopenharmony_ci			       additional_string,
257162306a36Sopenharmony_ci			       btrfsic_get_block_type(state, block),
257262306a36Sopenharmony_ci			       block->logical_bytenr, dev_state->bdev,
257362306a36Sopenharmony_ci			       block->dev_bytenr, mirror_num);
257462306a36Sopenharmony_ci		list_add(&block->all_blocks_node, &state->all_blocks_list);
257562306a36Sopenharmony_ci		btrfsic_block_hashtable_add(block, &state->block_hashtable);
257662306a36Sopenharmony_ci		if (NULL != was_created)
257762306a36Sopenharmony_ci			*was_created = 1;
257862306a36Sopenharmony_ci	} else {
257962306a36Sopenharmony_ci		if (NULL != was_created)
258062306a36Sopenharmony_ci			*was_created = 0;
258162306a36Sopenharmony_ci	}
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci	return block;
258462306a36Sopenharmony_ci}
258562306a36Sopenharmony_ci
258662306a36Sopenharmony_cistatic void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
258762306a36Sopenharmony_ci					   u64 bytenr,
258862306a36Sopenharmony_ci					   struct btrfsic_dev_state *dev_state,
258962306a36Sopenharmony_ci					   u64 dev_bytenr)
259062306a36Sopenharmony_ci{
259162306a36Sopenharmony_ci	struct btrfs_fs_info *fs_info = state->fs_info;
259262306a36Sopenharmony_ci	struct btrfsic_block_data_ctx block_ctx;
259362306a36Sopenharmony_ci	int num_copies;
259462306a36Sopenharmony_ci	int mirror_num;
259562306a36Sopenharmony_ci	int match = 0;
259662306a36Sopenharmony_ci	int ret;
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	num_copies = btrfs_num_copies(fs_info, bytenr, state->metablock_size);
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci	for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
260162306a36Sopenharmony_ci		ret = btrfsic_map_block(state, bytenr, state->metablock_size,
260262306a36Sopenharmony_ci					&block_ctx, mirror_num);
260362306a36Sopenharmony_ci		if (ret) {
260462306a36Sopenharmony_ci			pr_info("btrfsic: btrfsic_map_block(logical @%llu, mirror %d) failed!\n",
260562306a36Sopenharmony_ci			       bytenr, mirror_num);
260662306a36Sopenharmony_ci			continue;
260762306a36Sopenharmony_ci		}
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci		if (dev_state->bdev == block_ctx.dev->bdev &&
261062306a36Sopenharmony_ci		    dev_bytenr == block_ctx.dev_bytenr) {
261162306a36Sopenharmony_ci			match++;
261262306a36Sopenharmony_ci			btrfsic_release_block_ctx(&block_ctx);
261362306a36Sopenharmony_ci			break;
261462306a36Sopenharmony_ci		}
261562306a36Sopenharmony_ci		btrfsic_release_block_ctx(&block_ctx);
261662306a36Sopenharmony_ci	}
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci	if (WARN_ON(!match)) {
261962306a36Sopenharmony_ci		pr_info(
262062306a36Sopenharmony_ci"btrfs: attempt to write M-block which contains logical bytenr that doesn't map to dev+physical bytenr of submit_bio, buffer->log_bytenr=%llu, submit_bio(bdev=%pg, phys_bytenr=%llu)!\n",
262162306a36Sopenharmony_ci		       bytenr, dev_state->bdev, dev_bytenr);
262262306a36Sopenharmony_ci		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
262362306a36Sopenharmony_ci			ret = btrfsic_map_block(state, bytenr,
262462306a36Sopenharmony_ci						state->metablock_size,
262562306a36Sopenharmony_ci						&block_ctx, mirror_num);
262662306a36Sopenharmony_ci			if (ret)
262762306a36Sopenharmony_ci				continue;
262862306a36Sopenharmony_ci
262962306a36Sopenharmony_ci			pr_info("read logical bytenr @%llu maps to (%pg/%llu/%d)\n",
263062306a36Sopenharmony_ci			       bytenr, block_ctx.dev->bdev,
263162306a36Sopenharmony_ci			       block_ctx.dev_bytenr, mirror_num);
263262306a36Sopenharmony_ci		}
263362306a36Sopenharmony_ci	}
263462306a36Sopenharmony_ci}
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_lookup(dev_t dev)
263762306a36Sopenharmony_ci{
263862306a36Sopenharmony_ci	return btrfsic_dev_state_hashtable_lookup(dev,
263962306a36Sopenharmony_ci						  &btrfsic_dev_state_hashtable);
264062306a36Sopenharmony_ci}
264162306a36Sopenharmony_ci
264262306a36Sopenharmony_cistatic void btrfsic_check_write_bio(struct bio *bio, struct btrfsic_dev_state *dev_state)
264362306a36Sopenharmony_ci{
264462306a36Sopenharmony_ci	unsigned int segs = bio_segments(bio);
264562306a36Sopenharmony_ci	u64 dev_bytenr = 512 * bio->bi_iter.bi_sector;
264662306a36Sopenharmony_ci	u64 cur_bytenr = dev_bytenr;
264762306a36Sopenharmony_ci	struct bvec_iter iter;
264862306a36Sopenharmony_ci	struct bio_vec bvec;
264962306a36Sopenharmony_ci	char **mapped_datav;
265062306a36Sopenharmony_ci	int bio_is_patched = 0;
265162306a36Sopenharmony_ci	int i = 0;
265262306a36Sopenharmony_ci
265362306a36Sopenharmony_ci	if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
265462306a36Sopenharmony_ci		pr_info(
265562306a36Sopenharmony_ci"submit_bio(rw=%d,0x%x, bi_vcnt=%u, bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n",
265662306a36Sopenharmony_ci		       bio_op(bio), bio->bi_opf, segs,
265762306a36Sopenharmony_ci		       bio->bi_iter.bi_sector, dev_bytenr, bio->bi_bdev);
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci	mapped_datav = kmalloc_array(segs, sizeof(*mapped_datav), GFP_NOFS);
266062306a36Sopenharmony_ci	if (!mapped_datav)
266162306a36Sopenharmony_ci		return;
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_ci	bio_for_each_segment(bvec, bio, iter) {
266462306a36Sopenharmony_ci		BUG_ON(bvec.bv_len != PAGE_SIZE);
266562306a36Sopenharmony_ci		mapped_datav[i] = page_address(bvec.bv_page);
266662306a36Sopenharmony_ci		i++;
266762306a36Sopenharmony_ci
266862306a36Sopenharmony_ci		if (dev_state->state->print_mask &
266962306a36Sopenharmony_ci		    BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE)
267062306a36Sopenharmony_ci			pr_info("#%u: bytenr=%llu, len=%u, offset=%u\n",
267162306a36Sopenharmony_ci			       i, cur_bytenr, bvec.bv_len, bvec.bv_offset);
267262306a36Sopenharmony_ci		cur_bytenr += bvec.bv_len;
267362306a36Sopenharmony_ci	}
267462306a36Sopenharmony_ci
267562306a36Sopenharmony_ci	btrfsic_process_written_block(dev_state, dev_bytenr, mapped_datav, segs,
267662306a36Sopenharmony_ci				      bio, &bio_is_patched, bio->bi_opf);
267762306a36Sopenharmony_ci	kfree(mapped_datav);
267862306a36Sopenharmony_ci}
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_cistatic void btrfsic_check_flush_bio(struct bio *bio, struct btrfsic_dev_state *dev_state)
268162306a36Sopenharmony_ci{
268262306a36Sopenharmony_ci	if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
268362306a36Sopenharmony_ci		pr_info("submit_bio(rw=%d,0x%x FLUSH, bdev=%p)\n",
268462306a36Sopenharmony_ci		       bio_op(bio), bio->bi_opf, bio->bi_bdev);
268562306a36Sopenharmony_ci
268662306a36Sopenharmony_ci	if (dev_state->dummy_block_for_bio_bh_flush.is_iodone) {
268762306a36Sopenharmony_ci		struct btrfsic_block *const block =
268862306a36Sopenharmony_ci			&dev_state->dummy_block_for_bio_bh_flush;
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci		block->is_iodone = 0;
269162306a36Sopenharmony_ci		block->never_written = 0;
269262306a36Sopenharmony_ci		block->iodone_w_error = 0;
269362306a36Sopenharmony_ci		block->flush_gen = dev_state->last_flush_gen + 1;
269462306a36Sopenharmony_ci		block->submit_bio_bh_rw = bio->bi_opf;
269562306a36Sopenharmony_ci		block->orig_bio_private = bio->bi_private;
269662306a36Sopenharmony_ci		block->orig_bio_end_io = bio->bi_end_io;
269762306a36Sopenharmony_ci		block->next_in_same_bio = NULL;
269862306a36Sopenharmony_ci		bio->bi_private = block;
269962306a36Sopenharmony_ci		bio->bi_end_io = btrfsic_bio_end_io;
270062306a36Sopenharmony_ci	} else if ((dev_state->state->print_mask &
270162306a36Sopenharmony_ci		   (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
270262306a36Sopenharmony_ci		    BTRFSIC_PRINT_MASK_VERBOSE))) {
270362306a36Sopenharmony_ci		pr_info(
270462306a36Sopenharmony_ci"btrfsic_submit_bio(%pg) with FLUSH but dummy block already in use (ignored)!\n",
270562306a36Sopenharmony_ci		       dev_state->bdev);
270662306a36Sopenharmony_ci	}
270762306a36Sopenharmony_ci}
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_civoid btrfsic_check_bio(struct bio *bio)
271062306a36Sopenharmony_ci{
271162306a36Sopenharmony_ci	struct btrfsic_dev_state *dev_state;
271262306a36Sopenharmony_ci
271362306a36Sopenharmony_ci	if (!btrfsic_is_initialized)
271462306a36Sopenharmony_ci		return;
271562306a36Sopenharmony_ci
271662306a36Sopenharmony_ci	/*
271762306a36Sopenharmony_ci	 * We can be called before btrfsic_mount, so there might not be a
271862306a36Sopenharmony_ci	 * dev_state.
271962306a36Sopenharmony_ci	 */
272062306a36Sopenharmony_ci	dev_state = btrfsic_dev_state_lookup(bio->bi_bdev->bd_dev);
272162306a36Sopenharmony_ci	mutex_lock(&btrfsic_mutex);
272262306a36Sopenharmony_ci	if (dev_state) {
272362306a36Sopenharmony_ci		if (bio_op(bio) == REQ_OP_WRITE && bio_has_data(bio))
272462306a36Sopenharmony_ci			btrfsic_check_write_bio(bio, dev_state);
272562306a36Sopenharmony_ci		else if (bio->bi_opf & REQ_PREFLUSH)
272662306a36Sopenharmony_ci			btrfsic_check_flush_bio(bio, dev_state);
272762306a36Sopenharmony_ci	}
272862306a36Sopenharmony_ci	mutex_unlock(&btrfsic_mutex);
272962306a36Sopenharmony_ci}
273062306a36Sopenharmony_ci
273162306a36Sopenharmony_ciint btrfsic_mount(struct btrfs_fs_info *fs_info,
273262306a36Sopenharmony_ci		  struct btrfs_fs_devices *fs_devices,
273362306a36Sopenharmony_ci		  int including_extent_data, u32 print_mask)
273462306a36Sopenharmony_ci{
273562306a36Sopenharmony_ci	int ret;
273662306a36Sopenharmony_ci	struct btrfsic_state *state;
273762306a36Sopenharmony_ci	struct list_head *dev_head = &fs_devices->devices;
273862306a36Sopenharmony_ci	struct btrfs_device *device;
273962306a36Sopenharmony_ci
274062306a36Sopenharmony_ci	if (!PAGE_ALIGNED(fs_info->nodesize)) {
274162306a36Sopenharmony_ci		pr_info("btrfsic: cannot handle nodesize %d not being a multiple of PAGE_SIZE %ld!\n",
274262306a36Sopenharmony_ci		       fs_info->nodesize, PAGE_SIZE);
274362306a36Sopenharmony_ci		return -1;
274462306a36Sopenharmony_ci	}
274562306a36Sopenharmony_ci	if (!PAGE_ALIGNED(fs_info->sectorsize)) {
274662306a36Sopenharmony_ci		pr_info("btrfsic: cannot handle sectorsize %d not being a multiple of PAGE_SIZE %ld!\n",
274762306a36Sopenharmony_ci		       fs_info->sectorsize, PAGE_SIZE);
274862306a36Sopenharmony_ci		return -1;
274962306a36Sopenharmony_ci	}
275062306a36Sopenharmony_ci	state = kvzalloc(sizeof(*state), GFP_KERNEL);
275162306a36Sopenharmony_ci	if (!state)
275262306a36Sopenharmony_ci		return -ENOMEM;
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci	if (!btrfsic_is_initialized) {
275562306a36Sopenharmony_ci		mutex_init(&btrfsic_mutex);
275662306a36Sopenharmony_ci		btrfsic_dev_state_hashtable_init(&btrfsic_dev_state_hashtable);
275762306a36Sopenharmony_ci		btrfsic_is_initialized = 1;
275862306a36Sopenharmony_ci	}
275962306a36Sopenharmony_ci	mutex_lock(&btrfsic_mutex);
276062306a36Sopenharmony_ci	state->fs_info = fs_info;
276162306a36Sopenharmony_ci	state->print_mask = print_mask;
276262306a36Sopenharmony_ci	state->include_extent_data = including_extent_data;
276362306a36Sopenharmony_ci	state->metablock_size = fs_info->nodesize;
276462306a36Sopenharmony_ci	state->datablock_size = fs_info->sectorsize;
276562306a36Sopenharmony_ci	INIT_LIST_HEAD(&state->all_blocks_list);
276662306a36Sopenharmony_ci	btrfsic_block_hashtable_init(&state->block_hashtable);
276762306a36Sopenharmony_ci	btrfsic_block_link_hashtable_init(&state->block_link_hashtable);
276862306a36Sopenharmony_ci	state->max_superblock_generation = 0;
276962306a36Sopenharmony_ci	state->latest_superblock = NULL;
277062306a36Sopenharmony_ci
277162306a36Sopenharmony_ci	list_for_each_entry(device, dev_head, dev_list) {
277262306a36Sopenharmony_ci		struct btrfsic_dev_state *ds;
277362306a36Sopenharmony_ci
277462306a36Sopenharmony_ci		if (!device->bdev || !device->name)
277562306a36Sopenharmony_ci			continue;
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci		ds = btrfsic_dev_state_alloc();
277862306a36Sopenharmony_ci		if (NULL == ds) {
277962306a36Sopenharmony_ci			mutex_unlock(&btrfsic_mutex);
278062306a36Sopenharmony_ci			return -ENOMEM;
278162306a36Sopenharmony_ci		}
278262306a36Sopenharmony_ci		ds->bdev = device->bdev;
278362306a36Sopenharmony_ci		ds->state = state;
278462306a36Sopenharmony_ci		btrfsic_dev_state_hashtable_add(ds,
278562306a36Sopenharmony_ci						&btrfsic_dev_state_hashtable);
278662306a36Sopenharmony_ci	}
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_ci	ret = btrfsic_process_superblock(state, fs_devices);
278962306a36Sopenharmony_ci	if (0 != ret) {
279062306a36Sopenharmony_ci		mutex_unlock(&btrfsic_mutex);
279162306a36Sopenharmony_ci		btrfsic_unmount(fs_devices);
279262306a36Sopenharmony_ci		return ret;
279362306a36Sopenharmony_ci	}
279462306a36Sopenharmony_ci
279562306a36Sopenharmony_ci	if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_DATABASE)
279662306a36Sopenharmony_ci		btrfsic_dump_database(state);
279762306a36Sopenharmony_ci	if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_TREE)
279862306a36Sopenharmony_ci		btrfsic_dump_tree(state);
279962306a36Sopenharmony_ci
280062306a36Sopenharmony_ci	mutex_unlock(&btrfsic_mutex);
280162306a36Sopenharmony_ci	return 0;
280262306a36Sopenharmony_ci}
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_civoid btrfsic_unmount(struct btrfs_fs_devices *fs_devices)
280562306a36Sopenharmony_ci{
280662306a36Sopenharmony_ci	struct btrfsic_block *b_all, *tmp_all;
280762306a36Sopenharmony_ci	struct btrfsic_state *state;
280862306a36Sopenharmony_ci	struct list_head *dev_head = &fs_devices->devices;
280962306a36Sopenharmony_ci	struct btrfs_device *device;
281062306a36Sopenharmony_ci
281162306a36Sopenharmony_ci	if (!btrfsic_is_initialized)
281262306a36Sopenharmony_ci		return;
281362306a36Sopenharmony_ci
281462306a36Sopenharmony_ci	mutex_lock(&btrfsic_mutex);
281562306a36Sopenharmony_ci
281662306a36Sopenharmony_ci	state = NULL;
281762306a36Sopenharmony_ci	list_for_each_entry(device, dev_head, dev_list) {
281862306a36Sopenharmony_ci		struct btrfsic_dev_state *ds;
281962306a36Sopenharmony_ci
282062306a36Sopenharmony_ci		if (!device->bdev || !device->name)
282162306a36Sopenharmony_ci			continue;
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_ci		ds = btrfsic_dev_state_hashtable_lookup(
282462306a36Sopenharmony_ci				device->bdev->bd_dev,
282562306a36Sopenharmony_ci				&btrfsic_dev_state_hashtable);
282662306a36Sopenharmony_ci		if (NULL != ds) {
282762306a36Sopenharmony_ci			state = ds->state;
282862306a36Sopenharmony_ci			btrfsic_dev_state_hashtable_remove(ds);
282962306a36Sopenharmony_ci			btrfsic_dev_state_free(ds);
283062306a36Sopenharmony_ci		}
283162306a36Sopenharmony_ci	}
283262306a36Sopenharmony_ci
283362306a36Sopenharmony_ci	if (NULL == state) {
283462306a36Sopenharmony_ci		pr_info("btrfsic: error, cannot find state information on umount!\n");
283562306a36Sopenharmony_ci		mutex_unlock(&btrfsic_mutex);
283662306a36Sopenharmony_ci		return;
283762306a36Sopenharmony_ci	}
283862306a36Sopenharmony_ci
283962306a36Sopenharmony_ci	/*
284062306a36Sopenharmony_ci	 * Don't care about keeping the lists' state up to date,
284162306a36Sopenharmony_ci	 * just free all memory that was allocated dynamically.
284262306a36Sopenharmony_ci	 * Free the blocks and the block_links.
284362306a36Sopenharmony_ci	 */
284462306a36Sopenharmony_ci	list_for_each_entry_safe(b_all, tmp_all, &state->all_blocks_list,
284562306a36Sopenharmony_ci				 all_blocks_node) {
284662306a36Sopenharmony_ci		struct btrfsic_block_link *l, *tmp;
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci		list_for_each_entry_safe(l, tmp, &b_all->ref_to_list,
284962306a36Sopenharmony_ci					 node_ref_to) {
285062306a36Sopenharmony_ci			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
285162306a36Sopenharmony_ci				btrfsic_print_rem_link(state, l);
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci			l->ref_cnt--;
285462306a36Sopenharmony_ci			if (0 == l->ref_cnt)
285562306a36Sopenharmony_ci				btrfsic_block_link_free(l);
285662306a36Sopenharmony_ci		}
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci		if (b_all->is_iodone || b_all->never_written)
285962306a36Sopenharmony_ci			btrfsic_block_free(b_all);
286062306a36Sopenharmony_ci		else
286162306a36Sopenharmony_ci			pr_info(
286262306a36Sopenharmony_ci"btrfs: attempt to free %c-block @%llu (%pg/%llu/%d) on umount which is not yet iodone!\n",
286362306a36Sopenharmony_ci			       btrfsic_get_block_type(state, b_all),
286462306a36Sopenharmony_ci			       b_all->logical_bytenr, b_all->dev_state->bdev,
286562306a36Sopenharmony_ci			       b_all->dev_bytenr, b_all->mirror_num);
286662306a36Sopenharmony_ci	}
286762306a36Sopenharmony_ci
286862306a36Sopenharmony_ci	mutex_unlock(&btrfsic_mutex);
286962306a36Sopenharmony_ci
287062306a36Sopenharmony_ci	kvfree(state);
287162306a36Sopenharmony_ci}
2872