xref: /openbmc/linux/fs/btrfs/check-integrity.c (revision cd4efd21)
1c1d7c514SDavid Sterba // SPDX-License-Identifier: GPL-2.0
25db02760SStefan Behrens /*
35db02760SStefan Behrens  * Copyright (C) STRATO AG 2011.  All rights reserved.
45db02760SStefan Behrens  */
55db02760SStefan Behrens 
65db02760SStefan Behrens /*
75db02760SStefan Behrens  * This module can be used to catch cases when the btrfs kernel
85db02760SStefan Behrens  * code executes write requests to the disk that bring the file
95db02760SStefan Behrens  * system in an inconsistent state. In such a state, a power-loss
105db02760SStefan Behrens  * or kernel panic event would cause that the data on disk is
115db02760SStefan Behrens  * lost or at least damaged.
125db02760SStefan Behrens  *
135db02760SStefan Behrens  * Code is added that examines all block write requests during
145db02760SStefan Behrens  * runtime (including writes of the super block). Three rules
155db02760SStefan Behrens  * are verified and an error is printed on violation of the
165db02760SStefan Behrens  * rules:
175db02760SStefan Behrens  * 1. It is not allowed to write a disk block which is
185db02760SStefan Behrens  *    currently referenced by the super block (either directly
195db02760SStefan Behrens  *    or indirectly).
205db02760SStefan Behrens  * 2. When a super block is written, it is verified that all
215db02760SStefan Behrens  *    referenced (directly or indirectly) blocks fulfill the
225db02760SStefan Behrens  *    following requirements:
235db02760SStefan Behrens  *    2a. All referenced blocks have either been present when
245db02760SStefan Behrens  *        the file system was mounted, (i.e., they have been
255db02760SStefan Behrens  *        referenced by the super block) or they have been
265db02760SStefan Behrens  *        written since then and the write completion callback
2762856a9bSStefan Behrens  *        was called and no write error was indicated and a
2862856a9bSStefan Behrens  *        FLUSH request to the device where these blocks are
2962856a9bSStefan Behrens  *        located was received and completed.
305db02760SStefan Behrens  *    2b. All referenced blocks need to have a generation
315db02760SStefan Behrens  *        number which is equal to the parent's number.
325db02760SStefan Behrens  *
335db02760SStefan Behrens  * One issue that was found using this module was that the log
345db02760SStefan Behrens  * tree on disk became temporarily corrupted because disk blocks
355db02760SStefan Behrens  * that had been in use for the log tree had been freed and
365db02760SStefan Behrens  * reused too early, while being referenced by the written super
375db02760SStefan Behrens  * block.
385db02760SStefan Behrens  *
395db02760SStefan Behrens  * The search term in the kernel log that can be used to filter
405db02760SStefan Behrens  * on the existence of detected integrity issues is
415db02760SStefan Behrens  * "btrfs: attempt".
425db02760SStefan Behrens  *
435db02760SStefan Behrens  * The integrity check is enabled via mount options. These
445db02760SStefan Behrens  * mount options are only supported if the integrity check
455db02760SStefan Behrens  * tool is compiled by defining BTRFS_FS_CHECK_INTEGRITY.
465db02760SStefan Behrens  *
475db02760SStefan Behrens  * Example #1, apply integrity checks to all metadata:
485db02760SStefan Behrens  * mount /dev/sdb1 /mnt -o check_int
495db02760SStefan Behrens  *
505db02760SStefan Behrens  * Example #2, apply integrity checks to all metadata and
515db02760SStefan Behrens  * to data extents:
525db02760SStefan Behrens  * mount /dev/sdb1 /mnt -o check_int_data
535db02760SStefan Behrens  *
545db02760SStefan Behrens  * Example #3, apply integrity checks to all metadata and dump
555db02760SStefan Behrens  * the tree that the super block references to kernel messages
565db02760SStefan Behrens  * each time after a super block was written:
575db02760SStefan Behrens  * mount /dev/sdb1 /mnt -o check_int,check_int_print_mask=263
585db02760SStefan Behrens  *
595db02760SStefan Behrens  * If the integrity check tool is included and activated in
605db02760SStefan Behrens  * the mount options, plenty of kernel memory is used, and
615db02760SStefan Behrens  * plenty of additional CPU cycles are spent. Enabling this
625db02760SStefan Behrens  * functionality is not intended for normal use. In most
635db02760SStefan Behrens  * cases, unless you are a btrfs developer who needs to verify
645db02760SStefan Behrens  * the integrity of (super)-block write requests, do not
655db02760SStefan Behrens  * enable the config option BTRFS_FS_CHECK_INTEGRITY to
665db02760SStefan Behrens  * include and compile the integrity check tool.
6756d140f5SStefan Behrens  *
6856d140f5SStefan Behrens  * Expect millions of lines of information in the kernel log with an
6956d140f5SStefan Behrens  * enabled check_int_print_mask. Therefore set LOG_BUF_SHIFT in the
7056d140f5SStefan Behrens  * kernel config to at least 26 (which is 64MB). Usually the value is
7156d140f5SStefan Behrens  * limited to 21 (which is 2MB) in init/Kconfig. The file needs to be
7256d140f5SStefan Behrens  * changed like this before LOG_BUF_SHIFT can be set to a high value:
7356d140f5SStefan Behrens  * config LOG_BUF_SHIFT
7456d140f5SStefan Behrens  *       int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
7556d140f5SStefan Behrens  *       range 12 30
765db02760SStefan Behrens  */
775db02760SStefan Behrens 
785db02760SStefan Behrens #include <linux/sched.h>
795db02760SStefan Behrens #include <linux/slab.h>
805db02760SStefan Behrens #include <linux/mutex.h>
815db02760SStefan Behrens #include <linux/blkdev.h>
82818e010bSDavid Sterba #include <linux/mm.h>
8302def69fSRasmus Villemoes #include <linux/string.h>
84d5178578SJohannes Thumshirn #include <crypto/hash.h>
859b569ea0SJosef Bacik #include "messages.h"
865db02760SStefan Behrens #include "ctree.h"
875db02760SStefan Behrens #include "disk-io.h"
885db02760SStefan Behrens #include "transaction.h"
895db02760SStefan Behrens #include "extent_io.h"
905db02760SStefan Behrens #include "volumes.h"
915db02760SStefan Behrens #include "print-tree.h"
925db02760SStefan Behrens #include "locking.h"
935db02760SStefan Behrens #include "check-integrity.h"
94606686eeSJosef Bacik #include "rcu-string.h"
95ebb8765bSAnand Jain #include "compression.h"
9607e81dc9SJosef Bacik #include "accessors.h"
975db02760SStefan Behrens 
985db02760SStefan Behrens #define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000
995db02760SStefan Behrens #define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000
1005db02760SStefan Behrens #define BTRFSIC_DEV2STATE_HASHTABLE_SIZE 0x100
1015db02760SStefan Behrens #define BTRFSIC_BLOCK_MAGIC_NUMBER 0x14491051
1025db02760SStefan Behrens #define BTRFSIC_BLOCK_LINK_MAGIC_NUMBER 0x11070807
1035db02760SStefan Behrens #define BTRFSIC_DEV2STATE_MAGIC_NUMBER 0x20111530
1045db02760SStefan Behrens #define BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER 20111300
1055db02760SStefan Behrens #define BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL (200 - 6)	/* in characters,
1065db02760SStefan Behrens 							 * excluding " [...]" */
1075db02760SStefan Behrens #define BTRFSIC_GENERATION_UNKNOWN ((u64)-1)
1085db02760SStefan Behrens 
1095db02760SStefan Behrens /*
1105db02760SStefan Behrens  * The definition of the bitmask fields for the print_mask.
1115db02760SStefan Behrens  * They are specified with the mount option check_integrity_print_mask.
1125db02760SStefan Behrens  */
1135db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE			0x00000001
1145db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION		0x00000002
1155db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE			0x00000004
1165db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE			0x00000008
1175db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH			0x00000010
1185db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_END_IO_BIO_BH			0x00000020
1195db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_VERBOSE				0x00000040
1205db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_VERY_VERBOSE				0x00000080
1215db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_INITIAL_TREE				0x00000100
1225db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES			0x00000200
1235db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_INITIAL_DATABASE			0x00000400
1245db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_NUM_COPIES				0x00000800
1255db02760SStefan Behrens #define BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS		0x00001000
12656d140f5SStefan Behrens #define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE		0x00002000
1275db02760SStefan Behrens 
1285db02760SStefan Behrens struct btrfsic_dev_state;
1295db02760SStefan Behrens struct btrfsic_state;
1305db02760SStefan Behrens 
1315db02760SStefan Behrens struct btrfsic_block {
1325db02760SStefan Behrens 	u32 magic_num;		/* only used for debug purposes */
1335db02760SStefan Behrens 	unsigned int is_metadata:1;	/* if it is meta-data, not data-data */
1345db02760SStefan Behrens 	unsigned int is_superblock:1;	/* if it is one of the superblocks */
1355db02760SStefan Behrens 	unsigned int is_iodone:1;	/* if is done by lower subsystem */
1365db02760SStefan Behrens 	unsigned int iodone_w_error:1;	/* error was indicated to endio */
1375db02760SStefan Behrens 	unsigned int never_written:1;	/* block was added because it was
1385db02760SStefan Behrens 					 * referenced, not because it was
1395db02760SStefan Behrens 					 * written */
140cb3806ecSStefan Behrens 	unsigned int mirror_num;	/* large enough to hold
1415db02760SStefan Behrens 					 * BTRFS_SUPER_MIRROR_MAX */
1425db02760SStefan Behrens 	struct btrfsic_dev_state *dev_state;
1435db02760SStefan Behrens 	u64 dev_bytenr;		/* key, physical byte num on disk */
1445db02760SStefan Behrens 	u64 logical_bytenr;	/* logical byte num on disk */
1455db02760SStefan Behrens 	u64 generation;
1465db02760SStefan Behrens 	struct btrfs_disk_key disk_key;	/* extra info to print in case of
1475db02760SStefan Behrens 					 * issues, will not always be correct */
1485db02760SStefan Behrens 	struct list_head collision_resolving_node;	/* list node */
1495db02760SStefan Behrens 	struct list_head all_blocks_node;	/* list node */
1505db02760SStefan Behrens 
1515db02760SStefan Behrens 	/* the following two lists contain block_link items */
1525db02760SStefan Behrens 	struct list_head ref_to_list;	/* list */
1535db02760SStefan Behrens 	struct list_head ref_from_list;	/* list */
1545db02760SStefan Behrens 	struct btrfsic_block *next_in_same_bio;
15559aaad50SJohannes Thumshirn 	void *orig_bio_private;
15659aaad50SJohannes Thumshirn 	bio_end_io_t *orig_bio_end_io;
157bf9486d6SBart Van Assche 	blk_opf_t submit_bio_bh_rw;
1585db02760SStefan Behrens 	u64 flush_gen; /* only valid if !never_written */
1595db02760SStefan Behrens };
1605db02760SStefan Behrens 
1615db02760SStefan Behrens /*
1625db02760SStefan Behrens  * Elements of this type are allocated dynamically and required because
1635db02760SStefan Behrens  * each block object can refer to and can be ref from multiple blocks.
1645db02760SStefan Behrens  * The key to lookup them in the hashtable is the dev_bytenr of
165bb7ab3b9SAdam Buchbinder  * the block ref to plus the one from the block referred from.
1665db02760SStefan Behrens  * The fact that they are searchable via a hashtable and that a
1675db02760SStefan Behrens  * ref_cnt is maintained is not required for the btrfs integrity
1685db02760SStefan Behrens  * check algorithm itself, it is only used to make the output more
1695db02760SStefan Behrens  * beautiful in case that an error is detected (an error is defined
1705db02760SStefan Behrens  * as a write operation to a block while that block is still referenced).
1715db02760SStefan Behrens  */
1725db02760SStefan Behrens struct btrfsic_block_link {
1735db02760SStefan Behrens 	u32 magic_num;		/* only used for debug purposes */
1745db02760SStefan Behrens 	u32 ref_cnt;
1755db02760SStefan Behrens 	struct list_head node_ref_to;	/* list node */
1765db02760SStefan Behrens 	struct list_head node_ref_from;	/* list node */
1775db02760SStefan Behrens 	struct list_head collision_resolving_node;	/* list node */
1785db02760SStefan Behrens 	struct btrfsic_block *block_ref_to;
1795db02760SStefan Behrens 	struct btrfsic_block *block_ref_from;
1805db02760SStefan Behrens 	u64 parent_generation;
1815db02760SStefan Behrens };
1825db02760SStefan Behrens 
1835db02760SStefan Behrens struct btrfsic_dev_state {
1845db02760SStefan Behrens 	u32 magic_num;		/* only used for debug purposes */
1855db02760SStefan Behrens 	struct block_device *bdev;
1865db02760SStefan Behrens 	struct btrfsic_state *state;
1875db02760SStefan Behrens 	struct list_head collision_resolving_node;	/* list node */
1885db02760SStefan Behrens 	struct btrfsic_block dummy_block_for_bio_bh_flush;
1895db02760SStefan Behrens 	u64 last_flush_gen;
1905db02760SStefan Behrens };
1915db02760SStefan Behrens 
1925db02760SStefan Behrens struct btrfsic_block_hashtable {
1935db02760SStefan Behrens 	struct list_head table[BTRFSIC_BLOCK_HASHTABLE_SIZE];
1945db02760SStefan Behrens };
1955db02760SStefan Behrens 
1965db02760SStefan Behrens struct btrfsic_block_link_hashtable {
1975db02760SStefan Behrens 	struct list_head table[BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE];
1985db02760SStefan Behrens };
1995db02760SStefan Behrens 
2005db02760SStefan Behrens struct btrfsic_dev_state_hashtable {
2015db02760SStefan Behrens 	struct list_head table[BTRFSIC_DEV2STATE_HASHTABLE_SIZE];
2025db02760SStefan Behrens };
2035db02760SStefan Behrens 
2045db02760SStefan Behrens struct btrfsic_block_data_ctx {
2055db02760SStefan Behrens 	u64 start;		/* virtual bytenr */
2065db02760SStefan Behrens 	u64 dev_bytenr;		/* physical bytenr on device */
2075db02760SStefan Behrens 	u32 len;
2085db02760SStefan Behrens 	struct btrfsic_dev_state *dev;
209e06baab4SStefan Behrens 	char **datav;
210e06baab4SStefan Behrens 	struct page **pagev;
211e06baab4SStefan Behrens 	void *mem_to_free;
2125db02760SStefan Behrens };
2135db02760SStefan Behrens 
2145db02760SStefan Behrens /* This structure is used to implement recursion without occupying
2155db02760SStefan Behrens  * any stack space, refer to btrfsic_process_metablock() */
2165db02760SStefan Behrens struct btrfsic_stack_frame {
2175db02760SStefan Behrens 	u32 magic;
2185db02760SStefan Behrens 	u32 nr;
2195db02760SStefan Behrens 	int error;
2205db02760SStefan Behrens 	int i;
2215db02760SStefan Behrens 	int limit_nesting;
2225db02760SStefan Behrens 	int num_copies;
2235db02760SStefan Behrens 	int mirror_num;
2245db02760SStefan Behrens 	struct btrfsic_block *block;
2255db02760SStefan Behrens 	struct btrfsic_block_data_ctx *block_ctx;
2265db02760SStefan Behrens 	struct btrfsic_block *next_block;
2275db02760SStefan Behrens 	struct btrfsic_block_data_ctx next_block_ctx;
2285db02760SStefan Behrens 	struct btrfs_header *hdr;
2295db02760SStefan Behrens 	struct btrfsic_stack_frame *prev;
2305db02760SStefan Behrens };
2315db02760SStefan Behrens 
2325db02760SStefan Behrens /* Some state per mounted filesystem */
2335db02760SStefan Behrens struct btrfsic_state {
2345db02760SStefan Behrens 	u32 print_mask;
2355db02760SStefan Behrens 	int include_extent_data;
2365db02760SStefan Behrens 	struct list_head all_blocks_list;
2375db02760SStefan Behrens 	struct btrfsic_block_hashtable block_hashtable;
2385db02760SStefan Behrens 	struct btrfsic_block_link_hashtable block_link_hashtable;
239de143792SJeff Mahoney 	struct btrfs_fs_info *fs_info;
2405db02760SStefan Behrens 	u64 max_superblock_generation;
2415db02760SStefan Behrens 	struct btrfsic_block *latest_superblock;
242e06baab4SStefan Behrens 	u32 metablock_size;
243e06baab4SStefan Behrens 	u32 datablock_size;
2445db02760SStefan Behrens };
2455db02760SStefan Behrens 
2465db02760SStefan Behrens static int btrfsic_process_metablock(struct btrfsic_state *state,
2475db02760SStefan Behrens 				     struct btrfsic_block *block,
2485db02760SStefan Behrens 				     struct btrfsic_block_data_ctx *block_ctx,
2495db02760SStefan Behrens 				     int limit_nesting, int force_iodone_flag);
250e06baab4SStefan Behrens static void btrfsic_read_from_block_data(
251e06baab4SStefan Behrens 	struct btrfsic_block_data_ctx *block_ctx,
252e06baab4SStefan Behrens 	void *dst, u32 offset, size_t len);
2535db02760SStefan Behrens static int btrfsic_create_link_to_next_block(
2545db02760SStefan Behrens 		struct btrfsic_state *state,
2555db02760SStefan Behrens 		struct btrfsic_block *block,
2565db02760SStefan Behrens 		struct btrfsic_block_data_ctx
2575db02760SStefan Behrens 		*block_ctx, u64 next_bytenr,
2585db02760SStefan Behrens 		int limit_nesting,
2595db02760SStefan Behrens 		struct btrfsic_block_data_ctx *next_block_ctx,
2605db02760SStefan Behrens 		struct btrfsic_block **next_blockp,
2615db02760SStefan Behrens 		int force_iodone_flag,
2625db02760SStefan Behrens 		int *num_copiesp, int *mirror_nump,
2635db02760SStefan Behrens 		struct btrfs_disk_key *disk_key,
2645db02760SStefan Behrens 		u64 parent_generation);
2655db02760SStefan Behrens static int btrfsic_handle_extent_data(struct btrfsic_state *state,
2665db02760SStefan Behrens 				      struct btrfsic_block *block,
2675db02760SStefan Behrens 				      struct btrfsic_block_data_ctx *block_ctx,
2685db02760SStefan Behrens 				      u32 item_offset, int force_iodone_flag);
2695db02760SStefan Behrens static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
2705db02760SStefan Behrens 			     struct btrfsic_block_data_ctx *block_ctx_out,
2715db02760SStefan Behrens 			     int mirror_num);
2725db02760SStefan Behrens static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx);
2735db02760SStefan Behrens static int btrfsic_read_block(struct btrfsic_state *state,
2745db02760SStefan Behrens 			      struct btrfsic_block_data_ctx *block_ctx);
2755db02760SStefan Behrens static int btrfsic_process_written_superblock(
2765db02760SStefan Behrens 		struct btrfsic_state *state,
2775db02760SStefan Behrens 		struct btrfsic_block *const block,
2785db02760SStefan Behrens 		struct btrfs_super_block *const super_hdr);
2794246a0b6SChristoph Hellwig static void btrfsic_bio_end_io(struct bio *bp);
2805db02760SStefan Behrens static int btrfsic_is_block_ref_by_superblock(const struct btrfsic_state *state,
2815db02760SStefan Behrens 					      const struct btrfsic_block *block,
2825db02760SStefan Behrens 					      int recursion_level);
2835db02760SStefan Behrens static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
2845db02760SStefan Behrens 					struct btrfsic_block *const block,
2855db02760SStefan Behrens 					int recursion_level);
2865db02760SStefan Behrens static void btrfsic_print_add_link(const struct btrfsic_state *state,
2875db02760SStefan Behrens 				   const struct btrfsic_block_link *l);
2885db02760SStefan Behrens static void btrfsic_print_rem_link(const struct btrfsic_state *state,
2895db02760SStefan Behrens 				   const struct btrfsic_block_link *l);
2905db02760SStefan Behrens static char btrfsic_get_block_type(const struct btrfsic_state *state,
2915db02760SStefan Behrens 				   const struct btrfsic_block *block);
2925db02760SStefan Behrens static void btrfsic_dump_tree(const struct btrfsic_state *state);
2935db02760SStefan Behrens static void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
2945db02760SStefan Behrens 				  const struct btrfsic_block *block,
2955db02760SStefan Behrens 				  int indent_level);
2965db02760SStefan Behrens static struct btrfsic_block_link *btrfsic_block_link_lookup_or_add(
2975db02760SStefan Behrens 		struct btrfsic_state *state,
2985db02760SStefan Behrens 		struct btrfsic_block_data_ctx *next_block_ctx,
2995db02760SStefan Behrens 		struct btrfsic_block *next_block,
3005db02760SStefan Behrens 		struct btrfsic_block *from_block,
3015db02760SStefan Behrens 		u64 parent_generation);
3025db02760SStefan Behrens static struct btrfsic_block *btrfsic_block_lookup_or_add(
3035db02760SStefan Behrens 		struct btrfsic_state *state,
3045db02760SStefan Behrens 		struct btrfsic_block_data_ctx *block_ctx,
3055db02760SStefan Behrens 		const char *additional_string,
3065db02760SStefan Behrens 		int is_metadata,
3075db02760SStefan Behrens 		int is_iodone,
3085db02760SStefan Behrens 		int never_written,
3095db02760SStefan Behrens 		int mirror_num,
3105db02760SStefan Behrens 		int *was_created);
3115db02760SStefan Behrens static int btrfsic_process_superblock_dev_mirror(
3125db02760SStefan Behrens 		struct btrfsic_state *state,
3135db02760SStefan Behrens 		struct btrfsic_dev_state *dev_state,
3145db02760SStefan Behrens 		struct btrfs_device *device,
3155db02760SStefan Behrens 		int superblock_mirror_num,
3165db02760SStefan Behrens 		struct btrfsic_dev_state **selected_dev_state,
3175db02760SStefan Behrens 		struct btrfs_super_block *selected_super);
318f8f84b2dSChristoph Hellwig static struct btrfsic_dev_state *btrfsic_dev_state_lookup(dev_t dev);
3195db02760SStefan Behrens static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
3205db02760SStefan Behrens 					   u64 bytenr,
3215db02760SStefan Behrens 					   struct btrfsic_dev_state *dev_state,
322e06baab4SStefan Behrens 					   u64 dev_bytenr);
3235db02760SStefan Behrens 
3245db02760SStefan Behrens static struct mutex btrfsic_mutex;
3255db02760SStefan Behrens static int btrfsic_is_initialized;
3265db02760SStefan Behrens static struct btrfsic_dev_state_hashtable btrfsic_dev_state_hashtable;
3275db02760SStefan Behrens 
3285db02760SStefan Behrens 
btrfsic_block_init(struct btrfsic_block * b)3295db02760SStefan Behrens static void btrfsic_block_init(struct btrfsic_block *b)
3305db02760SStefan Behrens {
3315db02760SStefan Behrens 	b->magic_num = BTRFSIC_BLOCK_MAGIC_NUMBER;
3325db02760SStefan Behrens 	b->dev_state = NULL;
3335db02760SStefan Behrens 	b->dev_bytenr = 0;
3345db02760SStefan Behrens 	b->logical_bytenr = 0;
3355db02760SStefan Behrens 	b->generation = BTRFSIC_GENERATION_UNKNOWN;
3365db02760SStefan Behrens 	b->disk_key.objectid = 0;
3375db02760SStefan Behrens 	b->disk_key.type = 0;
3385db02760SStefan Behrens 	b->disk_key.offset = 0;
3395db02760SStefan Behrens 	b->is_metadata = 0;
3405db02760SStefan Behrens 	b->is_superblock = 0;
3415db02760SStefan Behrens 	b->is_iodone = 0;
3425db02760SStefan Behrens 	b->iodone_w_error = 0;
3435db02760SStefan Behrens 	b->never_written = 0;
3445db02760SStefan Behrens 	b->mirror_num = 0;
3455db02760SStefan Behrens 	b->next_in_same_bio = NULL;
34659aaad50SJohannes Thumshirn 	b->orig_bio_private = NULL;
34759aaad50SJohannes Thumshirn 	b->orig_bio_end_io = NULL;
3485db02760SStefan Behrens 	INIT_LIST_HEAD(&b->collision_resolving_node);
3495db02760SStefan Behrens 	INIT_LIST_HEAD(&b->all_blocks_node);
3505db02760SStefan Behrens 	INIT_LIST_HEAD(&b->ref_to_list);
3515db02760SStefan Behrens 	INIT_LIST_HEAD(&b->ref_from_list);
3525db02760SStefan Behrens 	b->submit_bio_bh_rw = 0;
3535db02760SStefan Behrens 	b->flush_gen = 0;
3545db02760SStefan Behrens }
3555db02760SStefan Behrens 
btrfsic_block_alloc(void)3565db02760SStefan Behrens static struct btrfsic_block *btrfsic_block_alloc(void)
3575db02760SStefan Behrens {
3585db02760SStefan Behrens 	struct btrfsic_block *b;
3595db02760SStefan Behrens 
3605db02760SStefan Behrens 	b = kzalloc(sizeof(*b), GFP_NOFS);
3615db02760SStefan Behrens 	if (NULL != b)
3625db02760SStefan Behrens 		btrfsic_block_init(b);
3635db02760SStefan Behrens 
3645db02760SStefan Behrens 	return b;
3655db02760SStefan Behrens }
3665db02760SStefan Behrens 
btrfsic_block_free(struct btrfsic_block * b)3675db02760SStefan Behrens static void btrfsic_block_free(struct btrfsic_block *b)
3685db02760SStefan Behrens {
3695db02760SStefan Behrens 	BUG_ON(!(NULL == b || BTRFSIC_BLOCK_MAGIC_NUMBER == b->magic_num));
3705db02760SStefan Behrens 	kfree(b);
3715db02760SStefan Behrens }
3725db02760SStefan Behrens 
btrfsic_block_link_init(struct btrfsic_block_link * l)3735db02760SStefan Behrens static void btrfsic_block_link_init(struct btrfsic_block_link *l)
3745db02760SStefan Behrens {
3755db02760SStefan Behrens 	l->magic_num = BTRFSIC_BLOCK_LINK_MAGIC_NUMBER;
3765db02760SStefan Behrens 	l->ref_cnt = 1;
3775db02760SStefan Behrens 	INIT_LIST_HEAD(&l->node_ref_to);
3785db02760SStefan Behrens 	INIT_LIST_HEAD(&l->node_ref_from);
3795db02760SStefan Behrens 	INIT_LIST_HEAD(&l->collision_resolving_node);
3805db02760SStefan Behrens 	l->block_ref_to = NULL;
3815db02760SStefan Behrens 	l->block_ref_from = NULL;
3825db02760SStefan Behrens }
3835db02760SStefan Behrens 
btrfsic_block_link_alloc(void)3845db02760SStefan Behrens static struct btrfsic_block_link *btrfsic_block_link_alloc(void)
3855db02760SStefan Behrens {
3865db02760SStefan Behrens 	struct btrfsic_block_link *l;
3875db02760SStefan Behrens 
3885db02760SStefan Behrens 	l = kzalloc(sizeof(*l), GFP_NOFS);
3895db02760SStefan Behrens 	if (NULL != l)
3905db02760SStefan Behrens 		btrfsic_block_link_init(l);
3915db02760SStefan Behrens 
3925db02760SStefan Behrens 	return l;
3935db02760SStefan Behrens }
3945db02760SStefan Behrens 
btrfsic_block_link_free(struct btrfsic_block_link * l)3955db02760SStefan Behrens static void btrfsic_block_link_free(struct btrfsic_block_link *l)
3965db02760SStefan Behrens {
3975db02760SStefan Behrens 	BUG_ON(!(NULL == l || BTRFSIC_BLOCK_LINK_MAGIC_NUMBER == l->magic_num));
3985db02760SStefan Behrens 	kfree(l);
3995db02760SStefan Behrens }
4005db02760SStefan Behrens 
btrfsic_dev_state_init(struct btrfsic_dev_state * ds)4015db02760SStefan Behrens static void btrfsic_dev_state_init(struct btrfsic_dev_state *ds)
4025db02760SStefan Behrens {
4035db02760SStefan Behrens 	ds->magic_num = BTRFSIC_DEV2STATE_MAGIC_NUMBER;
4045db02760SStefan Behrens 	ds->bdev = NULL;
4055db02760SStefan Behrens 	ds->state = NULL;
4065db02760SStefan Behrens 	INIT_LIST_HEAD(&ds->collision_resolving_node);
4075db02760SStefan Behrens 	ds->last_flush_gen = 0;
4085db02760SStefan Behrens 	btrfsic_block_init(&ds->dummy_block_for_bio_bh_flush);
4095db02760SStefan Behrens 	ds->dummy_block_for_bio_bh_flush.is_iodone = 1;
4105db02760SStefan Behrens 	ds->dummy_block_for_bio_bh_flush.dev_state = ds;
4115db02760SStefan Behrens }
4125db02760SStefan Behrens 
btrfsic_dev_state_alloc(void)4135db02760SStefan Behrens static struct btrfsic_dev_state *btrfsic_dev_state_alloc(void)
4145db02760SStefan Behrens {
4155db02760SStefan Behrens 	struct btrfsic_dev_state *ds;
4165db02760SStefan Behrens 
4175db02760SStefan Behrens 	ds = kzalloc(sizeof(*ds), GFP_NOFS);
4185db02760SStefan Behrens 	if (NULL != ds)
4195db02760SStefan Behrens 		btrfsic_dev_state_init(ds);
4205db02760SStefan Behrens 
4215db02760SStefan Behrens 	return ds;
4225db02760SStefan Behrens }
4235db02760SStefan Behrens 
btrfsic_dev_state_free(struct btrfsic_dev_state * ds)4245db02760SStefan Behrens static void btrfsic_dev_state_free(struct btrfsic_dev_state *ds)
4255db02760SStefan Behrens {
4265db02760SStefan Behrens 	BUG_ON(!(NULL == ds ||
4275db02760SStefan Behrens 		 BTRFSIC_DEV2STATE_MAGIC_NUMBER == ds->magic_num));
4285db02760SStefan Behrens 	kfree(ds);
4295db02760SStefan Behrens }
4305db02760SStefan Behrens 
btrfsic_block_hashtable_init(struct btrfsic_block_hashtable * h)4315db02760SStefan Behrens static void btrfsic_block_hashtable_init(struct btrfsic_block_hashtable *h)
4325db02760SStefan Behrens {
4335db02760SStefan Behrens 	int i;
4345db02760SStefan Behrens 
4355db02760SStefan Behrens 	for (i = 0; i < BTRFSIC_BLOCK_HASHTABLE_SIZE; i++)
4365db02760SStefan Behrens 		INIT_LIST_HEAD(h->table + i);
4375db02760SStefan Behrens }
4385db02760SStefan Behrens 
btrfsic_block_hashtable_add(struct btrfsic_block * b,struct btrfsic_block_hashtable * h)4395db02760SStefan Behrens static void btrfsic_block_hashtable_add(struct btrfsic_block *b,
4405db02760SStefan Behrens 					struct btrfsic_block_hashtable *h)
4415db02760SStefan Behrens {
4425db02760SStefan Behrens 	const unsigned int hashval =
4435db02760SStefan Behrens 	    (((unsigned int)(b->dev_bytenr >> 16)) ^
4445db02760SStefan Behrens 	     ((unsigned int)((uintptr_t)b->dev_state->bdev))) &
4455db02760SStefan Behrens 	     (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1);
4465db02760SStefan Behrens 
4475db02760SStefan Behrens 	list_add(&b->collision_resolving_node, h->table + hashval);
4485db02760SStefan Behrens }
4495db02760SStefan Behrens 
btrfsic_block_hashtable_remove(struct btrfsic_block * b)4505db02760SStefan Behrens static void btrfsic_block_hashtable_remove(struct btrfsic_block *b)
4515db02760SStefan Behrens {
4525db02760SStefan Behrens 	list_del(&b->collision_resolving_node);
4535db02760SStefan Behrens }
4545db02760SStefan Behrens 
btrfsic_block_hashtable_lookup(struct block_device * bdev,u64 dev_bytenr,struct btrfsic_block_hashtable * h)4555db02760SStefan Behrens static struct btrfsic_block *btrfsic_block_hashtable_lookup(
4565db02760SStefan Behrens 		struct block_device *bdev,
4575db02760SStefan Behrens 		u64 dev_bytenr,
4585db02760SStefan Behrens 		struct btrfsic_block_hashtable *h)
4595db02760SStefan Behrens {
4605db02760SStefan Behrens 	const unsigned int hashval =
4615db02760SStefan Behrens 	    (((unsigned int)(dev_bytenr >> 16)) ^
4625db02760SStefan Behrens 	     ((unsigned int)((uintptr_t)bdev))) &
4635db02760SStefan Behrens 	     (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1);
464b69f2befSGeliang Tang 	struct btrfsic_block *b;
4655db02760SStefan Behrens 
466b69f2befSGeliang Tang 	list_for_each_entry(b, h->table + hashval, collision_resolving_node) {
4675db02760SStefan Behrens 		if (b->dev_state->bdev == bdev && b->dev_bytenr == dev_bytenr)
4685db02760SStefan Behrens 			return b;
4695db02760SStefan Behrens 	}
4705db02760SStefan Behrens 
4715db02760SStefan Behrens 	return NULL;
4725db02760SStefan Behrens }
4735db02760SStefan Behrens 
btrfsic_block_link_hashtable_init(struct btrfsic_block_link_hashtable * h)4745db02760SStefan Behrens static void btrfsic_block_link_hashtable_init(
4755db02760SStefan Behrens 		struct btrfsic_block_link_hashtable *h)
4765db02760SStefan Behrens {
4775db02760SStefan Behrens 	int i;
4785db02760SStefan Behrens 
4795db02760SStefan Behrens 	for (i = 0; i < BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE; i++)
4805db02760SStefan Behrens 		INIT_LIST_HEAD(h->table + i);
4815db02760SStefan Behrens }
4825db02760SStefan Behrens 
btrfsic_block_link_hashtable_add(struct btrfsic_block_link * l,struct btrfsic_block_link_hashtable * h)4835db02760SStefan Behrens static void btrfsic_block_link_hashtable_add(
4845db02760SStefan Behrens 		struct btrfsic_block_link *l,
4855db02760SStefan Behrens 		struct btrfsic_block_link_hashtable *h)
4865db02760SStefan Behrens {
4875db02760SStefan Behrens 	const unsigned int hashval =
4885db02760SStefan Behrens 	    (((unsigned int)(l->block_ref_to->dev_bytenr >> 16)) ^
4895db02760SStefan Behrens 	     ((unsigned int)(l->block_ref_from->dev_bytenr >> 16)) ^
4905db02760SStefan Behrens 	     ((unsigned int)((uintptr_t)l->block_ref_to->dev_state->bdev)) ^
4915db02760SStefan Behrens 	     ((unsigned int)((uintptr_t)l->block_ref_from->dev_state->bdev)))
4925db02760SStefan Behrens 	     & (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1);
4935db02760SStefan Behrens 
4945db02760SStefan Behrens 	BUG_ON(NULL == l->block_ref_to);
4955db02760SStefan Behrens 	BUG_ON(NULL == l->block_ref_from);
4965db02760SStefan Behrens 	list_add(&l->collision_resolving_node, h->table + hashval);
4975db02760SStefan Behrens }
4985db02760SStefan Behrens 
btrfsic_block_link_hashtable_remove(struct btrfsic_block_link * l)4995db02760SStefan Behrens static void btrfsic_block_link_hashtable_remove(struct btrfsic_block_link *l)
5005db02760SStefan Behrens {
5015db02760SStefan Behrens 	list_del(&l->collision_resolving_node);
5025db02760SStefan Behrens }
5035db02760SStefan Behrens 
btrfsic_block_link_hashtable_lookup(struct block_device * bdev_ref_to,u64 dev_bytenr_ref_to,struct block_device * bdev_ref_from,u64 dev_bytenr_ref_from,struct btrfsic_block_link_hashtable * h)5045db02760SStefan Behrens static struct btrfsic_block_link *btrfsic_block_link_hashtable_lookup(
5055db02760SStefan Behrens 		struct block_device *bdev_ref_to,
5065db02760SStefan Behrens 		u64 dev_bytenr_ref_to,
5075db02760SStefan Behrens 		struct block_device *bdev_ref_from,
5085db02760SStefan Behrens 		u64 dev_bytenr_ref_from,
5095db02760SStefan Behrens 		struct btrfsic_block_link_hashtable *h)
5105db02760SStefan Behrens {
5115db02760SStefan Behrens 	const unsigned int hashval =
5125db02760SStefan Behrens 	    (((unsigned int)(dev_bytenr_ref_to >> 16)) ^
5135db02760SStefan Behrens 	     ((unsigned int)(dev_bytenr_ref_from >> 16)) ^
5145db02760SStefan Behrens 	     ((unsigned int)((uintptr_t)bdev_ref_to)) ^
5155db02760SStefan Behrens 	     ((unsigned int)((uintptr_t)bdev_ref_from))) &
5165db02760SStefan Behrens 	     (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1);
517b69f2befSGeliang Tang 	struct btrfsic_block_link *l;
5185db02760SStefan Behrens 
519b69f2befSGeliang Tang 	list_for_each_entry(l, h->table + hashval, collision_resolving_node) {
5205db02760SStefan Behrens 		BUG_ON(NULL == l->block_ref_to);
5215db02760SStefan Behrens 		BUG_ON(NULL == l->block_ref_from);
5225db02760SStefan Behrens 		if (l->block_ref_to->dev_state->bdev == bdev_ref_to &&
5235db02760SStefan Behrens 		    l->block_ref_to->dev_bytenr == dev_bytenr_ref_to &&
5245db02760SStefan Behrens 		    l->block_ref_from->dev_state->bdev == bdev_ref_from &&
5255db02760SStefan Behrens 		    l->block_ref_from->dev_bytenr == dev_bytenr_ref_from)
5265db02760SStefan Behrens 			return l;
5275db02760SStefan Behrens 	}
5285db02760SStefan Behrens 
5295db02760SStefan Behrens 	return NULL;
5305db02760SStefan Behrens }
5315db02760SStefan Behrens 
btrfsic_dev_state_hashtable_init(struct btrfsic_dev_state_hashtable * h)5325db02760SStefan Behrens static void btrfsic_dev_state_hashtable_init(
5335db02760SStefan Behrens 		struct btrfsic_dev_state_hashtable *h)
5345db02760SStefan Behrens {
5355db02760SStefan Behrens 	int i;
5365db02760SStefan Behrens 
5375db02760SStefan Behrens 	for (i = 0; i < BTRFSIC_DEV2STATE_HASHTABLE_SIZE; i++)
5385db02760SStefan Behrens 		INIT_LIST_HEAD(h->table + i);
5395db02760SStefan Behrens }
5405db02760SStefan Behrens 
btrfsic_dev_state_hashtable_add(struct btrfsic_dev_state * ds,struct btrfsic_dev_state_hashtable * h)5415db02760SStefan Behrens static void btrfsic_dev_state_hashtable_add(
5425db02760SStefan Behrens 		struct btrfsic_dev_state *ds,
5435db02760SStefan Behrens 		struct btrfsic_dev_state_hashtable *h)
5445db02760SStefan Behrens {
5455db02760SStefan Behrens 	const unsigned int hashval =
546859a58a2SGu JinXiang 	    (((unsigned int)((uintptr_t)ds->bdev->bd_dev)) &
5475db02760SStefan Behrens 	     (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1));
5485db02760SStefan Behrens 
5495db02760SStefan Behrens 	list_add(&ds->collision_resolving_node, h->table + hashval);
5505db02760SStefan Behrens }
5515db02760SStefan Behrens 
btrfsic_dev_state_hashtable_remove(struct btrfsic_dev_state * ds)5525db02760SStefan Behrens static void btrfsic_dev_state_hashtable_remove(struct btrfsic_dev_state *ds)
5535db02760SStefan Behrens {
5545db02760SStefan Behrens 	list_del(&ds->collision_resolving_node);
5555db02760SStefan Behrens }
5565db02760SStefan Behrens 
btrfsic_dev_state_hashtable_lookup(dev_t dev,struct btrfsic_dev_state_hashtable * h)557f8f84b2dSChristoph Hellwig static struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(dev_t dev,
5585db02760SStefan Behrens 		struct btrfsic_dev_state_hashtable *h)
5595db02760SStefan Behrens {
5605db02760SStefan Behrens 	const unsigned int hashval =
561f8f84b2dSChristoph Hellwig 		dev & (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1);
562b69f2befSGeliang Tang 	struct btrfsic_dev_state *ds;
5635db02760SStefan Behrens 
564b69f2befSGeliang Tang 	list_for_each_entry(ds, h->table + hashval, collision_resolving_node) {
565f8f84b2dSChristoph Hellwig 		if (ds->bdev->bd_dev == dev)
5665db02760SStefan Behrens 			return ds;
5675db02760SStefan Behrens 	}
5685db02760SStefan Behrens 
5695db02760SStefan Behrens 	return NULL;
5705db02760SStefan Behrens }
5715db02760SStefan Behrens 
btrfsic_process_superblock(struct btrfsic_state * state,struct btrfs_fs_devices * fs_devices)5725db02760SStefan Behrens static int btrfsic_process_superblock(struct btrfsic_state *state,
5735db02760SStefan Behrens 				      struct btrfs_fs_devices *fs_devices)
5745db02760SStefan Behrens {
5755db02760SStefan Behrens 	struct btrfs_super_block *selected_super;
5765db02760SStefan Behrens 	struct list_head *dev_head = &fs_devices->devices;
5775db02760SStefan Behrens 	struct btrfs_device *device;
5785db02760SStefan Behrens 	struct btrfsic_dev_state *selected_dev_state = NULL;
5790b246afaSJeff Mahoney 	int ret = 0;
5805db02760SStefan Behrens 	int pass;
5815db02760SStefan Behrens 
582e06baab4SStefan Behrens 	selected_super = kzalloc(sizeof(*selected_super), GFP_NOFS);
583ab483009SLiao Pingfang 	if (!selected_super)
5840b8d8ce0SLuis de Bethencourt 		return -ENOMEM;
5855db02760SStefan Behrens 
5865db02760SStefan Behrens 	list_for_each_entry(device, dev_head, dev_list) {
5875db02760SStefan Behrens 		int i;
5885db02760SStefan Behrens 		struct btrfsic_dev_state *dev_state;
5895db02760SStefan Behrens 
5905db02760SStefan Behrens 		if (!device->bdev || !device->name)
5915db02760SStefan Behrens 			continue;
5925db02760SStefan Behrens 
593f8f84b2dSChristoph Hellwig 		dev_state = btrfsic_dev_state_lookup(device->bdev->bd_dev);
5945db02760SStefan Behrens 		BUG_ON(NULL == dev_state);
5955db02760SStefan Behrens 		for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
5965db02760SStefan Behrens 			ret = btrfsic_process_superblock_dev_mirror(
5975db02760SStefan Behrens 					state, dev_state, device, i,
5985db02760SStefan Behrens 					&selected_dev_state, selected_super);
5995db02760SStefan Behrens 			if (0 != ret && 0 == i) {
6005db02760SStefan Behrens 				kfree(selected_super);
6015db02760SStefan Behrens 				return ret;
6025db02760SStefan Behrens 			}
6035db02760SStefan Behrens 		}
6045db02760SStefan Behrens 	}
6055db02760SStefan Behrens 
6065db02760SStefan Behrens 	if (NULL == state->latest_superblock) {
60762e85577SJeff Mahoney 		pr_info("btrfsic: no superblock found!\n");
6085db02760SStefan Behrens 		kfree(selected_super);
6095db02760SStefan Behrens 		return -1;
6105db02760SStefan Behrens 	}
6115db02760SStefan Behrens 
6125db02760SStefan Behrens 	for (pass = 0; pass < 3; pass++) {
6135db02760SStefan Behrens 		int num_copies;
6145db02760SStefan Behrens 		int mirror_num;
6155db02760SStefan Behrens 		u64 next_bytenr;
6165db02760SStefan Behrens 
6175db02760SStefan Behrens 		switch (pass) {
6185db02760SStefan Behrens 		case 0:
6195db02760SStefan Behrens 			next_bytenr = btrfs_super_root(selected_super);
6205db02760SStefan Behrens 			if (state->print_mask &
6215db02760SStefan Behrens 			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
62262e85577SJeff Mahoney 				pr_info("root@%llu\n", next_bytenr);
6235db02760SStefan Behrens 			break;
6245db02760SStefan Behrens 		case 1:
6255db02760SStefan Behrens 			next_bytenr = btrfs_super_chunk_root(selected_super);
6265db02760SStefan Behrens 			if (state->print_mask &
6275db02760SStefan Behrens 			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
62862e85577SJeff Mahoney 				pr_info("chunk@%llu\n", next_bytenr);
6295db02760SStefan Behrens 			break;
6305db02760SStefan Behrens 		case 2:
6315db02760SStefan Behrens 			next_bytenr = btrfs_super_log_root(selected_super);
6325db02760SStefan Behrens 			if (0 == next_bytenr)
6335db02760SStefan Behrens 				continue;
6345db02760SStefan Behrens 			if (state->print_mask &
6355db02760SStefan Behrens 			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
63662e85577SJeff Mahoney 				pr_info("log@%llu\n", next_bytenr);
6375db02760SStefan Behrens 			break;
6385db02760SStefan Behrens 		}
6395db02760SStefan Behrens 
6403dbd351dSJohannes Thumshirn 		num_copies = btrfs_num_copies(state->fs_info, next_bytenr,
6410b246afaSJeff Mahoney 					      state->metablock_size);
6425db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
64362e85577SJeff Mahoney 			pr_info("num_copies(log_bytenr=%llu) = %d\n",
644c1c9ff7cSGeert Uytterhoeven 			       next_bytenr, num_copies);
6455db02760SStefan Behrens 
6465db02760SStefan Behrens 		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
6475db02760SStefan Behrens 			struct btrfsic_block *next_block;
6485db02760SStefan Behrens 			struct btrfsic_block_data_ctx tmp_next_block_ctx;
6495db02760SStefan Behrens 			struct btrfsic_block_link *l;
6505db02760SStefan Behrens 
651e06baab4SStefan Behrens 			ret = btrfsic_map_block(state, next_bytenr,
652e06baab4SStefan Behrens 						state->metablock_size,
6535db02760SStefan Behrens 						&tmp_next_block_ctx,
6545db02760SStefan Behrens 						mirror_num);
6555db02760SStefan Behrens 			if (ret) {
65662e85577SJeff Mahoney 				pr_info("btrfsic: btrfsic_map_block(root @%llu, mirror %d) failed!\n",
657c1c9ff7cSGeert Uytterhoeven 				       next_bytenr, mirror_num);
6585db02760SStefan Behrens 				kfree(selected_super);
6595db02760SStefan Behrens 				return -1;
6605db02760SStefan Behrens 			}
6615db02760SStefan Behrens 
6625db02760SStefan Behrens 			next_block = btrfsic_block_hashtable_lookup(
6635db02760SStefan Behrens 					tmp_next_block_ctx.dev->bdev,
6645db02760SStefan Behrens 					tmp_next_block_ctx.dev_bytenr,
6655db02760SStefan Behrens 					&state->block_hashtable);
6665db02760SStefan Behrens 			BUG_ON(NULL == next_block);
6675db02760SStefan Behrens 
6685db02760SStefan Behrens 			l = btrfsic_block_link_hashtable_lookup(
6695db02760SStefan Behrens 					tmp_next_block_ctx.dev->bdev,
6705db02760SStefan Behrens 					tmp_next_block_ctx.dev_bytenr,
6715db02760SStefan Behrens 					state->latest_superblock->dev_state->
6725db02760SStefan Behrens 					bdev,
6735db02760SStefan Behrens 					state->latest_superblock->dev_bytenr,
6745db02760SStefan Behrens 					&state->block_link_hashtable);
6755db02760SStefan Behrens 			BUG_ON(NULL == l);
6765db02760SStefan Behrens 
6775db02760SStefan Behrens 			ret = btrfsic_read_block(state, &tmp_next_block_ctx);
67809cbfeafSKirill A. Shutemov 			if (ret < (int)PAGE_SIZE) {
67962e85577SJeff Mahoney 				pr_info("btrfsic: read @logical %llu failed!\n",
6805db02760SStefan Behrens 				       tmp_next_block_ctx.start);
6815db02760SStefan Behrens 				btrfsic_release_block_ctx(&tmp_next_block_ctx);
6825db02760SStefan Behrens 				kfree(selected_super);
6835db02760SStefan Behrens 				return -1;
6845db02760SStefan Behrens 			}
6855db02760SStefan Behrens 
6865db02760SStefan Behrens 			ret = btrfsic_process_metablock(state,
6875db02760SStefan Behrens 							next_block,
6885db02760SStefan Behrens 							&tmp_next_block_ctx,
6895db02760SStefan Behrens 							BTRFS_MAX_LEVEL + 3, 1);
6905db02760SStefan Behrens 			btrfsic_release_block_ctx(&tmp_next_block_ctx);
6915db02760SStefan Behrens 		}
6925db02760SStefan Behrens 	}
6935db02760SStefan Behrens 
6945db02760SStefan Behrens 	kfree(selected_super);
6955db02760SStefan Behrens 	return ret;
6965db02760SStefan Behrens }
6975db02760SStefan Behrens 
btrfsic_process_superblock_dev_mirror(struct btrfsic_state * state,struct btrfsic_dev_state * dev_state,struct btrfs_device * device,int superblock_mirror_num,struct btrfsic_dev_state ** selected_dev_state,struct btrfs_super_block * selected_super)6985db02760SStefan Behrens static int btrfsic_process_superblock_dev_mirror(
6995db02760SStefan Behrens 		struct btrfsic_state *state,
7005db02760SStefan Behrens 		struct btrfsic_dev_state *dev_state,
7015db02760SStefan Behrens 		struct btrfs_device *device,
7025db02760SStefan Behrens 		int superblock_mirror_num,
7035db02760SStefan Behrens 		struct btrfsic_dev_state **selected_dev_state,
7045db02760SStefan Behrens 		struct btrfs_super_block *selected_super)
7055db02760SStefan Behrens {
7060b246afaSJeff Mahoney 	struct btrfs_fs_info *fs_info = state->fs_info;
7075db02760SStefan Behrens 	struct btrfs_super_block *super_tmp;
7085db02760SStefan Behrens 	u64 dev_bytenr;
7095db02760SStefan Behrens 	struct btrfsic_block *superblock_tmp;
7105db02760SStefan Behrens 	int pass;
7115db02760SStefan Behrens 	struct block_device *const superblock_bdev = device->bdev;
7129da2b242SJohannes Thumshirn 	struct page *page;
7139da2b242SJohannes Thumshirn 	struct address_space *mapping = superblock_bdev->bd_inode->i_mapping;
7149da2b242SJohannes Thumshirn 	int ret = 0;
7155db02760SStefan Behrens 
7165db02760SStefan Behrens 	/* super block bytenr is always the unmapped device bytenr */
7175db02760SStefan Behrens 	dev_bytenr = btrfs_sb_offset(superblock_mirror_num);
718935e5cc9SMiao Xie 	if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes)
719e06baab4SStefan Behrens 		return -1;
7209da2b242SJohannes Thumshirn 
7219da2b242SJohannes Thumshirn 	page = read_cache_page_gfp(mapping, dev_bytenr >> PAGE_SHIFT, GFP_NOFS);
7229da2b242SJohannes Thumshirn 	if (IS_ERR(page))
7235db02760SStefan Behrens 		return -1;
7249da2b242SJohannes Thumshirn 
7259da2b242SJohannes Thumshirn 	super_tmp = page_address(page);
7265db02760SStefan Behrens 
7275db02760SStefan Behrens 	if (btrfs_super_bytenr(super_tmp) != dev_bytenr ||
7283cae210fSQu Wenruo 	    btrfs_super_magic(super_tmp) != BTRFS_MAGIC ||
729e06baab4SStefan Behrens 	    memcmp(device->uuid, super_tmp->dev_item.uuid, BTRFS_UUID_SIZE) ||
730e06baab4SStefan Behrens 	    btrfs_super_nodesize(super_tmp) != state->metablock_size ||
731e06baab4SStefan Behrens 	    btrfs_super_sectorsize(super_tmp) != state->datablock_size) {
7329da2b242SJohannes Thumshirn 		ret = 0;
7339da2b242SJohannes Thumshirn 		goto out;
7345db02760SStefan Behrens 	}
7355db02760SStefan Behrens 
7365db02760SStefan Behrens 	superblock_tmp =
7375db02760SStefan Behrens 	    btrfsic_block_hashtable_lookup(superblock_bdev,
7385db02760SStefan Behrens 					   dev_bytenr,
7395db02760SStefan Behrens 					   &state->block_hashtable);
7405db02760SStefan Behrens 	if (NULL == superblock_tmp) {
7415db02760SStefan Behrens 		superblock_tmp = btrfsic_block_alloc();
7425db02760SStefan Behrens 		if (NULL == superblock_tmp) {
7439da2b242SJohannes Thumshirn 			ret = -1;
7449da2b242SJohannes Thumshirn 			goto out;
7455db02760SStefan Behrens 		}
7465db02760SStefan Behrens 		/* for superblock, only the dev_bytenr makes sense */
7475db02760SStefan Behrens 		superblock_tmp->dev_bytenr = dev_bytenr;
7485db02760SStefan Behrens 		superblock_tmp->dev_state = dev_state;
7495db02760SStefan Behrens 		superblock_tmp->logical_bytenr = dev_bytenr;
7505db02760SStefan Behrens 		superblock_tmp->generation = btrfs_super_generation(super_tmp);
7515db02760SStefan Behrens 		superblock_tmp->is_metadata = 1;
7525db02760SStefan Behrens 		superblock_tmp->is_superblock = 1;
7535db02760SStefan Behrens 		superblock_tmp->is_iodone = 1;
7545db02760SStefan Behrens 		superblock_tmp->never_written = 0;
7555db02760SStefan Behrens 		superblock_tmp->mirror_num = 1 + superblock_mirror_num;
7565db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
7570b246afaSJeff Mahoney 			btrfs_info_in_rcu(fs_info,
758813ebc16SChristoph Hellwig 			"new initial S-block (bdev %p, %s) @%llu (%pg/%llu/%d)",
759606686eeSJosef Bacik 				     superblock_bdev,
760cb3e217bSQu Wenruo 				     btrfs_dev_name(device), dev_bytenr,
761813ebc16SChristoph Hellwig 				     dev_state->bdev, dev_bytenr,
7625db02760SStefan Behrens 				     superblock_mirror_num);
7635db02760SStefan Behrens 		list_add(&superblock_tmp->all_blocks_node,
7645db02760SStefan Behrens 			 &state->all_blocks_list);
7655db02760SStefan Behrens 		btrfsic_block_hashtable_add(superblock_tmp,
7665db02760SStefan Behrens 					    &state->block_hashtable);
7675db02760SStefan Behrens 	}
7685db02760SStefan Behrens 
7695db02760SStefan Behrens 	/* select the one with the highest generation field */
7705db02760SStefan Behrens 	if (btrfs_super_generation(super_tmp) >
7715db02760SStefan Behrens 	    state->max_superblock_generation ||
7725db02760SStefan Behrens 	    0 == state->max_superblock_generation) {
7735db02760SStefan Behrens 		memcpy(selected_super, super_tmp, sizeof(*selected_super));
7745db02760SStefan Behrens 		*selected_dev_state = dev_state;
7755db02760SStefan Behrens 		state->max_superblock_generation =
7765db02760SStefan Behrens 		    btrfs_super_generation(super_tmp);
7775db02760SStefan Behrens 		state->latest_superblock = superblock_tmp;
7785db02760SStefan Behrens 	}
7795db02760SStefan Behrens 
7805db02760SStefan Behrens 	for (pass = 0; pass < 3; pass++) {
7815db02760SStefan Behrens 		u64 next_bytenr;
7825db02760SStefan Behrens 		int num_copies;
7835db02760SStefan Behrens 		int mirror_num;
7845db02760SStefan Behrens 		const char *additional_string = NULL;
7855db02760SStefan Behrens 		struct btrfs_disk_key tmp_disk_key;
7865db02760SStefan Behrens 
7875db02760SStefan Behrens 		tmp_disk_key.type = BTRFS_ROOT_ITEM_KEY;
7885db02760SStefan Behrens 		tmp_disk_key.offset = 0;
7895db02760SStefan Behrens 		switch (pass) {
7905db02760SStefan Behrens 		case 0:
7913cae210fSQu Wenruo 			btrfs_set_disk_key_objectid(&tmp_disk_key,
7923cae210fSQu Wenruo 						    BTRFS_ROOT_TREE_OBJECTID);
7935db02760SStefan Behrens 			additional_string = "initial root ";
7945db02760SStefan Behrens 			next_bytenr = btrfs_super_root(super_tmp);
7955db02760SStefan Behrens 			break;
7965db02760SStefan Behrens 		case 1:
7973cae210fSQu Wenruo 			btrfs_set_disk_key_objectid(&tmp_disk_key,
7983cae210fSQu Wenruo 						    BTRFS_CHUNK_TREE_OBJECTID);
7995db02760SStefan Behrens 			additional_string = "initial chunk ";
8005db02760SStefan Behrens 			next_bytenr = btrfs_super_chunk_root(super_tmp);
8015db02760SStefan Behrens 			break;
8025db02760SStefan Behrens 		case 2:
8033cae210fSQu Wenruo 			btrfs_set_disk_key_objectid(&tmp_disk_key,
8043cae210fSQu Wenruo 						    BTRFS_TREE_LOG_OBJECTID);
8055db02760SStefan Behrens 			additional_string = "initial log ";
8065db02760SStefan Behrens 			next_bytenr = btrfs_super_log_root(super_tmp);
8075db02760SStefan Behrens 			if (0 == next_bytenr)
8085db02760SStefan Behrens 				continue;
8095db02760SStefan Behrens 			break;
8105db02760SStefan Behrens 		}
8115db02760SStefan Behrens 
8120b246afaSJeff Mahoney 		num_copies = btrfs_num_copies(fs_info, next_bytenr,
8130b246afaSJeff Mahoney 					      state->metablock_size);
8145db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
81562e85577SJeff Mahoney 			pr_info("num_copies(log_bytenr=%llu) = %d\n",
816c1c9ff7cSGeert Uytterhoeven 			       next_bytenr, num_copies);
8175db02760SStefan Behrens 		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
8185db02760SStefan Behrens 			struct btrfsic_block *next_block;
8195db02760SStefan Behrens 			struct btrfsic_block_data_ctx tmp_next_block_ctx;
8205db02760SStefan Behrens 			struct btrfsic_block_link *l;
8215db02760SStefan Behrens 
822e06baab4SStefan Behrens 			if (btrfsic_map_block(state, next_bytenr,
823e06baab4SStefan Behrens 					      state->metablock_size,
8245db02760SStefan Behrens 					      &tmp_next_block_ctx,
8255db02760SStefan Behrens 					      mirror_num)) {
82662e85577SJeff Mahoney 				pr_info("btrfsic: btrfsic_map_block(bytenr @%llu, mirror %d) failed!\n",
827c1c9ff7cSGeert Uytterhoeven 				       next_bytenr, mirror_num);
8289da2b242SJohannes Thumshirn 				ret = -1;
8299da2b242SJohannes Thumshirn 				goto out;
8305db02760SStefan Behrens 			}
8315db02760SStefan Behrens 
8325db02760SStefan Behrens 			next_block = btrfsic_block_lookup_or_add(
8335db02760SStefan Behrens 					state, &tmp_next_block_ctx,
8345db02760SStefan Behrens 					additional_string, 1, 1, 0,
8355db02760SStefan Behrens 					mirror_num, NULL);
8365db02760SStefan Behrens 			if (NULL == next_block) {
8375db02760SStefan Behrens 				btrfsic_release_block_ctx(&tmp_next_block_ctx);
8389da2b242SJohannes Thumshirn 				ret = -1;
8399da2b242SJohannes Thumshirn 				goto out;
8405db02760SStefan Behrens 			}
8415db02760SStefan Behrens 
8425db02760SStefan Behrens 			next_block->disk_key = tmp_disk_key;
8435db02760SStefan Behrens 			next_block->generation = BTRFSIC_GENERATION_UNKNOWN;
8445db02760SStefan Behrens 			l = btrfsic_block_link_lookup_or_add(
8455db02760SStefan Behrens 					state, &tmp_next_block_ctx,
8465db02760SStefan Behrens 					next_block, superblock_tmp,
8475db02760SStefan Behrens 					BTRFSIC_GENERATION_UNKNOWN);
8485db02760SStefan Behrens 			btrfsic_release_block_ctx(&tmp_next_block_ctx);
8495db02760SStefan Behrens 			if (NULL == l) {
8509da2b242SJohannes Thumshirn 				ret = -1;
8519da2b242SJohannes Thumshirn 				goto out;
8525db02760SStefan Behrens 			}
8535db02760SStefan Behrens 		}
8545db02760SStefan Behrens 	}
8555db02760SStefan Behrens 	if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES)
8565db02760SStefan Behrens 		btrfsic_dump_tree_sub(state, superblock_tmp, 0);
8575db02760SStefan Behrens 
8589da2b242SJohannes Thumshirn out:
8599da2b242SJohannes Thumshirn 	put_page(page);
8609da2b242SJohannes Thumshirn 	return ret;
8615db02760SStefan Behrens }
8625db02760SStefan Behrens 
btrfsic_stack_frame_alloc(void)8635db02760SStefan Behrens static struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void)
8645db02760SStefan Behrens {
8655db02760SStefan Behrens 	struct btrfsic_stack_frame *sf;
8665db02760SStefan Behrens 
8675db02760SStefan Behrens 	sf = kzalloc(sizeof(*sf), GFP_NOFS);
868ab483009SLiao Pingfang 	if (sf)
8695db02760SStefan Behrens 		sf->magic = BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER;
8705db02760SStefan Behrens 	return sf;
8715db02760SStefan Behrens }
8725db02760SStefan Behrens 
btrfsic_stack_frame_free(struct btrfsic_stack_frame * sf)8735db02760SStefan Behrens static void btrfsic_stack_frame_free(struct btrfsic_stack_frame *sf)
8745db02760SStefan Behrens {
8755db02760SStefan Behrens 	BUG_ON(!(NULL == sf ||
8765db02760SStefan Behrens 		 BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER == sf->magic));
8775db02760SStefan Behrens 	kfree(sf);
8785db02760SStefan Behrens }
8795db02760SStefan Behrens 
btrfsic_process_metablock(struct btrfsic_state * state,struct btrfsic_block * const first_block,struct btrfsic_block_data_ctx * const first_block_ctx,int first_limit_nesting,int force_iodone_flag)8808ddc3197SArnd Bergmann static noinline_for_stack int btrfsic_process_metablock(
8815db02760SStefan Behrens 		struct btrfsic_state *state,
8825db02760SStefan Behrens 		struct btrfsic_block *const first_block,
8835db02760SStefan Behrens 		struct btrfsic_block_data_ctx *const first_block_ctx,
8845db02760SStefan Behrens 		int first_limit_nesting, int force_iodone_flag)
8855db02760SStefan Behrens {
8865db02760SStefan Behrens 	struct btrfsic_stack_frame initial_stack_frame = { 0 };
8875db02760SStefan Behrens 	struct btrfsic_stack_frame *sf;
8885db02760SStefan Behrens 	struct btrfsic_stack_frame *next_stack;
889e06baab4SStefan Behrens 	struct btrfs_header *const first_hdr =
890e06baab4SStefan Behrens 		(struct btrfs_header *)first_block_ctx->datav[0];
8915db02760SStefan Behrens 
892e06baab4SStefan Behrens 	BUG_ON(!first_hdr);
8935db02760SStefan Behrens 	sf = &initial_stack_frame;
8945db02760SStefan Behrens 	sf->error = 0;
8955db02760SStefan Behrens 	sf->i = -1;
8965db02760SStefan Behrens 	sf->limit_nesting = first_limit_nesting;
8975db02760SStefan Behrens 	sf->block = first_block;
8985db02760SStefan Behrens 	sf->block_ctx = first_block_ctx;
8995db02760SStefan Behrens 	sf->next_block = NULL;
9005db02760SStefan Behrens 	sf->hdr = first_hdr;
9015db02760SStefan Behrens 	sf->prev = NULL;
9025db02760SStefan Behrens 
9035db02760SStefan Behrens continue_with_new_stack_frame:
9043b5418fbSDavid Sterba 	sf->block->generation = btrfs_stack_header_generation(sf->hdr);
9055db02760SStefan Behrens 	if (0 == sf->hdr->level) {
9065db02760SStefan Behrens 		struct btrfs_leaf *const leafhdr =
9075db02760SStefan Behrens 		    (struct btrfs_leaf *)sf->hdr;
9085db02760SStefan Behrens 
9095db02760SStefan Behrens 		if (-1 == sf->i) {
9103cae210fSQu Wenruo 			sf->nr = btrfs_stack_header_nritems(&leafhdr->header);
9115db02760SStefan Behrens 
9125db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
91362e85577SJeff Mahoney 				pr_info("leaf %llu items %d generation %llu owner %llu\n",
914c1c9ff7cSGeert Uytterhoeven 				       sf->block_ctx->start, sf->nr,
9153cae210fSQu Wenruo 				       btrfs_stack_header_generation(
9163cae210fSQu Wenruo 					       &leafhdr->header),
9173cae210fSQu Wenruo 				       btrfs_stack_header_owner(
9183cae210fSQu Wenruo 					       &leafhdr->header));
9195db02760SStefan Behrens 		}
9205db02760SStefan Behrens 
9215db02760SStefan Behrens continue_with_current_leaf_stack_frame:
9225db02760SStefan Behrens 		if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) {
9235db02760SStefan Behrens 			sf->i++;
9245db02760SStefan Behrens 			sf->num_copies = 0;
9255db02760SStefan Behrens 		}
9265db02760SStefan Behrens 
9275db02760SStefan Behrens 		if (sf->i < sf->nr) {
928e06baab4SStefan Behrens 			struct btrfs_item disk_item;
929e06baab4SStefan Behrens 			u32 disk_item_offset =
930e06baab4SStefan Behrens 				(uintptr_t)(leafhdr->items + sf->i) -
931e06baab4SStefan Behrens 				(uintptr_t)leafhdr;
932e06baab4SStefan Behrens 			struct btrfs_disk_key *disk_key;
9335db02760SStefan Behrens 			u8 type;
934e06baab4SStefan Behrens 			u32 item_offset;
9358ea05e3aSAlexander Block 			u32 item_size;
9365db02760SStefan Behrens 
937e06baab4SStefan Behrens 			if (disk_item_offset + sizeof(struct btrfs_item) >
938e06baab4SStefan Behrens 			    sf->block_ctx->len) {
939e06baab4SStefan Behrens leaf_item_out_of_bounce_error:
940813ebc16SChristoph Hellwig 				pr_info(
941813ebc16SChristoph Hellwig 		"btrfsic: leaf item out of bounce at logical %llu, dev %pg\n",
942e06baab4SStefan Behrens 				       sf->block_ctx->start,
943813ebc16SChristoph Hellwig 				       sf->block_ctx->dev->bdev);
944e06baab4SStefan Behrens 				goto one_stack_frame_backwards;
945e06baab4SStefan Behrens 			}
946e06baab4SStefan Behrens 			btrfsic_read_from_block_data(sf->block_ctx,
947e06baab4SStefan Behrens 						     &disk_item,
948e06baab4SStefan Behrens 						     disk_item_offset,
949e06baab4SStefan Behrens 						     sizeof(struct btrfs_item));
9503cae210fSQu Wenruo 			item_offset = btrfs_stack_item_offset(&disk_item);
951a5f519c9SStefan Behrens 			item_size = btrfs_stack_item_size(&disk_item);
952e06baab4SStefan Behrens 			disk_key = &disk_item.key;
9533cae210fSQu Wenruo 			type = btrfs_disk_key_type(disk_key);
9545db02760SStefan Behrens 
9555db02760SStefan Behrens 			if (BTRFS_ROOT_ITEM_KEY == type) {
956e06baab4SStefan Behrens 				struct btrfs_root_item root_item;
957e06baab4SStefan Behrens 				u32 root_item_offset;
958e06baab4SStefan Behrens 				u64 next_bytenr;
959e06baab4SStefan Behrens 
960e06baab4SStefan Behrens 				root_item_offset = item_offset +
961e06baab4SStefan Behrens 					offsetof(struct btrfs_leaf, items);
9628ea05e3aSAlexander Block 				if (root_item_offset + item_size >
963e06baab4SStefan Behrens 				    sf->block_ctx->len)
964e06baab4SStefan Behrens 					goto leaf_item_out_of_bounce_error;
965e06baab4SStefan Behrens 				btrfsic_read_from_block_data(
966e06baab4SStefan Behrens 					sf->block_ctx, &root_item,
967e06baab4SStefan Behrens 					root_item_offset,
9688ea05e3aSAlexander Block 					item_size);
9693cae210fSQu Wenruo 				next_bytenr = btrfs_root_bytenr(&root_item);
9705db02760SStefan Behrens 
9715db02760SStefan Behrens 				sf->error =
9725db02760SStefan Behrens 				    btrfsic_create_link_to_next_block(
9735db02760SStefan Behrens 						state,
9745db02760SStefan Behrens 						sf->block,
9755db02760SStefan Behrens 						sf->block_ctx,
9765db02760SStefan Behrens 						next_bytenr,
9775db02760SStefan Behrens 						sf->limit_nesting,
9785db02760SStefan Behrens 						&sf->next_block_ctx,
9795db02760SStefan Behrens 						&sf->next_block,
9805db02760SStefan Behrens 						force_iodone_flag,
9815db02760SStefan Behrens 						&sf->num_copies,
9825db02760SStefan Behrens 						&sf->mirror_num,
9835db02760SStefan Behrens 						disk_key,
9843cae210fSQu Wenruo 						btrfs_root_generation(
9853cae210fSQu Wenruo 						&root_item));
9865db02760SStefan Behrens 				if (sf->error)
9875db02760SStefan Behrens 					goto one_stack_frame_backwards;
9885db02760SStefan Behrens 
9895db02760SStefan Behrens 				if (NULL != sf->next_block) {
9905db02760SStefan Behrens 					struct btrfs_header *const next_hdr =
9915db02760SStefan Behrens 					    (struct btrfs_header *)
992e06baab4SStefan Behrens 					    sf->next_block_ctx.datav[0];
9935db02760SStefan Behrens 
9945db02760SStefan Behrens 					next_stack =
9955db02760SStefan Behrens 					    btrfsic_stack_frame_alloc();
9965db02760SStefan Behrens 					if (NULL == next_stack) {
99798806b44SStefan Behrens 						sf->error = -1;
9985db02760SStefan Behrens 						btrfsic_release_block_ctx(
9995db02760SStefan Behrens 								&sf->
10005db02760SStefan Behrens 								next_block_ctx);
10015db02760SStefan Behrens 						goto one_stack_frame_backwards;
10025db02760SStefan Behrens 					}
10035db02760SStefan Behrens 
10045db02760SStefan Behrens 					next_stack->i = -1;
10055db02760SStefan Behrens 					next_stack->block = sf->next_block;
10065db02760SStefan Behrens 					next_stack->block_ctx =
10075db02760SStefan Behrens 					    &sf->next_block_ctx;
10085db02760SStefan Behrens 					next_stack->next_block = NULL;
10095db02760SStefan Behrens 					next_stack->hdr = next_hdr;
10105db02760SStefan Behrens 					next_stack->limit_nesting =
10115db02760SStefan Behrens 					    sf->limit_nesting - 1;
10125db02760SStefan Behrens 					next_stack->prev = sf;
10135db02760SStefan Behrens 					sf = next_stack;
10145db02760SStefan Behrens 					goto continue_with_new_stack_frame;
10155db02760SStefan Behrens 				}
10165db02760SStefan Behrens 			} else if (BTRFS_EXTENT_DATA_KEY == type &&
10175db02760SStefan Behrens 				   state->include_extent_data) {
10185db02760SStefan Behrens 				sf->error = btrfsic_handle_extent_data(
10195db02760SStefan Behrens 						state,
10205db02760SStefan Behrens 						sf->block,
10215db02760SStefan Behrens 						sf->block_ctx,
10225db02760SStefan Behrens 						item_offset,
10235db02760SStefan Behrens 						force_iodone_flag);
10245db02760SStefan Behrens 				if (sf->error)
10255db02760SStefan Behrens 					goto one_stack_frame_backwards;
10265db02760SStefan Behrens 			}
10275db02760SStefan Behrens 
10285db02760SStefan Behrens 			goto continue_with_current_leaf_stack_frame;
10295db02760SStefan Behrens 		}
10305db02760SStefan Behrens 	} else {
10315db02760SStefan Behrens 		struct btrfs_node *const nodehdr = (struct btrfs_node *)sf->hdr;
10325db02760SStefan Behrens 
10335db02760SStefan Behrens 		if (-1 == sf->i) {
10343cae210fSQu Wenruo 			sf->nr = btrfs_stack_header_nritems(&nodehdr->header);
10355db02760SStefan Behrens 
10365db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
103762e85577SJeff Mahoney 				pr_info("node %llu level %d items %d generation %llu owner %llu\n",
10385db02760SStefan Behrens 				       sf->block_ctx->start,
10395db02760SStefan Behrens 				       nodehdr->header.level, sf->nr,
10403cae210fSQu Wenruo 				       btrfs_stack_header_generation(
10413cae210fSQu Wenruo 				       &nodehdr->header),
10423cae210fSQu Wenruo 				       btrfs_stack_header_owner(
10433cae210fSQu Wenruo 				       &nodehdr->header));
10445db02760SStefan Behrens 		}
10455db02760SStefan Behrens 
10465db02760SStefan Behrens continue_with_current_node_stack_frame:
10475db02760SStefan Behrens 		if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) {
10485db02760SStefan Behrens 			sf->i++;
10495db02760SStefan Behrens 			sf->num_copies = 0;
10505db02760SStefan Behrens 		}
10515db02760SStefan Behrens 
10525db02760SStefan Behrens 		if (sf->i < sf->nr) {
1053e06baab4SStefan Behrens 			struct btrfs_key_ptr key_ptr;
1054e06baab4SStefan Behrens 			u32 key_ptr_offset;
1055e06baab4SStefan Behrens 			u64 next_bytenr;
1056e06baab4SStefan Behrens 
1057e06baab4SStefan Behrens 			key_ptr_offset = (uintptr_t)(nodehdr->ptrs + sf->i) -
1058e06baab4SStefan Behrens 					  (uintptr_t)nodehdr;
1059e06baab4SStefan Behrens 			if (key_ptr_offset + sizeof(struct btrfs_key_ptr) >
1060e06baab4SStefan Behrens 			    sf->block_ctx->len) {
1061813ebc16SChristoph Hellwig 				pr_info(
1062813ebc16SChristoph Hellwig 		"btrfsic: node item out of bounce at logical %llu, dev %pg\n",
1063e06baab4SStefan Behrens 				       sf->block_ctx->start,
1064813ebc16SChristoph Hellwig 				       sf->block_ctx->dev->bdev);
1065e06baab4SStefan Behrens 				goto one_stack_frame_backwards;
1066e06baab4SStefan Behrens 			}
1067e06baab4SStefan Behrens 			btrfsic_read_from_block_data(
1068e06baab4SStefan Behrens 				sf->block_ctx, &key_ptr, key_ptr_offset,
1069e06baab4SStefan Behrens 				sizeof(struct btrfs_key_ptr));
10703cae210fSQu Wenruo 			next_bytenr = btrfs_stack_key_blockptr(&key_ptr);
10715db02760SStefan Behrens 
10725db02760SStefan Behrens 			sf->error = btrfsic_create_link_to_next_block(
10735db02760SStefan Behrens 					state,
10745db02760SStefan Behrens 					sf->block,
10755db02760SStefan Behrens 					sf->block_ctx,
10765db02760SStefan Behrens 					next_bytenr,
10775db02760SStefan Behrens 					sf->limit_nesting,
10785db02760SStefan Behrens 					&sf->next_block_ctx,
10795db02760SStefan Behrens 					&sf->next_block,
10805db02760SStefan Behrens 					force_iodone_flag,
10815db02760SStefan Behrens 					&sf->num_copies,
10825db02760SStefan Behrens 					&sf->mirror_num,
1083e06baab4SStefan Behrens 					&key_ptr.key,
10843cae210fSQu Wenruo 					btrfs_stack_key_generation(&key_ptr));
10855db02760SStefan Behrens 			if (sf->error)
10865db02760SStefan Behrens 				goto one_stack_frame_backwards;
10875db02760SStefan Behrens 
10885db02760SStefan Behrens 			if (NULL != sf->next_block) {
10895db02760SStefan Behrens 				struct btrfs_header *const next_hdr =
10905db02760SStefan Behrens 				    (struct btrfs_header *)
1091e06baab4SStefan Behrens 				    sf->next_block_ctx.datav[0];
10925db02760SStefan Behrens 
10935db02760SStefan Behrens 				next_stack = btrfsic_stack_frame_alloc();
109498806b44SStefan Behrens 				if (NULL == next_stack) {
109598806b44SStefan Behrens 					sf->error = -1;
10965db02760SStefan Behrens 					goto one_stack_frame_backwards;
109798806b44SStefan Behrens 				}
10985db02760SStefan Behrens 
10995db02760SStefan Behrens 				next_stack->i = -1;
11005db02760SStefan Behrens 				next_stack->block = sf->next_block;
11015db02760SStefan Behrens 				next_stack->block_ctx = &sf->next_block_ctx;
11025db02760SStefan Behrens 				next_stack->next_block = NULL;
11035db02760SStefan Behrens 				next_stack->hdr = next_hdr;
11045db02760SStefan Behrens 				next_stack->limit_nesting =
11055db02760SStefan Behrens 				    sf->limit_nesting - 1;
11065db02760SStefan Behrens 				next_stack->prev = sf;
11075db02760SStefan Behrens 				sf = next_stack;
11085db02760SStefan Behrens 				goto continue_with_new_stack_frame;
11095db02760SStefan Behrens 			}
11105db02760SStefan Behrens 
11115db02760SStefan Behrens 			goto continue_with_current_node_stack_frame;
11125db02760SStefan Behrens 		}
11135db02760SStefan Behrens 	}
11145db02760SStefan Behrens 
11155db02760SStefan Behrens one_stack_frame_backwards:
11165db02760SStefan Behrens 	if (NULL != sf->prev) {
11175db02760SStefan Behrens 		struct btrfsic_stack_frame *const prev = sf->prev;
11185db02760SStefan Behrens 
11195db02760SStefan Behrens 		/* the one for the initial block is freed in the caller */
11205db02760SStefan Behrens 		btrfsic_release_block_ctx(sf->block_ctx);
11215db02760SStefan Behrens 
11225db02760SStefan Behrens 		if (sf->error) {
11235db02760SStefan Behrens 			prev->error = sf->error;
11245db02760SStefan Behrens 			btrfsic_stack_frame_free(sf);
11255db02760SStefan Behrens 			sf = prev;
11265db02760SStefan Behrens 			goto one_stack_frame_backwards;
11275db02760SStefan Behrens 		}
11285db02760SStefan Behrens 
11295db02760SStefan Behrens 		btrfsic_stack_frame_free(sf);
11305db02760SStefan Behrens 		sf = prev;
11315db02760SStefan Behrens 		goto continue_with_new_stack_frame;
11325db02760SStefan Behrens 	} else {
11335db02760SStefan Behrens 		BUG_ON(&initial_stack_frame != sf);
11345db02760SStefan Behrens 	}
11355db02760SStefan Behrens 
11365db02760SStefan Behrens 	return sf->error;
11375db02760SStefan Behrens }
11385db02760SStefan Behrens 
btrfsic_read_from_block_data(struct btrfsic_block_data_ctx * block_ctx,void * dstv,u32 offset,size_t len)1139e06baab4SStefan Behrens static void btrfsic_read_from_block_data(
1140e06baab4SStefan Behrens 	struct btrfsic_block_data_ctx *block_ctx,
1141e06baab4SStefan Behrens 	void *dstv, u32 offset, size_t len)
1142e06baab4SStefan Behrens {
1143e06baab4SStefan Behrens 	size_t cur;
11447073017aSJohannes Thumshirn 	size_t pgoff;
1145e06baab4SStefan Behrens 	char *kaddr;
1146e06baab4SStefan Behrens 	char *dst = (char *)dstv;
11477073017aSJohannes Thumshirn 	size_t start_offset = offset_in_page(block_ctx->start);
114809cbfeafSKirill A. Shutemov 	unsigned long i = (start_offset + offset) >> PAGE_SHIFT;
1149e06baab4SStefan Behrens 
1150e06baab4SStefan Behrens 	WARN_ON(offset + len > block_ctx->len);
11517073017aSJohannes Thumshirn 	pgoff = offset_in_page(start_offset + offset);
1152e06baab4SStefan Behrens 
1153e06baab4SStefan Behrens 	while (len > 0) {
11547073017aSJohannes Thumshirn 		cur = min(len, ((size_t)PAGE_SIZE - pgoff));
115509cbfeafSKirill A. Shutemov 		BUG_ON(i >= DIV_ROUND_UP(block_ctx->len, PAGE_SIZE));
1156e06baab4SStefan Behrens 		kaddr = block_ctx->datav[i];
11577073017aSJohannes Thumshirn 		memcpy(dst, kaddr + pgoff, cur);
1158e06baab4SStefan Behrens 
1159e06baab4SStefan Behrens 		dst += cur;
1160e06baab4SStefan Behrens 		len -= cur;
11617073017aSJohannes Thumshirn 		pgoff = 0;
1162e06baab4SStefan Behrens 		i++;
1163e06baab4SStefan Behrens 	}
1164e06baab4SStefan Behrens }
1165e06baab4SStefan Behrens 
btrfsic_create_link_to_next_block(struct btrfsic_state * state,struct btrfsic_block * block,struct btrfsic_block_data_ctx * block_ctx,u64 next_bytenr,int limit_nesting,struct btrfsic_block_data_ctx * next_block_ctx,struct btrfsic_block ** next_blockp,int force_iodone_flag,int * num_copiesp,int * mirror_nump,struct btrfs_disk_key * disk_key,u64 parent_generation)11665db02760SStefan Behrens static int btrfsic_create_link_to_next_block(
11675db02760SStefan Behrens 		struct btrfsic_state *state,
11685db02760SStefan Behrens 		struct btrfsic_block *block,
11695db02760SStefan Behrens 		struct btrfsic_block_data_ctx *block_ctx,
11705db02760SStefan Behrens 		u64 next_bytenr,
11715db02760SStefan Behrens 		int limit_nesting,
11725db02760SStefan Behrens 		struct btrfsic_block_data_ctx *next_block_ctx,
11735db02760SStefan Behrens 		struct btrfsic_block **next_blockp,
11745db02760SStefan Behrens 		int force_iodone_flag,
11755db02760SStefan Behrens 		int *num_copiesp, int *mirror_nump,
11765db02760SStefan Behrens 		struct btrfs_disk_key *disk_key,
11775db02760SStefan Behrens 		u64 parent_generation)
11785db02760SStefan Behrens {
11790b246afaSJeff Mahoney 	struct btrfs_fs_info *fs_info = state->fs_info;
11805db02760SStefan Behrens 	struct btrfsic_block *next_block = NULL;
11815db02760SStefan Behrens 	int ret;
11825db02760SStefan Behrens 	struct btrfsic_block_link *l;
11835db02760SStefan Behrens 	int did_alloc_block_link;
11845db02760SStefan Behrens 	int block_was_created;
11855db02760SStefan Behrens 
11865db02760SStefan Behrens 	*next_blockp = NULL;
11875db02760SStefan Behrens 	if (0 == *num_copiesp) {
11880b246afaSJeff Mahoney 		*num_copiesp = btrfs_num_copies(fs_info, next_bytenr,
11890b246afaSJeff Mahoney 						state->metablock_size);
11905db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
119162e85577SJeff Mahoney 			pr_info("num_copies(log_bytenr=%llu) = %d\n",
1192c1c9ff7cSGeert Uytterhoeven 			       next_bytenr, *num_copiesp);
11935db02760SStefan Behrens 		*mirror_nump = 1;
11945db02760SStefan Behrens 	}
11955db02760SStefan Behrens 
11965db02760SStefan Behrens 	if (*mirror_nump > *num_copiesp)
11975db02760SStefan Behrens 		return 0;
11985db02760SStefan Behrens 
11995db02760SStefan Behrens 	if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
120062e85577SJeff Mahoney 		pr_info("btrfsic_create_link_to_next_block(mirror_num=%d)\n",
12015db02760SStefan Behrens 		       *mirror_nump);
12025db02760SStefan Behrens 	ret = btrfsic_map_block(state, next_bytenr,
1203e06baab4SStefan Behrens 				state->metablock_size,
12045db02760SStefan Behrens 				next_block_ctx, *mirror_nump);
12055db02760SStefan Behrens 	if (ret) {
120662e85577SJeff Mahoney 		pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
1207c1c9ff7cSGeert Uytterhoeven 		       next_bytenr, *mirror_nump);
12085db02760SStefan Behrens 		btrfsic_release_block_ctx(next_block_ctx);
12095db02760SStefan Behrens 		*next_blockp = NULL;
12105db02760SStefan Behrens 		return -1;
12115db02760SStefan Behrens 	}
12125db02760SStefan Behrens 
12135db02760SStefan Behrens 	next_block = btrfsic_block_lookup_or_add(state,
12145db02760SStefan Behrens 						 next_block_ctx, "referenced ",
12155db02760SStefan Behrens 						 1, force_iodone_flag,
12165db02760SStefan Behrens 						 !force_iodone_flag,
12175db02760SStefan Behrens 						 *mirror_nump,
12185db02760SStefan Behrens 						 &block_was_created);
12195db02760SStefan Behrens 	if (NULL == next_block) {
12205db02760SStefan Behrens 		btrfsic_release_block_ctx(next_block_ctx);
12215db02760SStefan Behrens 		*next_blockp = NULL;
12225db02760SStefan Behrens 		return -1;
12235db02760SStefan Behrens 	}
12245db02760SStefan Behrens 	if (block_was_created) {
12255db02760SStefan Behrens 		l = NULL;
12265db02760SStefan Behrens 		next_block->generation = BTRFSIC_GENERATION_UNKNOWN;
12275db02760SStefan Behrens 	} else {
1228cf90c59eSStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) {
12295db02760SStefan Behrens 			if (next_block->logical_bytenr != next_bytenr &&
12305db02760SStefan Behrens 			    !(!next_block->is_metadata &&
1231cf90c59eSStefan Behrens 			      0 == next_block->logical_bytenr))
1232813ebc16SChristoph Hellwig 				pr_info(
1233813ebc16SChristoph Hellwig "referenced block @%llu (%pg/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu)\n",
1234813ebc16SChristoph Hellwig 				       next_bytenr, next_block_ctx->dev->bdev,
1235c1c9ff7cSGeert Uytterhoeven 				       next_block_ctx->dev_bytenr, *mirror_nump,
1236cf90c59eSStefan Behrens 				       btrfsic_get_block_type(state,
1237cf90c59eSStefan Behrens 							      next_block),
1238c1c9ff7cSGeert Uytterhoeven 				       next_block->logical_bytenr);
1239cf90c59eSStefan Behrens 			else
1240813ebc16SChristoph Hellwig 				pr_info(
1241813ebc16SChristoph Hellwig 		"referenced block @%llu (%pg/%llu/%d) found in hash table, %c\n",
1242813ebc16SChristoph Hellwig 				       next_bytenr, next_block_ctx->dev->bdev,
1243c1c9ff7cSGeert Uytterhoeven 				       next_block_ctx->dev_bytenr, *mirror_nump,
1244cf90c59eSStefan Behrens 				       btrfsic_get_block_type(state,
1245cf90c59eSStefan Behrens 							      next_block));
1246cf90c59eSStefan Behrens 		}
12475db02760SStefan Behrens 		next_block->logical_bytenr = next_bytenr;
12485db02760SStefan Behrens 
12495db02760SStefan Behrens 		next_block->mirror_num = *mirror_nump;
12505db02760SStefan Behrens 		l = btrfsic_block_link_hashtable_lookup(
12515db02760SStefan Behrens 				next_block_ctx->dev->bdev,
12525db02760SStefan Behrens 				next_block_ctx->dev_bytenr,
12535db02760SStefan Behrens 				block_ctx->dev->bdev,
12545db02760SStefan Behrens 				block_ctx->dev_bytenr,
12555db02760SStefan Behrens 				&state->block_link_hashtable);
12565db02760SStefan Behrens 	}
12575db02760SStefan Behrens 
12585db02760SStefan Behrens 	next_block->disk_key = *disk_key;
12595db02760SStefan Behrens 	if (NULL == l) {
12605db02760SStefan Behrens 		l = btrfsic_block_link_alloc();
12615db02760SStefan Behrens 		if (NULL == l) {
12625db02760SStefan Behrens 			btrfsic_release_block_ctx(next_block_ctx);
12635db02760SStefan Behrens 			*next_blockp = NULL;
12645db02760SStefan Behrens 			return -1;
12655db02760SStefan Behrens 		}
12665db02760SStefan Behrens 
12675db02760SStefan Behrens 		did_alloc_block_link = 1;
12685db02760SStefan Behrens 		l->block_ref_to = next_block;
12695db02760SStefan Behrens 		l->block_ref_from = block;
12705db02760SStefan Behrens 		l->ref_cnt = 1;
12715db02760SStefan Behrens 		l->parent_generation = parent_generation;
12725db02760SStefan Behrens 
12735db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
12745db02760SStefan Behrens 			btrfsic_print_add_link(state, l);
12755db02760SStefan Behrens 
12765db02760SStefan Behrens 		list_add(&l->node_ref_to, &block->ref_to_list);
12775db02760SStefan Behrens 		list_add(&l->node_ref_from, &next_block->ref_from_list);
12785db02760SStefan Behrens 
12795db02760SStefan Behrens 		btrfsic_block_link_hashtable_add(l,
12805db02760SStefan Behrens 						 &state->block_link_hashtable);
12815db02760SStefan Behrens 	} else {
12825db02760SStefan Behrens 		did_alloc_block_link = 0;
12835db02760SStefan Behrens 		if (0 == limit_nesting) {
12845db02760SStefan Behrens 			l->ref_cnt++;
12855db02760SStefan Behrens 			l->parent_generation = parent_generation;
12865db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
12875db02760SStefan Behrens 				btrfsic_print_add_link(state, l);
12885db02760SStefan Behrens 		}
12895db02760SStefan Behrens 	}
12905db02760SStefan Behrens 
12915db02760SStefan Behrens 	if (limit_nesting > 0 && did_alloc_block_link) {
12925db02760SStefan Behrens 		ret = btrfsic_read_block(state, next_block_ctx);
1293e06baab4SStefan Behrens 		if (ret < (int)next_block_ctx->len) {
129462e85577SJeff Mahoney 			pr_info("btrfsic: read block @logical %llu failed!\n",
1295c1c9ff7cSGeert Uytterhoeven 			       next_bytenr);
12965db02760SStefan Behrens 			btrfsic_release_block_ctx(next_block_ctx);
12975db02760SStefan Behrens 			*next_blockp = NULL;
12985db02760SStefan Behrens 			return -1;
12995db02760SStefan Behrens 		}
13005db02760SStefan Behrens 
13015db02760SStefan Behrens 		*next_blockp = next_block;
13025db02760SStefan Behrens 	} else {
13035db02760SStefan Behrens 		*next_blockp = NULL;
13045db02760SStefan Behrens 	}
13055db02760SStefan Behrens 	(*mirror_nump)++;
13065db02760SStefan Behrens 
13075db02760SStefan Behrens 	return 0;
13085db02760SStefan Behrens }
13095db02760SStefan Behrens 
btrfsic_handle_extent_data(struct btrfsic_state * state,struct btrfsic_block * block,struct btrfsic_block_data_ctx * block_ctx,u32 item_offset,int force_iodone_flag)13105db02760SStefan Behrens static int btrfsic_handle_extent_data(
13115db02760SStefan Behrens 		struct btrfsic_state *state,
13125db02760SStefan Behrens 		struct btrfsic_block *block,
13135db02760SStefan Behrens 		struct btrfsic_block_data_ctx *block_ctx,
13145db02760SStefan Behrens 		u32 item_offset, int force_iodone_flag)
13155db02760SStefan Behrens {
13160b246afaSJeff Mahoney 	struct btrfs_fs_info *fs_info = state->fs_info;
1317e06baab4SStefan Behrens 	struct btrfs_file_extent_item file_extent_item;
1318e06baab4SStefan Behrens 	u64 file_extent_item_offset;
1319e06baab4SStefan Behrens 	u64 next_bytenr;
1320e06baab4SStefan Behrens 	u64 num_bytes;
1321e06baab4SStefan Behrens 	u64 generation;
13225db02760SStefan Behrens 	struct btrfsic_block_link *l;
13230b246afaSJeff Mahoney 	int ret;
13245db02760SStefan Behrens 
1325e06baab4SStefan Behrens 	file_extent_item_offset = offsetof(struct btrfs_leaf, items) +
1326e06baab4SStefan Behrens 				  item_offset;
132786ff7ffcSStefan Behrens 	if (file_extent_item_offset +
132886ff7ffcSStefan Behrens 	    offsetof(struct btrfs_file_extent_item, disk_num_bytes) >
132986ff7ffcSStefan Behrens 	    block_ctx->len) {
1330813ebc16SChristoph Hellwig 		pr_info("btrfsic: file item out of bounce at logical %llu, dev %pg\n",
1331813ebc16SChristoph Hellwig 		       block_ctx->start, block_ctx->dev->bdev);
133286ff7ffcSStefan Behrens 		return -1;
133386ff7ffcSStefan Behrens 	}
133486ff7ffcSStefan Behrens 
133586ff7ffcSStefan Behrens 	btrfsic_read_from_block_data(block_ctx, &file_extent_item,
133686ff7ffcSStefan Behrens 		file_extent_item_offset,
133786ff7ffcSStefan Behrens 		offsetof(struct btrfs_file_extent_item, disk_num_bytes));
133886ff7ffcSStefan Behrens 	if (BTRFS_FILE_EXTENT_REG != file_extent_item.type ||
13393cae210fSQu Wenruo 	    btrfs_stack_file_extent_disk_bytenr(&file_extent_item) == 0) {
134086ff7ffcSStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
134162e85577SJeff Mahoney 			pr_info("extent_data: type %u, disk_bytenr = %llu\n",
134286ff7ffcSStefan Behrens 			       file_extent_item.type,
13433cae210fSQu Wenruo 			       btrfs_stack_file_extent_disk_bytenr(
13443cae210fSQu Wenruo 			       &file_extent_item));
134586ff7ffcSStefan Behrens 		return 0;
134686ff7ffcSStefan Behrens 	}
134786ff7ffcSStefan Behrens 
1348e06baab4SStefan Behrens 	if (file_extent_item_offset + sizeof(struct btrfs_file_extent_item) >
1349e06baab4SStefan Behrens 	    block_ctx->len) {
1350813ebc16SChristoph Hellwig 		pr_info("btrfsic: file item out of bounce at logical %llu, dev %pg\n",
1351813ebc16SChristoph Hellwig 		       block_ctx->start, block_ctx->dev->bdev);
1352e06baab4SStefan Behrens 		return -1;
1353e06baab4SStefan Behrens 	}
1354e06baab4SStefan Behrens 	btrfsic_read_from_block_data(block_ctx, &file_extent_item,
1355e06baab4SStefan Behrens 				     file_extent_item_offset,
1356e06baab4SStefan Behrens 				     sizeof(struct btrfs_file_extent_item));
1357e20d6c5bSJosef Bacik 	next_bytenr = btrfs_stack_file_extent_disk_bytenr(&file_extent_item);
1358e20d6c5bSJosef Bacik 	if (btrfs_stack_file_extent_compression(&file_extent_item) ==
1359e20d6c5bSJosef Bacik 	    BTRFS_COMPRESS_NONE) {
1360e20d6c5bSJosef Bacik 		next_bytenr += btrfs_stack_file_extent_offset(&file_extent_item);
13613cae210fSQu Wenruo 		num_bytes = btrfs_stack_file_extent_num_bytes(&file_extent_item);
1362e20d6c5bSJosef Bacik 	} else {
1363e20d6c5bSJosef Bacik 		num_bytes = btrfs_stack_file_extent_disk_num_bytes(&file_extent_item);
1364e20d6c5bSJosef Bacik 	}
13653cae210fSQu Wenruo 	generation = btrfs_stack_file_extent_generation(&file_extent_item);
1366e06baab4SStefan Behrens 
13675db02760SStefan Behrens 	if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
136862e85577SJeff Mahoney 		pr_info("extent_data: type %u, disk_bytenr = %llu, offset = %llu, num_bytes = %llu\n",
1369e06baab4SStefan Behrens 		       file_extent_item.type,
13703cae210fSQu Wenruo 		       btrfs_stack_file_extent_disk_bytenr(&file_extent_item),
13713cae210fSQu Wenruo 		       btrfs_stack_file_extent_offset(&file_extent_item),
1372c1c9ff7cSGeert Uytterhoeven 		       num_bytes);
13735db02760SStefan Behrens 	while (num_bytes > 0) {
13745db02760SStefan Behrens 		u32 chunk_len;
13755db02760SStefan Behrens 		int num_copies;
13765db02760SStefan Behrens 		int mirror_num;
13775db02760SStefan Behrens 
1378e06baab4SStefan Behrens 		if (num_bytes > state->datablock_size)
1379e06baab4SStefan Behrens 			chunk_len = state->datablock_size;
13805db02760SStefan Behrens 		else
13815db02760SStefan Behrens 			chunk_len = num_bytes;
13825db02760SStefan Behrens 
13830b246afaSJeff Mahoney 		num_copies = btrfs_num_copies(fs_info, next_bytenr,
13840b246afaSJeff Mahoney 					      state->datablock_size);
13855db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
138662e85577SJeff Mahoney 			pr_info("num_copies(log_bytenr=%llu) = %d\n",
1387c1c9ff7cSGeert Uytterhoeven 			       next_bytenr, num_copies);
13885db02760SStefan Behrens 		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
13895db02760SStefan Behrens 			struct btrfsic_block_data_ctx next_block_ctx;
13905db02760SStefan Behrens 			struct btrfsic_block *next_block;
13915db02760SStefan Behrens 			int block_was_created;
13925db02760SStefan Behrens 
13935db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
139462e85577SJeff Mahoney 				pr_info("btrfsic_handle_extent_data(mirror_num=%d)\n",
139562e85577SJeff Mahoney 					mirror_num);
13965db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE)
139762e85577SJeff Mahoney 				pr_info("\tdisk_bytenr = %llu, num_bytes %u\n",
1398c1c9ff7cSGeert Uytterhoeven 				       next_bytenr, chunk_len);
13995db02760SStefan Behrens 			ret = btrfsic_map_block(state, next_bytenr,
14005db02760SStefan Behrens 						chunk_len, &next_block_ctx,
14015db02760SStefan Behrens 						mirror_num);
14025db02760SStefan Behrens 			if (ret) {
140362e85577SJeff Mahoney 				pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
1404c1c9ff7cSGeert Uytterhoeven 				       next_bytenr, mirror_num);
14055db02760SStefan Behrens 				return -1;
14065db02760SStefan Behrens 			}
14075db02760SStefan Behrens 
14085db02760SStefan Behrens 			next_block = btrfsic_block_lookup_or_add(
14095db02760SStefan Behrens 					state,
14105db02760SStefan Behrens 					&next_block_ctx,
14115db02760SStefan Behrens 					"referenced ",
14125db02760SStefan Behrens 					0,
14135db02760SStefan Behrens 					force_iodone_flag,
14145db02760SStefan Behrens 					!force_iodone_flag,
14155db02760SStefan Behrens 					mirror_num,
14165db02760SStefan Behrens 					&block_was_created);
14175db02760SStefan Behrens 			if (NULL == next_block) {
14185db02760SStefan Behrens 				btrfsic_release_block_ctx(&next_block_ctx);
14195db02760SStefan Behrens 				return -1;
14205db02760SStefan Behrens 			}
14215db02760SStefan Behrens 			if (!block_was_created) {
1422cf90c59eSStefan Behrens 				if ((state->print_mask &
1423cf90c59eSStefan Behrens 				     BTRFSIC_PRINT_MASK_VERBOSE) &&
1424cf90c59eSStefan Behrens 				    next_block->logical_bytenr != next_bytenr &&
14255db02760SStefan Behrens 				    !(!next_block->is_metadata &&
14265db02760SStefan Behrens 				      0 == next_block->logical_bytenr)) {
1427813ebc16SChristoph Hellwig 					pr_info(
1428813ebc16SChristoph Hellwig "referenced block @%llu (%pg/%llu/%d) found in hash table, D, bytenr mismatch (!= stored %llu)\n",
1429c1c9ff7cSGeert Uytterhoeven 					       next_bytenr,
1430813ebc16SChristoph Hellwig 					       next_block_ctx.dev->bdev,
14315db02760SStefan Behrens 					       next_block_ctx.dev_bytenr,
14325db02760SStefan Behrens 					       mirror_num,
14335db02760SStefan Behrens 					       next_block->logical_bytenr);
14345db02760SStefan Behrens 				}
14355db02760SStefan Behrens 				next_block->logical_bytenr = next_bytenr;
14365db02760SStefan Behrens 				next_block->mirror_num = mirror_num;
14375db02760SStefan Behrens 			}
14385db02760SStefan Behrens 
14395db02760SStefan Behrens 			l = btrfsic_block_link_lookup_or_add(state,
14405db02760SStefan Behrens 							     &next_block_ctx,
14415db02760SStefan Behrens 							     next_block, block,
14425db02760SStefan Behrens 							     generation);
14435db02760SStefan Behrens 			btrfsic_release_block_ctx(&next_block_ctx);
14445db02760SStefan Behrens 			if (NULL == l)
14455db02760SStefan Behrens 				return -1;
14465db02760SStefan Behrens 		}
14475db02760SStefan Behrens 
14485db02760SStefan Behrens 		next_bytenr += chunk_len;
14495db02760SStefan Behrens 		num_bytes -= chunk_len;
14505db02760SStefan Behrens 	}
14515db02760SStefan Behrens 
14525db02760SStefan Behrens 	return 0;
14535db02760SStefan Behrens }
14545db02760SStefan Behrens 
btrfsic_map_block(struct btrfsic_state * state,u64 bytenr,u32 len,struct btrfsic_block_data_ctx * block_ctx_out,int mirror_num)14555db02760SStefan Behrens static int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len,
14565db02760SStefan Behrens 			     struct btrfsic_block_data_ctx *block_ctx_out,
14575db02760SStefan Behrens 			     int mirror_num)
14585db02760SStefan Behrens {
14590b246afaSJeff Mahoney 	struct btrfs_fs_info *fs_info = state->fs_info;
14605db02760SStefan Behrens 	int ret;
14615db02760SStefan Behrens 	u64 length;
146278a213a0SChristoph Hellwig 	struct btrfs_io_context *bioc = NULL;
146378a213a0SChristoph Hellwig 	struct btrfs_io_stripe smap, *map;
14645db02760SStefan Behrens 	struct btrfs_device *device;
14655db02760SStefan Behrens 
14665db02760SStefan Behrens 	length = len;
1467*cd4efd21SChristoph Hellwig 	ret = btrfs_map_block(fs_info, BTRFS_MAP_READ, bytenr, &length, &bioc,
146878a213a0SChristoph Hellwig 			      NULL, &mirror_num, 0);
146961891923SStefan Behrens 	if (ret) {
147061891923SStefan Behrens 		block_ctx_out->start = 0;
147161891923SStefan Behrens 		block_ctx_out->dev_bytenr = 0;
147261891923SStefan Behrens 		block_ctx_out->len = 0;
147361891923SStefan Behrens 		block_ctx_out->dev = NULL;
147461891923SStefan Behrens 		block_ctx_out->datav = NULL;
147561891923SStefan Behrens 		block_ctx_out->pagev = NULL;
147661891923SStefan Behrens 		block_ctx_out->mem_to_free = NULL;
147761891923SStefan Behrens 
147861891923SStefan Behrens 		return ret;
147961891923SStefan Behrens 	}
148061891923SStefan Behrens 
148178a213a0SChristoph Hellwig 	if (bioc)
148278a213a0SChristoph Hellwig 		map = &bioc->stripes[0];
148378a213a0SChristoph Hellwig 	else
148478a213a0SChristoph Hellwig 		map = &smap;
148578a213a0SChristoph Hellwig 
148678a213a0SChristoph Hellwig 	device = map->dev;
14879912bbf6SQu Wenruo 	if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state) ||
14889912bbf6SQu Wenruo 	    !device->bdev || !device->name)
14899912bbf6SQu Wenruo 		block_ctx_out->dev = NULL;
14909912bbf6SQu Wenruo 	else
14919912bbf6SQu Wenruo 		block_ctx_out->dev = btrfsic_dev_state_lookup(
14929912bbf6SQu Wenruo 							device->bdev->bd_dev);
149378a213a0SChristoph Hellwig 	block_ctx_out->dev_bytenr = map->physical;
14945db02760SStefan Behrens 	block_ctx_out->start = bytenr;
14955db02760SStefan Behrens 	block_ctx_out->len = len;
1496e06baab4SStefan Behrens 	block_ctx_out->datav = NULL;
1497e06baab4SStefan Behrens 	block_ctx_out->pagev = NULL;
1498e06baab4SStefan Behrens 	block_ctx_out->mem_to_free = NULL;
14995db02760SStefan Behrens 
150078a213a0SChristoph Hellwig 	kfree(bioc);
15015db02760SStefan Behrens 	if (NULL == block_ctx_out->dev) {
15025db02760SStefan Behrens 		ret = -ENXIO;
150362e85577SJeff Mahoney 		pr_info("btrfsic: error, cannot lookup dev (#1)!\n");
15045db02760SStefan Behrens 	}
15055db02760SStefan Behrens 
15065db02760SStefan Behrens 	return ret;
15075db02760SStefan Behrens }
15085db02760SStefan Behrens 
btrfsic_release_block_ctx(struct btrfsic_block_data_ctx * block_ctx)15095db02760SStefan Behrens static void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx)
15105db02760SStefan Behrens {
1511e06baab4SStefan Behrens 	if (block_ctx->mem_to_free) {
1512e06baab4SStefan Behrens 		unsigned int num_pages;
1513e06baab4SStefan Behrens 
1514e06baab4SStefan Behrens 		BUG_ON(!block_ctx->datav);
1515e06baab4SStefan Behrens 		BUG_ON(!block_ctx->pagev);
151609cbfeafSKirill A. Shutemov 		num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >>
151709cbfeafSKirill A. Shutemov 			    PAGE_SHIFT;
15189a002d53SIra Weiny 		/* Pages must be unmapped in reverse order */
1519e06baab4SStefan Behrens 		while (num_pages > 0) {
1520e06baab4SStefan Behrens 			num_pages--;
15215da38479SDavid Sterba 			if (block_ctx->datav[num_pages])
1522e06baab4SStefan Behrens 				block_ctx->datav[num_pages] = NULL;
1523e06baab4SStefan Behrens 			if (block_ctx->pagev[num_pages]) {
1524e06baab4SStefan Behrens 				__free_page(block_ctx->pagev[num_pages]);
1525e06baab4SStefan Behrens 				block_ctx->pagev[num_pages] = NULL;
1526e06baab4SStefan Behrens 			}
1527e06baab4SStefan Behrens 		}
1528e06baab4SStefan Behrens 
1529e06baab4SStefan Behrens 		kfree(block_ctx->mem_to_free);
1530e06baab4SStefan Behrens 		block_ctx->mem_to_free = NULL;
1531e06baab4SStefan Behrens 		block_ctx->pagev = NULL;
1532e06baab4SStefan Behrens 		block_ctx->datav = NULL;
15335db02760SStefan Behrens 	}
15345db02760SStefan Behrens }
15355db02760SStefan Behrens 
btrfsic_read_block(struct btrfsic_state * state,struct btrfsic_block_data_ctx * block_ctx)15365db02760SStefan Behrens static int btrfsic_read_block(struct btrfsic_state *state,
15375db02760SStefan Behrens 			      struct btrfsic_block_data_ctx *block_ctx)
15385db02760SStefan Behrens {
1539e06baab4SStefan Behrens 	unsigned int num_pages;
1540e06baab4SStefan Behrens 	unsigned int i;
15413b2fd801SLiu Bo 	size_t size;
1542e06baab4SStefan Behrens 	u64 dev_bytenr;
1543e06baab4SStefan Behrens 	int ret;
1544e06baab4SStefan Behrens 
1545e06baab4SStefan Behrens 	BUG_ON(block_ctx->datav);
1546e06baab4SStefan Behrens 	BUG_ON(block_ctx->pagev);
1547e06baab4SStefan Behrens 	BUG_ON(block_ctx->mem_to_free);
1548fdb1e121SJohannes Thumshirn 	if (!PAGE_ALIGNED(block_ctx->dev_bytenr)) {
154962e85577SJeff Mahoney 		pr_info("btrfsic: read_block() with unaligned bytenr %llu\n",
1550c1c9ff7cSGeert Uytterhoeven 		       block_ctx->dev_bytenr);
15515db02760SStefan Behrens 		return -1;
15525db02760SStefan Behrens 	}
1553e06baab4SStefan Behrens 
155409cbfeafSKirill A. Shutemov 	num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >>
155509cbfeafSKirill A. Shutemov 		    PAGE_SHIFT;
15563b2fd801SLiu Bo 	size = sizeof(*block_ctx->datav) + sizeof(*block_ctx->pagev);
15573b2fd801SLiu Bo 	block_ctx->mem_to_free = kcalloc(num_pages, size, GFP_NOFS);
1558e06baab4SStefan Behrens 	if (!block_ctx->mem_to_free)
15590b8d8ce0SLuis de Bethencourt 		return -ENOMEM;
1560e06baab4SStefan Behrens 	block_ctx->datav = block_ctx->mem_to_free;
1561e06baab4SStefan Behrens 	block_ctx->pagev = (struct page **)(block_ctx->datav + num_pages);
1562dd137dd1SSweet Tea Dorminy 	ret = btrfs_alloc_page_array(num_pages, block_ctx->pagev);
1563dd137dd1SSweet Tea Dorminy 	if (ret)
1564dd137dd1SSweet Tea Dorminy 		return ret;
15655db02760SStefan Behrens 
1566e06baab4SStefan Behrens 	dev_bytenr = block_ctx->dev_bytenr;
1567e06baab4SStefan Behrens 	for (i = 0; i < num_pages;) {
1568e06baab4SStefan Behrens 		struct bio *bio;
1569e06baab4SStefan Behrens 		unsigned int j;
1570e06baab4SStefan Behrens 
157191e3b5f1SChristoph Hellwig 		bio = bio_alloc(block_ctx->dev->bdev, num_pages - i,
157291e3b5f1SChristoph Hellwig 				REQ_OP_READ, GFP_NOFS);
157329e70be2SAnand Jain 		bio->bi_iter.bi_sector = dev_bytenr >> SECTOR_SHIFT;
1574e06baab4SStefan Behrens 
1575e06baab4SStefan Behrens 		for (j = i; j < num_pages; j++) {
1576e06baab4SStefan Behrens 			ret = bio_add_page(bio, block_ctx->pagev[j],
157709cbfeafSKirill A. Shutemov 					   PAGE_SIZE, 0);
157809cbfeafSKirill A. Shutemov 			if (PAGE_SIZE != ret)
1579e06baab4SStefan Behrens 				break;
1580e06baab4SStefan Behrens 		}
1581e06baab4SStefan Behrens 		if (j == i) {
158262e85577SJeff Mahoney 			pr_info("btrfsic: error, failed to add a single page!\n");
1583e06baab4SStefan Behrens 			return -1;
1584e06baab4SStefan Behrens 		}
15854e49ea4aSMike Christie 		if (submit_bio_wait(bio)) {
1586813ebc16SChristoph Hellwig 			pr_info("btrfsic: read error at logical %llu dev %pg!\n",
1587813ebc16SChristoph Hellwig 			       block_ctx->start, block_ctx->dev->bdev);
1588e06baab4SStefan Behrens 			bio_put(bio);
1589e06baab4SStefan Behrens 			return -1;
1590e06baab4SStefan Behrens 		}
1591e06baab4SStefan Behrens 		bio_put(bio);
159209cbfeafSKirill A. Shutemov 		dev_bytenr += (j - i) * PAGE_SIZE;
1593e06baab4SStefan Behrens 		i = j;
1594e06baab4SStefan Behrens 	}
1595977ec792SFabian Frederick 	for (i = 0; i < num_pages; i++)
15965da38479SDavid Sterba 		block_ctx->datav[i] = page_address(block_ctx->pagev[i]);
15975db02760SStefan Behrens 
15985db02760SStefan Behrens 	return block_ctx->len;
15995db02760SStefan Behrens }
16005db02760SStefan Behrens 
btrfsic_dump_database(struct btrfsic_state * state)16015db02760SStefan Behrens static void btrfsic_dump_database(struct btrfsic_state *state)
16025db02760SStefan Behrens {
1603b69f2befSGeliang Tang 	const struct btrfsic_block *b_all;
16045db02760SStefan Behrens 
16055db02760SStefan Behrens 	BUG_ON(NULL == state);
16065db02760SStefan Behrens 
160762e85577SJeff Mahoney 	pr_info("all_blocks_list:\n");
1608b69f2befSGeliang Tang 	list_for_each_entry(b_all, &state->all_blocks_list, all_blocks_node) {
1609b69f2befSGeliang Tang 		const struct btrfsic_block_link *l;
16105db02760SStefan Behrens 
1611813ebc16SChristoph Hellwig 		pr_info("%c-block @%llu (%pg/%llu/%d)\n",
16125db02760SStefan Behrens 		       btrfsic_get_block_type(state, b_all),
1613813ebc16SChristoph Hellwig 		       b_all->logical_bytenr, b_all->dev_state->bdev,
1614c1c9ff7cSGeert Uytterhoeven 		       b_all->dev_bytenr, b_all->mirror_num);
16155db02760SStefan Behrens 
1616b69f2befSGeliang Tang 		list_for_each_entry(l, &b_all->ref_to_list, node_ref_to) {
1617813ebc16SChristoph Hellwig 			pr_info(
1618813ebc16SChristoph Hellwig 		" %c @%llu (%pg/%llu/%d) refers %u* to %c @%llu (%pg/%llu/%d)\n",
16195db02760SStefan Behrens 			       btrfsic_get_block_type(state, b_all),
1620813ebc16SChristoph Hellwig 			       b_all->logical_bytenr, b_all->dev_state->bdev,
1621c1c9ff7cSGeert Uytterhoeven 			       b_all->dev_bytenr, b_all->mirror_num,
16225db02760SStefan Behrens 			       l->ref_cnt,
16235db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_to),
16245db02760SStefan Behrens 			       l->block_ref_to->logical_bytenr,
1625813ebc16SChristoph Hellwig 			       l->block_ref_to->dev_state->bdev,
1626c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->dev_bytenr,
16275db02760SStefan Behrens 			       l->block_ref_to->mirror_num);
16285db02760SStefan Behrens 		}
16295db02760SStefan Behrens 
1630b69f2befSGeliang Tang 		list_for_each_entry(l, &b_all->ref_from_list, node_ref_from) {
1631813ebc16SChristoph Hellwig 			pr_info(
1632813ebc16SChristoph Hellwig 		" %c @%llu (%pg/%llu/%d) is ref %u* from %c @%llu (%pg/%llu/%d)\n",
16335db02760SStefan Behrens 			       btrfsic_get_block_type(state, b_all),
1634813ebc16SChristoph Hellwig 			       b_all->logical_bytenr, b_all->dev_state->bdev,
1635c1c9ff7cSGeert Uytterhoeven 			       b_all->dev_bytenr, b_all->mirror_num,
16365db02760SStefan Behrens 			       l->ref_cnt,
16375db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_from),
16385db02760SStefan Behrens 			       l->block_ref_from->logical_bytenr,
1639813ebc16SChristoph Hellwig 			       l->block_ref_from->dev_state->bdev,
16405db02760SStefan Behrens 			       l->block_ref_from->dev_bytenr,
16415db02760SStefan Behrens 			       l->block_ref_from->mirror_num);
16425db02760SStefan Behrens 		}
16435db02760SStefan Behrens 
164462e85577SJeff Mahoney 		pr_info("\n");
16455db02760SStefan Behrens 	}
16465db02760SStefan Behrens }
16475db02760SStefan Behrens 
16485db02760SStefan Behrens /*
16495db02760SStefan Behrens  * Test whether the disk block contains a tree block (leaf or node)
16505db02760SStefan Behrens  * (note that this test fails for the super block)
16515db02760SStefan Behrens  */
btrfsic_test_for_metadata(struct btrfsic_state * state,char ** datav,unsigned int num_pages)16528ddc3197SArnd Bergmann static noinline_for_stack int btrfsic_test_for_metadata(
16538ddc3197SArnd Bergmann 		struct btrfsic_state *state,
1654e06baab4SStefan Behrens 		char **datav, unsigned int num_pages)
16555db02760SStefan Behrens {
16560b246afaSJeff Mahoney 	struct btrfs_fs_info *fs_info = state->fs_info;
1657d5178578SJohannes Thumshirn 	SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
16585db02760SStefan Behrens 	struct btrfs_header *h;
16595db02760SStefan Behrens 	u8 csum[BTRFS_CSUM_SIZE];
1660e06baab4SStefan Behrens 	unsigned int i;
16615db02760SStefan Behrens 
166209cbfeafSKirill A. Shutemov 	if (num_pages * PAGE_SIZE < state->metablock_size)
1663e06baab4SStefan Behrens 		return 1; /* not metadata */
166409cbfeafSKirill A. Shutemov 	num_pages = state->metablock_size >> PAGE_SHIFT;
1665e06baab4SStefan Behrens 	h = (struct btrfs_header *)datav[0];
16665db02760SStefan Behrens 
1667de37aa51SNikolay Borisov 	if (memcmp(h->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE))
1668e06baab4SStefan Behrens 		return 1;
16695db02760SStefan Behrens 
1670d5178578SJohannes Thumshirn 	shash->tfm = fs_info->csum_shash;
1671d5178578SJohannes Thumshirn 	crypto_shash_init(shash);
1672d5178578SJohannes Thumshirn 
1673e06baab4SStefan Behrens 	for (i = 0; i < num_pages; i++) {
1674e06baab4SStefan Behrens 		u8 *data = i ? datav[i] : (datav[i] + BTRFS_CSUM_SIZE);
167509cbfeafSKirill A. Shutemov 		size_t sublen = i ? PAGE_SIZE :
167609cbfeafSKirill A. Shutemov 				    (PAGE_SIZE - BTRFS_CSUM_SIZE);
1677e06baab4SStefan Behrens 
1678d5178578SJohannes Thumshirn 		crypto_shash_update(shash, data, sublen);
1679e06baab4SStefan Behrens 	}
1680d5178578SJohannes Thumshirn 	crypto_shash_final(shash, csum);
1681419b791cSDavid Sterba 	if (memcmp(csum, h->csum, fs_info->csum_size))
1682e06baab4SStefan Behrens 		return 1;
16835db02760SStefan Behrens 
1684e06baab4SStefan Behrens 	return 0; /* is metadata */
16855db02760SStefan Behrens }
16865db02760SStefan Behrens 
btrfsic_process_written_block(struct btrfsic_dev_state * dev_state,u64 dev_bytenr,char ** mapped_datav,unsigned int num_pages,struct bio * bio,int * bio_is_patched,blk_opf_t submit_bio_bh_rw)16875db02760SStefan Behrens static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state,
1688e06baab4SStefan Behrens 					  u64 dev_bytenr, char **mapped_datav,
1689e06baab4SStefan Behrens 					  unsigned int num_pages,
1690e06baab4SStefan Behrens 					  struct bio *bio, int *bio_is_patched,
1691bf9486d6SBart Van Assche 					  blk_opf_t submit_bio_bh_rw)
16925db02760SStefan Behrens {
16935db02760SStefan Behrens 	int is_metadata;
16945db02760SStefan Behrens 	struct btrfsic_block *block;
16955db02760SStefan Behrens 	struct btrfsic_block_data_ctx block_ctx;
16965db02760SStefan Behrens 	int ret;
16975db02760SStefan Behrens 	struct btrfsic_state *state = dev_state->state;
16985db02760SStefan Behrens 	struct block_device *bdev = dev_state->bdev;
1699e06baab4SStefan Behrens 	unsigned int processed_len;
17005db02760SStefan Behrens 
17015db02760SStefan Behrens 	if (NULL != bio_is_patched)
17025db02760SStefan Behrens 		*bio_is_patched = 0;
17035db02760SStefan Behrens 
1704e06baab4SStefan Behrens again:
1705e06baab4SStefan Behrens 	if (num_pages == 0)
1706e06baab4SStefan Behrens 		return;
1707e06baab4SStefan Behrens 
1708e06baab4SStefan Behrens 	processed_len = 0;
1709e06baab4SStefan Behrens 	is_metadata = (0 == btrfsic_test_for_metadata(state, mapped_datav,
1710e06baab4SStefan Behrens 						      num_pages));
1711e06baab4SStefan Behrens 
17125db02760SStefan Behrens 	block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr,
17135db02760SStefan Behrens 					       &state->block_hashtable);
17145db02760SStefan Behrens 	if (NULL != block) {
17150b485143SStefan Behrens 		u64 bytenr = 0;
1716b69f2befSGeliang Tang 		struct btrfsic_block_link *l, *tmp;
17175db02760SStefan Behrens 
17185db02760SStefan Behrens 		if (block->is_superblock) {
17193cae210fSQu Wenruo 			bytenr = btrfs_super_bytenr((struct btrfs_super_block *)
17203cae210fSQu Wenruo 						    mapped_datav[0]);
172109cbfeafSKirill A. Shutemov 			if (num_pages * PAGE_SIZE <
1722e06baab4SStefan Behrens 			    BTRFS_SUPER_INFO_SIZE) {
172362e85577SJeff Mahoney 				pr_info("btrfsic: cannot work with too short bios!\n");
1724e06baab4SStefan Behrens 				return;
1725e06baab4SStefan Behrens 			}
17265db02760SStefan Behrens 			is_metadata = 1;
1727fdb1e121SJohannes Thumshirn 			BUG_ON(!PAGE_ALIGNED(BTRFS_SUPER_INFO_SIZE));
1728e06baab4SStefan Behrens 			processed_len = BTRFS_SUPER_INFO_SIZE;
17295db02760SStefan Behrens 			if (state->print_mask &
17305db02760SStefan Behrens 			    BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE) {
173162e85577SJeff Mahoney 				pr_info("[before new superblock is written]:\n");
17325db02760SStefan Behrens 				btrfsic_dump_tree_sub(state, block, 0);
17335db02760SStefan Behrens 			}
17345db02760SStefan Behrens 		}
17355db02760SStefan Behrens 		if (is_metadata) {
17365db02760SStefan Behrens 			if (!block->is_superblock) {
173709cbfeafSKirill A. Shutemov 				if (num_pages * PAGE_SIZE <
1738e06baab4SStefan Behrens 				    state->metablock_size) {
173962e85577SJeff Mahoney 					pr_info("btrfsic: cannot work with too short bios!\n");
1740e06baab4SStefan Behrens 					return;
1741e06baab4SStefan Behrens 				}
1742e06baab4SStefan Behrens 				processed_len = state->metablock_size;
17433cae210fSQu Wenruo 				bytenr = btrfs_stack_header_bytenr(
17443cae210fSQu Wenruo 						(struct btrfs_header *)
17453cae210fSQu Wenruo 						mapped_datav[0]);
17465db02760SStefan Behrens 				btrfsic_cmp_log_and_dev_bytenr(state, bytenr,
17475db02760SStefan Behrens 							       dev_state,
1748e06baab4SStefan Behrens 							       dev_bytenr);
17495db02760SStefan Behrens 			}
1750cf90c59eSStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) {
1751301993a4SStefan Behrens 				if (block->logical_bytenr != bytenr &&
1752301993a4SStefan Behrens 				    !(!block->is_metadata &&
1753301993a4SStefan Behrens 				      block->logical_bytenr == 0))
1754813ebc16SChristoph Hellwig 					pr_info(
1755813ebc16SChristoph Hellwig "written block @%llu (%pg/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu)\n",
1756813ebc16SChristoph Hellwig 					       bytenr, dev_state->bdev,
1757cf90c59eSStefan Behrens 					       dev_bytenr,
17585db02760SStefan Behrens 					       block->mirror_num,
1759cf90c59eSStefan Behrens 					       btrfsic_get_block_type(state,
1760cf90c59eSStefan Behrens 								      block),
17615db02760SStefan Behrens 					       block->logical_bytenr);
1762cf90c59eSStefan Behrens 				else
1763813ebc16SChristoph Hellwig 					pr_info(
1764813ebc16SChristoph Hellwig 		"written block @%llu (%pg/%llu/%d) found in hash table, %c\n",
1765813ebc16SChristoph Hellwig 					       bytenr, dev_state->bdev,
1766cf90c59eSStefan Behrens 					       dev_bytenr, block->mirror_num,
1767cf90c59eSStefan Behrens 					       btrfsic_get_block_type(state,
1768cf90c59eSStefan Behrens 								      block));
1769cf90c59eSStefan Behrens 			}
1770301993a4SStefan Behrens 			block->logical_bytenr = bytenr;
17715db02760SStefan Behrens 		} else {
177209cbfeafSKirill A. Shutemov 			if (num_pages * PAGE_SIZE <
1773e06baab4SStefan Behrens 			    state->datablock_size) {
177462e85577SJeff Mahoney 				pr_info("btrfsic: cannot work with too short bios!\n");
1775e06baab4SStefan Behrens 				return;
1776e06baab4SStefan Behrens 			}
1777e06baab4SStefan Behrens 			processed_len = state->datablock_size;
17785db02760SStefan Behrens 			bytenr = block->logical_bytenr;
17795db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
1780813ebc16SChristoph Hellwig 				pr_info(
1781813ebc16SChristoph Hellwig 		"written block @%llu (%pg/%llu/%d) found in hash table, %c\n",
1782813ebc16SChristoph Hellwig 				       bytenr, dev_state->bdev, dev_bytenr,
17835db02760SStefan Behrens 				       block->mirror_num,
17845db02760SStefan Behrens 				       btrfsic_get_block_type(state, block));
17855db02760SStefan Behrens 		}
17865db02760SStefan Behrens 
17875db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
178862e85577SJeff Mahoney 			pr_info("ref_to_list: %cE, ref_from_list: %cE\n",
17895db02760SStefan Behrens 			       list_empty(&block->ref_to_list) ? ' ' : '!',
17905db02760SStefan Behrens 			       list_empty(&block->ref_from_list) ? ' ' : '!');
17915db02760SStefan Behrens 		if (btrfsic_is_block_ref_by_superblock(state, block, 0)) {
1792813ebc16SChristoph Hellwig 			pr_info(
1793813ebc16SChristoph Hellwig "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",
1794c1c9ff7cSGeert Uytterhoeven 			       btrfsic_get_block_type(state, block), bytenr,
1795813ebc16SChristoph Hellwig 			       dev_state->bdev, dev_bytenr, block->mirror_num,
1796c1c9ff7cSGeert Uytterhoeven 			       block->generation,
17973cae210fSQu Wenruo 			       btrfs_disk_key_objectid(&block->disk_key),
17985db02760SStefan Behrens 			       block->disk_key.type,
17993cae210fSQu Wenruo 			       btrfs_disk_key_offset(&block->disk_key),
18003cae210fSQu Wenruo 			       btrfs_stack_header_generation(
18013cae210fSQu Wenruo 				       (struct btrfs_header *) mapped_datav[0]),
18025db02760SStefan Behrens 			       state->max_superblock_generation);
18035db02760SStefan Behrens 			btrfsic_dump_tree(state);
18045db02760SStefan Behrens 		}
18055db02760SStefan Behrens 
18065db02760SStefan Behrens 		if (!block->is_iodone && !block->never_written) {
1807813ebc16SChristoph Hellwig 			pr_info(
1808813ebc16SChristoph Hellwig "btrfs: attempt to overwrite %c-block @%llu (%pg/%llu/%d), oldgen=%llu, newgen=%llu, which is not yet iodone!\n",
1809c1c9ff7cSGeert Uytterhoeven 			       btrfsic_get_block_type(state, block), bytenr,
1810813ebc16SChristoph Hellwig 			       dev_state->bdev, dev_bytenr, block->mirror_num,
1811c1c9ff7cSGeert Uytterhoeven 			       block->generation,
18123cae210fSQu Wenruo 			       btrfs_stack_header_generation(
18133cae210fSQu Wenruo 				       (struct btrfs_header *)
18143cae210fSQu Wenruo 				       mapped_datav[0]));
18155db02760SStefan Behrens 			/* it would not be safe to go on */
18165db02760SStefan Behrens 			btrfsic_dump_tree(state);
1817e06baab4SStefan Behrens 			goto continue_loop;
18185db02760SStefan Behrens 		}
18195db02760SStefan Behrens 
18205db02760SStefan Behrens 		/*
18215db02760SStefan Behrens 		 * Clear all references of this block. Do not free
18225db02760SStefan Behrens 		 * the block itself even if is not referenced anymore
182301327610SNicholas D Steeves 		 * because it still carries valuable information
18245db02760SStefan Behrens 		 * like whether it was ever written and IO completed.
18255db02760SStefan Behrens 		 */
1826b69f2befSGeliang Tang 		list_for_each_entry_safe(l, tmp, &block->ref_to_list,
1827b69f2befSGeliang Tang 					 node_ref_to) {
18285db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
18295db02760SStefan Behrens 				btrfsic_print_rem_link(state, l);
18305db02760SStefan Behrens 			l->ref_cnt--;
18315db02760SStefan Behrens 			if (0 == l->ref_cnt) {
18325db02760SStefan Behrens 				list_del(&l->node_ref_to);
18335db02760SStefan Behrens 				list_del(&l->node_ref_from);
18345db02760SStefan Behrens 				btrfsic_block_link_hashtable_remove(l);
18355db02760SStefan Behrens 				btrfsic_block_link_free(l);
18365db02760SStefan Behrens 			}
18375db02760SStefan Behrens 		}
18385db02760SStefan Behrens 
18395db02760SStefan Behrens 		block_ctx.dev = dev_state;
18405db02760SStefan Behrens 		block_ctx.dev_bytenr = dev_bytenr;
1841f382e465SStefan Behrens 		block_ctx.start = bytenr;
1842f382e465SStefan Behrens 		block_ctx.len = processed_len;
1843f382e465SStefan Behrens 		block_ctx.pagev = NULL;
1844f382e465SStefan Behrens 		block_ctx.mem_to_free = NULL;
1845f382e465SStefan Behrens 		block_ctx.datav = mapped_datav;
18465db02760SStefan Behrens 
18475db02760SStefan Behrens 		if (is_metadata || state->include_extent_data) {
18485db02760SStefan Behrens 			block->never_written = 0;
18495db02760SStefan Behrens 			block->iodone_w_error = 0;
18505db02760SStefan Behrens 			if (NULL != bio) {
18515db02760SStefan Behrens 				block->is_iodone = 0;
18525db02760SStefan Behrens 				BUG_ON(NULL == bio_is_patched);
18535db02760SStefan Behrens 				if (!*bio_is_patched) {
185459aaad50SJohannes Thumshirn 					block->orig_bio_private =
18555db02760SStefan Behrens 					    bio->bi_private;
185659aaad50SJohannes Thumshirn 					block->orig_bio_end_io =
18575db02760SStefan Behrens 					    bio->bi_end_io;
18585db02760SStefan Behrens 					block->next_in_same_bio = NULL;
18595db02760SStefan Behrens 					bio->bi_private = block;
18605db02760SStefan Behrens 					bio->bi_end_io = btrfsic_bio_end_io;
18615db02760SStefan Behrens 					*bio_is_patched = 1;
18625db02760SStefan Behrens 				} else {
18635db02760SStefan Behrens 					struct btrfsic_block *chained_block =
18645db02760SStefan Behrens 					    (struct btrfsic_block *)
18655db02760SStefan Behrens 					    bio->bi_private;
18665db02760SStefan Behrens 
18675db02760SStefan Behrens 					BUG_ON(NULL == chained_block);
186859aaad50SJohannes Thumshirn 					block->orig_bio_private =
186959aaad50SJohannes Thumshirn 					    chained_block->orig_bio_private;
187059aaad50SJohannes Thumshirn 					block->orig_bio_end_io =
187159aaad50SJohannes Thumshirn 					    chained_block->orig_bio_end_io;
18725db02760SStefan Behrens 					block->next_in_same_bio = chained_block;
18735db02760SStefan Behrens 					bio->bi_private = block;
18745db02760SStefan Behrens 				}
18755db02760SStefan Behrens 			} else {
18765db02760SStefan Behrens 				block->is_iodone = 1;
187759aaad50SJohannes Thumshirn 				block->orig_bio_private = NULL;
187859aaad50SJohannes Thumshirn 				block->orig_bio_end_io = NULL;
18795db02760SStefan Behrens 				block->next_in_same_bio = NULL;
18805db02760SStefan Behrens 			}
18815db02760SStefan Behrens 		}
18825db02760SStefan Behrens 
18835db02760SStefan Behrens 		block->flush_gen = dev_state->last_flush_gen + 1;
18845db02760SStefan Behrens 		block->submit_bio_bh_rw = submit_bio_bh_rw;
18855db02760SStefan Behrens 		if (is_metadata) {
18865db02760SStefan Behrens 			block->logical_bytenr = bytenr;
18875db02760SStefan Behrens 			block->is_metadata = 1;
18885db02760SStefan Behrens 			if (block->is_superblock) {
188909cbfeafSKirill A. Shutemov 				BUG_ON(PAGE_SIZE !=
1890e06baab4SStefan Behrens 				       BTRFS_SUPER_INFO_SIZE);
18915db02760SStefan Behrens 				ret = btrfsic_process_written_superblock(
18925db02760SStefan Behrens 						state,
18935db02760SStefan Behrens 						block,
18945db02760SStefan Behrens 						(struct btrfs_super_block *)
1895e06baab4SStefan Behrens 						mapped_datav[0]);
18965db02760SStefan Behrens 				if (state->print_mask &
18975db02760SStefan Behrens 				    BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE) {
189862e85577SJeff Mahoney 					pr_info("[after new superblock is written]:\n");
18995db02760SStefan Behrens 					btrfsic_dump_tree_sub(state, block, 0);
19005db02760SStefan Behrens 				}
19015db02760SStefan Behrens 			} else {
19025db02760SStefan Behrens 				block->mirror_num = 0;	/* unknown */
19035db02760SStefan Behrens 				ret = btrfsic_process_metablock(
19045db02760SStefan Behrens 						state,
19055db02760SStefan Behrens 						block,
19065db02760SStefan Behrens 						&block_ctx,
19075db02760SStefan Behrens 						0, 0);
19085db02760SStefan Behrens 			}
19095db02760SStefan Behrens 			if (ret)
191062e85577SJeff Mahoney 				pr_info("btrfsic: btrfsic_process_metablock(root @%llu) failed!\n",
1911c1c9ff7cSGeert Uytterhoeven 				       dev_bytenr);
19125db02760SStefan Behrens 		} else {
19135db02760SStefan Behrens 			block->is_metadata = 0;
19145db02760SStefan Behrens 			block->mirror_num = 0;	/* unknown */
19155db02760SStefan Behrens 			block->generation = BTRFSIC_GENERATION_UNKNOWN;
19165db02760SStefan Behrens 			if (!state->include_extent_data
19175db02760SStefan Behrens 			    && list_empty(&block->ref_from_list)) {
19185db02760SStefan Behrens 				/*
19195db02760SStefan Behrens 				 * disk block is overwritten with extent
19205db02760SStefan Behrens 				 * data (not meta data) and we are configured
19215db02760SStefan Behrens 				 * to not include extent data: take the
19225db02760SStefan Behrens 				 * chance and free the block's memory
19235db02760SStefan Behrens 				 */
19245db02760SStefan Behrens 				btrfsic_block_hashtable_remove(block);
19255db02760SStefan Behrens 				list_del(&block->all_blocks_node);
19265db02760SStefan Behrens 				btrfsic_block_free(block);
19275db02760SStefan Behrens 			}
19285db02760SStefan Behrens 		}
19295db02760SStefan Behrens 		btrfsic_release_block_ctx(&block_ctx);
19305db02760SStefan Behrens 	} else {
19315db02760SStefan Behrens 		/* block has not been found in hash table */
19325db02760SStefan Behrens 		u64 bytenr;
19335db02760SStefan Behrens 
19345db02760SStefan Behrens 		if (!is_metadata) {
1935e06baab4SStefan Behrens 			processed_len = state->datablock_size;
19365db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
1937813ebc16SChristoph Hellwig 				pr_info(
1938813ebc16SChristoph Hellwig 			"written block (%pg/%llu/?) !found in hash table, D\n",
1939813ebc16SChristoph Hellwig 				       dev_state->bdev, dev_bytenr);
1940e06baab4SStefan Behrens 			if (!state->include_extent_data) {
1941e06baab4SStefan Behrens 				/* ignore that written D block */
1942e06baab4SStefan Behrens 				goto continue_loop;
1943e06baab4SStefan Behrens 			}
19445db02760SStefan Behrens 
19455db02760SStefan Behrens 			/* this is getting ugly for the
19465db02760SStefan Behrens 			 * include_extent_data case... */
19475db02760SStefan Behrens 			bytenr = 0;	/* unknown */
19485db02760SStefan Behrens 		} else {
1949e06baab4SStefan Behrens 			processed_len = state->metablock_size;
19503cae210fSQu Wenruo 			bytenr = btrfs_stack_header_bytenr(
19513cae210fSQu Wenruo 					(struct btrfs_header *)
19523cae210fSQu Wenruo 					mapped_datav[0]);
19535db02760SStefan Behrens 			btrfsic_cmp_log_and_dev_bytenr(state, bytenr, dev_state,
1954e06baab4SStefan Behrens 						       dev_bytenr);
19555db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
1956813ebc16SChristoph Hellwig 				pr_info(
1957813ebc16SChristoph Hellwig 			"written block @%llu (%pg/%llu/?) !found in hash table, M\n",
1958813ebc16SChristoph Hellwig 				       bytenr, dev_state->bdev, dev_bytenr);
1959f382e465SStefan Behrens 		}
19605db02760SStefan Behrens 
19615db02760SStefan Behrens 		block_ctx.dev = dev_state;
19625db02760SStefan Behrens 		block_ctx.dev_bytenr = dev_bytenr;
1963f382e465SStefan Behrens 		block_ctx.start = bytenr;
1964f382e465SStefan Behrens 		block_ctx.len = processed_len;
1965f382e465SStefan Behrens 		block_ctx.pagev = NULL;
1966f382e465SStefan Behrens 		block_ctx.mem_to_free = NULL;
1967f382e465SStefan Behrens 		block_ctx.datav = mapped_datav;
19685db02760SStefan Behrens 
19695db02760SStefan Behrens 		block = btrfsic_block_alloc();
19705db02760SStefan Behrens 		if (NULL == block) {
19715db02760SStefan Behrens 			btrfsic_release_block_ctx(&block_ctx);
1972e06baab4SStefan Behrens 			goto continue_loop;
19735db02760SStefan Behrens 		}
19745db02760SStefan Behrens 		block->dev_state = dev_state;
19755db02760SStefan Behrens 		block->dev_bytenr = dev_bytenr;
19765db02760SStefan Behrens 		block->logical_bytenr = bytenr;
19775db02760SStefan Behrens 		block->is_metadata = is_metadata;
19785db02760SStefan Behrens 		block->never_written = 0;
19795db02760SStefan Behrens 		block->iodone_w_error = 0;
19805db02760SStefan Behrens 		block->mirror_num = 0;	/* unknown */
19815db02760SStefan Behrens 		block->flush_gen = dev_state->last_flush_gen + 1;
19825db02760SStefan Behrens 		block->submit_bio_bh_rw = submit_bio_bh_rw;
19835db02760SStefan Behrens 		if (NULL != bio) {
19845db02760SStefan Behrens 			block->is_iodone = 0;
19855db02760SStefan Behrens 			BUG_ON(NULL == bio_is_patched);
19865db02760SStefan Behrens 			if (!*bio_is_patched) {
198759aaad50SJohannes Thumshirn 				block->orig_bio_private = bio->bi_private;
198859aaad50SJohannes Thumshirn 				block->orig_bio_end_io = bio->bi_end_io;
19895db02760SStefan Behrens 				block->next_in_same_bio = NULL;
19905db02760SStefan Behrens 				bio->bi_private = block;
19915db02760SStefan Behrens 				bio->bi_end_io = btrfsic_bio_end_io;
19925db02760SStefan Behrens 				*bio_is_patched = 1;
19935db02760SStefan Behrens 			} else {
19945db02760SStefan Behrens 				struct btrfsic_block *chained_block =
19955db02760SStefan Behrens 				    (struct btrfsic_block *)
19965db02760SStefan Behrens 				    bio->bi_private;
19975db02760SStefan Behrens 
19985db02760SStefan Behrens 				BUG_ON(NULL == chained_block);
199959aaad50SJohannes Thumshirn 				block->orig_bio_private =
200059aaad50SJohannes Thumshirn 				    chained_block->orig_bio_private;
200159aaad50SJohannes Thumshirn 				block->orig_bio_end_io =
200259aaad50SJohannes Thumshirn 				    chained_block->orig_bio_end_io;
20035db02760SStefan Behrens 				block->next_in_same_bio = chained_block;
20045db02760SStefan Behrens 				bio->bi_private = block;
20055db02760SStefan Behrens 			}
20065db02760SStefan Behrens 		} else {
20075db02760SStefan Behrens 			block->is_iodone = 1;
200859aaad50SJohannes Thumshirn 			block->orig_bio_private = NULL;
200959aaad50SJohannes Thumshirn 			block->orig_bio_end_io = NULL;
20105db02760SStefan Behrens 			block->next_in_same_bio = NULL;
20115db02760SStefan Behrens 		}
20125db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
2013813ebc16SChristoph Hellwig 			pr_info("new written %c-block @%llu (%pg/%llu/%d)\n",
20145db02760SStefan Behrens 			       is_metadata ? 'M' : 'D',
2015813ebc16SChristoph Hellwig 			       block->logical_bytenr, block->dev_state->bdev,
2016c1c9ff7cSGeert Uytterhoeven 			       block->dev_bytenr, block->mirror_num);
20175db02760SStefan Behrens 		list_add(&block->all_blocks_node, &state->all_blocks_list);
20185db02760SStefan Behrens 		btrfsic_block_hashtable_add(block, &state->block_hashtable);
20195db02760SStefan Behrens 
20205db02760SStefan Behrens 		if (is_metadata) {
20215db02760SStefan Behrens 			ret = btrfsic_process_metablock(state, block,
2022e06baab4SStefan Behrens 							&block_ctx, 0, 0);
20235db02760SStefan Behrens 			if (ret)
202462e85577SJeff Mahoney 				pr_info("btrfsic: process_metablock(root @%llu) failed!\n",
2025c1c9ff7cSGeert Uytterhoeven 				       dev_bytenr);
20265db02760SStefan Behrens 		}
20275db02760SStefan Behrens 		btrfsic_release_block_ctx(&block_ctx);
20285db02760SStefan Behrens 	}
2029e06baab4SStefan Behrens 
2030e06baab4SStefan Behrens continue_loop:
2031e06baab4SStefan Behrens 	BUG_ON(!processed_len);
2032e06baab4SStefan Behrens 	dev_bytenr += processed_len;
203309cbfeafSKirill A. Shutemov 	mapped_datav += processed_len >> PAGE_SHIFT;
203409cbfeafSKirill A. Shutemov 	num_pages -= processed_len >> PAGE_SHIFT;
2035e06baab4SStefan Behrens 	goto again;
20365db02760SStefan Behrens }
20375db02760SStefan Behrens 
btrfsic_bio_end_io(struct bio * bp)20384246a0b6SChristoph Hellwig static void btrfsic_bio_end_io(struct bio *bp)
20395db02760SStefan Behrens {
20400d031dc4SYu Zhe 	struct btrfsic_block *block = bp->bi_private;
20415db02760SStefan Behrens 	int iodone_w_error;
20425db02760SStefan Behrens 
20435db02760SStefan Behrens 	/* mutex is not held! This is not save if IO is not yet completed
20445db02760SStefan Behrens 	 * on umount */
20455db02760SStefan Behrens 	iodone_w_error = 0;
20464e4cbee9SChristoph Hellwig 	if (bp->bi_status)
20475db02760SStefan Behrens 		iodone_w_error = 1;
20485db02760SStefan Behrens 
20495db02760SStefan Behrens 	BUG_ON(NULL == block);
205059aaad50SJohannes Thumshirn 	bp->bi_private = block->orig_bio_private;
205159aaad50SJohannes Thumshirn 	bp->bi_end_io = block->orig_bio_end_io;
20525db02760SStefan Behrens 
20535db02760SStefan Behrens 	do {
20545db02760SStefan Behrens 		struct btrfsic_block *next_block;
20555db02760SStefan Behrens 		struct btrfsic_dev_state *const dev_state = block->dev_state;
20565db02760SStefan Behrens 
20575db02760SStefan Behrens 		if ((dev_state->state->print_mask &
20585db02760SStefan Behrens 		     BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
2059813ebc16SChristoph Hellwig 			pr_info("bio_end_io(err=%d) for %c @%llu (%pg/%llu/%d)\n",
20604e4cbee9SChristoph Hellwig 			       bp->bi_status,
20615db02760SStefan Behrens 			       btrfsic_get_block_type(dev_state->state, block),
2062813ebc16SChristoph Hellwig 			       block->logical_bytenr, dev_state->bdev,
2063c1c9ff7cSGeert Uytterhoeven 			       block->dev_bytenr, block->mirror_num);
20645db02760SStefan Behrens 		next_block = block->next_in_same_bio;
20655db02760SStefan Behrens 		block->iodone_w_error = iodone_w_error;
206628a8f0d3SMike Christie 		if (block->submit_bio_bh_rw & REQ_PREFLUSH) {
20675db02760SStefan Behrens 			dev_state->last_flush_gen++;
20685db02760SStefan Behrens 			if ((dev_state->state->print_mask &
20695db02760SStefan Behrens 			     BTRFSIC_PRINT_MASK_END_IO_BIO_BH))
2070813ebc16SChristoph Hellwig 				pr_info("bio_end_io() new %pg flush_gen=%llu\n",
2071813ebc16SChristoph Hellwig 				       dev_state->bdev,
20725db02760SStefan Behrens 				       dev_state->last_flush_gen);
20735db02760SStefan Behrens 		}
20745db02760SStefan Behrens 		if (block->submit_bio_bh_rw & REQ_FUA)
20755db02760SStefan Behrens 			block->flush_gen = 0; /* FUA completed means block is
20765db02760SStefan Behrens 					       * on disk */
20775db02760SStefan Behrens 		block->is_iodone = 1; /* for FLUSH, this releases the block */
20785db02760SStefan Behrens 		block = next_block;
20795db02760SStefan Behrens 	} while (NULL != block);
20805db02760SStefan Behrens 
20814246a0b6SChristoph Hellwig 	bp->bi_end_io(bp);
20825db02760SStefan Behrens }
20835db02760SStefan Behrens 
btrfsic_process_written_superblock(struct btrfsic_state * state,struct btrfsic_block * const superblock,struct btrfs_super_block * const super_hdr)20845db02760SStefan Behrens static int btrfsic_process_written_superblock(
20855db02760SStefan Behrens 		struct btrfsic_state *state,
20865db02760SStefan Behrens 		struct btrfsic_block *const superblock,
20875db02760SStefan Behrens 		struct btrfs_super_block *const super_hdr)
20885db02760SStefan Behrens {
20890b246afaSJeff Mahoney 	struct btrfs_fs_info *fs_info = state->fs_info;
20905db02760SStefan Behrens 	int pass;
20915db02760SStefan Behrens 
20925db02760SStefan Behrens 	superblock->generation = btrfs_super_generation(super_hdr);
20935db02760SStefan Behrens 	if (!(superblock->generation > state->max_superblock_generation ||
20945db02760SStefan Behrens 	      0 == state->max_superblock_generation)) {
20955db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
2096813ebc16SChristoph Hellwig 			pr_info(
2097813ebc16SChristoph Hellwig 	"btrfsic: superblock @%llu (%pg/%llu/%d) with old gen %llu <= %llu\n",
2098c1c9ff7cSGeert Uytterhoeven 			       superblock->logical_bytenr,
2099813ebc16SChristoph Hellwig 			       superblock->dev_state->bdev,
2100c1c9ff7cSGeert Uytterhoeven 			       superblock->dev_bytenr, superblock->mirror_num,
21015db02760SStefan Behrens 			       btrfs_super_generation(super_hdr),
21025db02760SStefan Behrens 			       state->max_superblock_generation);
21035db02760SStefan Behrens 	} else {
21045db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
2105813ebc16SChristoph Hellwig 			pr_info(
2106813ebc16SChristoph Hellwig 	"btrfsic: got new superblock @%llu (%pg/%llu/%d) with new gen %llu > %llu\n",
2107c1c9ff7cSGeert Uytterhoeven 			       superblock->logical_bytenr,
2108813ebc16SChristoph Hellwig 			       superblock->dev_state->bdev,
2109c1c9ff7cSGeert Uytterhoeven 			       superblock->dev_bytenr, superblock->mirror_num,
21105db02760SStefan Behrens 			       btrfs_super_generation(super_hdr),
21115db02760SStefan Behrens 			       state->max_superblock_generation);
21125db02760SStefan Behrens 
21135db02760SStefan Behrens 		state->max_superblock_generation =
21145db02760SStefan Behrens 		    btrfs_super_generation(super_hdr);
21155db02760SStefan Behrens 		state->latest_superblock = superblock;
21165db02760SStefan Behrens 	}
21175db02760SStefan Behrens 
21185db02760SStefan Behrens 	for (pass = 0; pass < 3; pass++) {
21195db02760SStefan Behrens 		int ret;
21205db02760SStefan Behrens 		u64 next_bytenr;
21215db02760SStefan Behrens 		struct btrfsic_block *next_block;
21225db02760SStefan Behrens 		struct btrfsic_block_data_ctx tmp_next_block_ctx;
21235db02760SStefan Behrens 		struct btrfsic_block_link *l;
21245db02760SStefan Behrens 		int num_copies;
21255db02760SStefan Behrens 		int mirror_num;
21265db02760SStefan Behrens 		const char *additional_string = NULL;
212735a3621bSStefan Behrens 		struct btrfs_disk_key tmp_disk_key = {0};
21285db02760SStefan Behrens 
21293cae210fSQu Wenruo 		btrfs_set_disk_key_objectid(&tmp_disk_key,
21303cae210fSQu Wenruo 					    BTRFS_ROOT_ITEM_KEY);
21313cae210fSQu Wenruo 		btrfs_set_disk_key_objectid(&tmp_disk_key, 0);
21325db02760SStefan Behrens 
21335db02760SStefan Behrens 		switch (pass) {
21345db02760SStefan Behrens 		case 0:
21353cae210fSQu Wenruo 			btrfs_set_disk_key_objectid(&tmp_disk_key,
21363cae210fSQu Wenruo 						    BTRFS_ROOT_TREE_OBJECTID);
21375db02760SStefan Behrens 			additional_string = "root ";
21385db02760SStefan Behrens 			next_bytenr = btrfs_super_root(super_hdr);
21395db02760SStefan Behrens 			if (state->print_mask &
21405db02760SStefan Behrens 			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
214162e85577SJeff Mahoney 				pr_info("root@%llu\n", next_bytenr);
21425db02760SStefan Behrens 			break;
21435db02760SStefan Behrens 		case 1:
21443cae210fSQu Wenruo 			btrfs_set_disk_key_objectid(&tmp_disk_key,
21453cae210fSQu Wenruo 						    BTRFS_CHUNK_TREE_OBJECTID);
21465db02760SStefan Behrens 			additional_string = "chunk ";
21475db02760SStefan Behrens 			next_bytenr = btrfs_super_chunk_root(super_hdr);
21485db02760SStefan Behrens 			if (state->print_mask &
21495db02760SStefan Behrens 			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
215062e85577SJeff Mahoney 				pr_info("chunk@%llu\n", next_bytenr);
21515db02760SStefan Behrens 			break;
21525db02760SStefan Behrens 		case 2:
21533cae210fSQu Wenruo 			btrfs_set_disk_key_objectid(&tmp_disk_key,
21543cae210fSQu Wenruo 						    BTRFS_TREE_LOG_OBJECTID);
21555db02760SStefan Behrens 			additional_string = "log ";
21565db02760SStefan Behrens 			next_bytenr = btrfs_super_log_root(super_hdr);
21575db02760SStefan Behrens 			if (0 == next_bytenr)
21585db02760SStefan Behrens 				continue;
21595db02760SStefan Behrens 			if (state->print_mask &
21605db02760SStefan Behrens 			    BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION)
216162e85577SJeff Mahoney 				pr_info("log@%llu\n", next_bytenr);
21625db02760SStefan Behrens 			break;
21635db02760SStefan Behrens 		}
21645db02760SStefan Behrens 
21650b246afaSJeff Mahoney 		num_copies = btrfs_num_copies(fs_info, next_bytenr,
21660b246afaSJeff Mahoney 					      BTRFS_SUPER_INFO_SIZE);
21675db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES)
216862e85577SJeff Mahoney 			pr_info("num_copies(log_bytenr=%llu) = %d\n",
2169c1c9ff7cSGeert Uytterhoeven 			       next_bytenr, num_copies);
21705db02760SStefan Behrens 		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
21715db02760SStefan Behrens 			int was_created;
21725db02760SStefan Behrens 
21735db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
217462e85577SJeff Mahoney 				pr_info("btrfsic_process_written_superblock(mirror_num=%d)\n", mirror_num);
2175e06baab4SStefan Behrens 			ret = btrfsic_map_block(state, next_bytenr,
2176e06baab4SStefan Behrens 						BTRFS_SUPER_INFO_SIZE,
21775db02760SStefan Behrens 						&tmp_next_block_ctx,
21785db02760SStefan Behrens 						mirror_num);
21795db02760SStefan Behrens 			if (ret) {
218062e85577SJeff Mahoney 				pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n",
2181c1c9ff7cSGeert Uytterhoeven 				       next_bytenr, mirror_num);
21825db02760SStefan Behrens 				return -1;
21835db02760SStefan Behrens 			}
21845db02760SStefan Behrens 
21855db02760SStefan Behrens 			next_block = btrfsic_block_lookup_or_add(
21865db02760SStefan Behrens 					state,
21875db02760SStefan Behrens 					&tmp_next_block_ctx,
21885db02760SStefan Behrens 					additional_string,
21895db02760SStefan Behrens 					1, 0, 1,
21905db02760SStefan Behrens 					mirror_num,
21915db02760SStefan Behrens 					&was_created);
21925db02760SStefan Behrens 			if (NULL == next_block) {
21935db02760SStefan Behrens 				btrfsic_release_block_ctx(&tmp_next_block_ctx);
21945db02760SStefan Behrens 				return -1;
21955db02760SStefan Behrens 			}
21965db02760SStefan Behrens 
21975db02760SStefan Behrens 			next_block->disk_key = tmp_disk_key;
21985db02760SStefan Behrens 			if (was_created)
21995db02760SStefan Behrens 				next_block->generation =
22005db02760SStefan Behrens 				    BTRFSIC_GENERATION_UNKNOWN;
22015db02760SStefan Behrens 			l = btrfsic_block_link_lookup_or_add(
22025db02760SStefan Behrens 					state,
22035db02760SStefan Behrens 					&tmp_next_block_ctx,
22045db02760SStefan Behrens 					next_block,
22055db02760SStefan Behrens 					superblock,
22065db02760SStefan Behrens 					BTRFSIC_GENERATION_UNKNOWN);
22075db02760SStefan Behrens 			btrfsic_release_block_ctx(&tmp_next_block_ctx);
22085db02760SStefan Behrens 			if (NULL == l)
22095db02760SStefan Behrens 				return -1;
22105db02760SStefan Behrens 		}
22115db02760SStefan Behrens 	}
22125db02760SStefan Behrens 
2213fae7f21cSDulshani Gunawardhana 	if (WARN_ON(-1 == btrfsic_check_all_ref_blocks(state, superblock, 0)))
22145db02760SStefan Behrens 		btrfsic_dump_tree(state);
22155db02760SStefan Behrens 
22165db02760SStefan Behrens 	return 0;
22175db02760SStefan Behrens }
22185db02760SStefan Behrens 
btrfsic_check_all_ref_blocks(struct btrfsic_state * state,struct btrfsic_block * const block,int recursion_level)22195db02760SStefan Behrens static int btrfsic_check_all_ref_blocks(struct btrfsic_state *state,
22205db02760SStefan Behrens 					struct btrfsic_block *const block,
22215db02760SStefan Behrens 					int recursion_level)
22225db02760SStefan Behrens {
2223b69f2befSGeliang Tang 	const struct btrfsic_block_link *l;
22245db02760SStefan Behrens 	int ret = 0;
22255db02760SStefan Behrens 
22265db02760SStefan Behrens 	if (recursion_level >= 3 + BTRFS_MAX_LEVEL) {
22275db02760SStefan Behrens 		/*
22285db02760SStefan Behrens 		 * Note that this situation can happen and does not
22295db02760SStefan Behrens 		 * indicate an error in regular cases. It happens
22305db02760SStefan Behrens 		 * when disk blocks are freed and later reused.
22315db02760SStefan Behrens 		 * The check-integrity module is not aware of any
22325db02760SStefan Behrens 		 * block free operations, it just recognizes block
22335db02760SStefan Behrens 		 * write operations. Therefore it keeps the linkage
22345db02760SStefan Behrens 		 * information for a block until a block is
22355db02760SStefan Behrens 		 * rewritten. This can temporarily cause incorrect
223652042d8eSAndrea Gelmini 		 * and even circular linkage information. This
22375db02760SStefan Behrens 		 * causes no harm unless such blocks are referenced
22385db02760SStefan Behrens 		 * by the most recent super block.
22395db02760SStefan Behrens 		 */
22405db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
224162e85577SJeff Mahoney 			pr_info("btrfsic: abort cyclic linkage (case 1).\n");
22425db02760SStefan Behrens 
22435db02760SStefan Behrens 		return ret;
22445db02760SStefan Behrens 	}
22455db02760SStefan Behrens 
22465db02760SStefan Behrens 	/*
22475db02760SStefan Behrens 	 * This algorithm is recursive because the amount of used stack
22485db02760SStefan Behrens 	 * space is very small and the max recursion depth is limited.
22495db02760SStefan Behrens 	 */
2250b69f2befSGeliang Tang 	list_for_each_entry(l, &block->ref_to_list, node_ref_to) {
22515db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
2252813ebc16SChristoph Hellwig 			pr_info(
2253813ebc16SChristoph Hellwig 		"rl=%d, %c @%llu (%pg/%llu/%d) %u* refers to %c @%llu (%pg/%llu/%d)\n",
22545db02760SStefan Behrens 			       recursion_level,
22555db02760SStefan Behrens 			       btrfsic_get_block_type(state, block),
2256813ebc16SChristoph Hellwig 			       block->logical_bytenr, block->dev_state->bdev,
2257c1c9ff7cSGeert Uytterhoeven 			       block->dev_bytenr, block->mirror_num,
22585db02760SStefan Behrens 			       l->ref_cnt,
22595db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_to),
22605db02760SStefan Behrens 			       l->block_ref_to->logical_bytenr,
2261813ebc16SChristoph Hellwig 			       l->block_ref_to->dev_state->bdev,
2262c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->dev_bytenr,
22635db02760SStefan Behrens 			       l->block_ref_to->mirror_num);
22645db02760SStefan Behrens 		if (l->block_ref_to->never_written) {
2265813ebc16SChristoph Hellwig 			pr_info(
2266813ebc16SChristoph Hellwig "btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) which is never written!\n",
22675db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_to),
22685db02760SStefan Behrens 			       l->block_ref_to->logical_bytenr,
2269813ebc16SChristoph Hellwig 			       l->block_ref_to->dev_state->bdev,
2270c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->dev_bytenr,
22715db02760SStefan Behrens 			       l->block_ref_to->mirror_num);
22725db02760SStefan Behrens 			ret = -1;
22735db02760SStefan Behrens 		} else if (!l->block_ref_to->is_iodone) {
2274813ebc16SChristoph Hellwig 			pr_info(
2275813ebc16SChristoph Hellwig "btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) which is not yet iodone!\n",
22765db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_to),
22775db02760SStefan Behrens 			       l->block_ref_to->logical_bytenr,
2278813ebc16SChristoph Hellwig 			       l->block_ref_to->dev_state->bdev,
2279c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->dev_bytenr,
22805db02760SStefan Behrens 			       l->block_ref_to->mirror_num);
22815db02760SStefan Behrens 			ret = -1;
228262856a9bSStefan Behrens 		} else if (l->block_ref_to->iodone_w_error) {
2283813ebc16SChristoph Hellwig 			pr_info(
2284813ebc16SChristoph Hellwig "btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) which has write error!\n",
228562856a9bSStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_to),
228662856a9bSStefan Behrens 			       l->block_ref_to->logical_bytenr,
2287813ebc16SChristoph Hellwig 			       l->block_ref_to->dev_state->bdev,
2288c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->dev_bytenr,
228962856a9bSStefan Behrens 			       l->block_ref_to->mirror_num);
229062856a9bSStefan Behrens 			ret = -1;
22915db02760SStefan Behrens 		} else if (l->parent_generation !=
22925db02760SStefan Behrens 			   l->block_ref_to->generation &&
22935db02760SStefan Behrens 			   BTRFSIC_GENERATION_UNKNOWN !=
22945db02760SStefan Behrens 			   l->parent_generation &&
22955db02760SStefan Behrens 			   BTRFSIC_GENERATION_UNKNOWN !=
22965db02760SStefan Behrens 			   l->block_ref_to->generation) {
2297813ebc16SChristoph Hellwig 			pr_info(
2298813ebc16SChristoph Hellwig "btrfs: attempt to write superblock which references block %c @%llu (%pg/%llu/%d) with generation %llu != parent generation %llu!\n",
22995db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_to),
23005db02760SStefan Behrens 			       l->block_ref_to->logical_bytenr,
2301813ebc16SChristoph Hellwig 			       l->block_ref_to->dev_state->bdev,
2302c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->dev_bytenr,
23035db02760SStefan Behrens 			       l->block_ref_to->mirror_num,
2304c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->generation,
2305c1c9ff7cSGeert Uytterhoeven 			       l->parent_generation);
23065db02760SStefan Behrens 			ret = -1;
23075db02760SStefan Behrens 		} else if (l->block_ref_to->flush_gen >
23085db02760SStefan Behrens 			   l->block_ref_to->dev_state->last_flush_gen) {
2309813ebc16SChristoph Hellwig 			pr_info(
2310813ebc16SChristoph Hellwig "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",
23115db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_to),
23125db02760SStefan Behrens 			       l->block_ref_to->logical_bytenr,
2313813ebc16SChristoph Hellwig 			       l->block_ref_to->dev_state->bdev,
2314c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->dev_bytenr,
2315c1c9ff7cSGeert Uytterhoeven 			       l->block_ref_to->mirror_num, block->flush_gen,
23165db02760SStefan Behrens 			       l->block_ref_to->dev_state->last_flush_gen);
23175db02760SStefan Behrens 			ret = -1;
23185db02760SStefan Behrens 		} else if (-1 == btrfsic_check_all_ref_blocks(state,
23195db02760SStefan Behrens 							      l->block_ref_to,
23205db02760SStefan Behrens 							      recursion_level +
23215db02760SStefan Behrens 							      1)) {
23225db02760SStefan Behrens 			ret = -1;
23235db02760SStefan Behrens 		}
23245db02760SStefan Behrens 	}
23255db02760SStefan Behrens 
23265db02760SStefan Behrens 	return ret;
23275db02760SStefan Behrens }
23285db02760SStefan Behrens 
btrfsic_is_block_ref_by_superblock(const struct btrfsic_state * state,const struct btrfsic_block * block,int recursion_level)23295db02760SStefan Behrens static int btrfsic_is_block_ref_by_superblock(
23305db02760SStefan Behrens 		const struct btrfsic_state *state,
23315db02760SStefan Behrens 		const struct btrfsic_block *block,
23325db02760SStefan Behrens 		int recursion_level)
23335db02760SStefan Behrens {
2334b69f2befSGeliang Tang 	const struct btrfsic_block_link *l;
23355db02760SStefan Behrens 
23365db02760SStefan Behrens 	if (recursion_level >= 3 + BTRFS_MAX_LEVEL) {
23375db02760SStefan Behrens 		/* refer to comment at "abort cyclic linkage (case 1)" */
23385db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
233962e85577SJeff Mahoney 			pr_info("btrfsic: abort cyclic linkage (case 2).\n");
23405db02760SStefan Behrens 
23415db02760SStefan Behrens 		return 0;
23425db02760SStefan Behrens 	}
23435db02760SStefan Behrens 
23445db02760SStefan Behrens 	/*
23455db02760SStefan Behrens 	 * This algorithm is recursive because the amount of used stack space
23465db02760SStefan Behrens 	 * is very small and the max recursion depth is limited.
23475db02760SStefan Behrens 	 */
2348b69f2befSGeliang Tang 	list_for_each_entry(l, &block->ref_from_list, node_ref_from) {
23495db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
2350813ebc16SChristoph Hellwig 			pr_info(
2351813ebc16SChristoph Hellwig 	"rl=%d, %c @%llu (%pg/%llu/%d) is ref %u* from %c @%llu (%pg/%llu/%d)\n",
23525db02760SStefan Behrens 			       recursion_level,
23535db02760SStefan Behrens 			       btrfsic_get_block_type(state, block),
2354813ebc16SChristoph Hellwig 			       block->logical_bytenr, block->dev_state->bdev,
2355c1c9ff7cSGeert Uytterhoeven 			       block->dev_bytenr, block->mirror_num,
23565db02760SStefan Behrens 			       l->ref_cnt,
23575db02760SStefan Behrens 			       btrfsic_get_block_type(state, l->block_ref_from),
23585db02760SStefan Behrens 			       l->block_ref_from->logical_bytenr,
2359813ebc16SChristoph Hellwig 			       l->block_ref_from->dev_state->bdev,
23605db02760SStefan Behrens 			       l->block_ref_from->dev_bytenr,
23615db02760SStefan Behrens 			       l->block_ref_from->mirror_num);
23625db02760SStefan Behrens 		if (l->block_ref_from->is_superblock &&
23635db02760SStefan Behrens 		    state->latest_superblock->dev_bytenr ==
23645db02760SStefan Behrens 		    l->block_ref_from->dev_bytenr &&
23655db02760SStefan Behrens 		    state->latest_superblock->dev_state->bdev ==
23665db02760SStefan Behrens 		    l->block_ref_from->dev_state->bdev)
23675db02760SStefan Behrens 			return 1;
23685db02760SStefan Behrens 		else if (btrfsic_is_block_ref_by_superblock(state,
23695db02760SStefan Behrens 							    l->block_ref_from,
23705db02760SStefan Behrens 							    recursion_level +
23715db02760SStefan Behrens 							    1))
23725db02760SStefan Behrens 			return 1;
23735db02760SStefan Behrens 	}
23745db02760SStefan Behrens 
23755db02760SStefan Behrens 	return 0;
23765db02760SStefan Behrens }
23775db02760SStefan Behrens 
btrfsic_print_add_link(const struct btrfsic_state * state,const struct btrfsic_block_link * l)23785db02760SStefan Behrens static void btrfsic_print_add_link(const struct btrfsic_state *state,
23795db02760SStefan Behrens 				   const struct btrfsic_block_link *l)
23805db02760SStefan Behrens {
2381813ebc16SChristoph Hellwig 	pr_info("add %u* link from %c @%llu (%pg/%llu/%d) to %c @%llu (%pg/%llu/%d)\n",
23825db02760SStefan Behrens 	       l->ref_cnt,
23835db02760SStefan Behrens 	       btrfsic_get_block_type(state, l->block_ref_from),
2384c1c9ff7cSGeert Uytterhoeven 	       l->block_ref_from->logical_bytenr,
2385813ebc16SChristoph Hellwig 	       l->block_ref_from->dev_state->bdev,
2386c1c9ff7cSGeert Uytterhoeven 	       l->block_ref_from->dev_bytenr, l->block_ref_from->mirror_num,
23875db02760SStefan Behrens 	       btrfsic_get_block_type(state, l->block_ref_to),
2388c1c9ff7cSGeert Uytterhoeven 	       l->block_ref_to->logical_bytenr,
2389813ebc16SChristoph Hellwig 	       l->block_ref_to->dev_state->bdev, l->block_ref_to->dev_bytenr,
23905db02760SStefan Behrens 	       l->block_ref_to->mirror_num);
23915db02760SStefan Behrens }
23925db02760SStefan Behrens 
btrfsic_print_rem_link(const struct btrfsic_state * state,const struct btrfsic_block_link * l)23935db02760SStefan Behrens static void btrfsic_print_rem_link(const struct btrfsic_state *state,
23945db02760SStefan Behrens 				   const struct btrfsic_block_link *l)
23955db02760SStefan Behrens {
2396813ebc16SChristoph Hellwig 	pr_info("rem %u* link from %c @%llu (%pg/%llu/%d) to %c @%llu (%pg/%llu/%d)\n",
23975db02760SStefan Behrens 	       l->ref_cnt,
23985db02760SStefan Behrens 	       btrfsic_get_block_type(state, l->block_ref_from),
2399c1c9ff7cSGeert Uytterhoeven 	       l->block_ref_from->logical_bytenr,
2400813ebc16SChristoph Hellwig 	       l->block_ref_from->dev_state->bdev,
2401c1c9ff7cSGeert Uytterhoeven 	       l->block_ref_from->dev_bytenr, l->block_ref_from->mirror_num,
24025db02760SStefan Behrens 	       btrfsic_get_block_type(state, l->block_ref_to),
2403c1c9ff7cSGeert Uytterhoeven 	       l->block_ref_to->logical_bytenr,
2404813ebc16SChristoph Hellwig 	       l->block_ref_to->dev_state->bdev, l->block_ref_to->dev_bytenr,
24055db02760SStefan Behrens 	       l->block_ref_to->mirror_num);
24065db02760SStefan Behrens }
24075db02760SStefan Behrens 
btrfsic_get_block_type(const struct btrfsic_state * state,const struct btrfsic_block * block)24085db02760SStefan Behrens static char btrfsic_get_block_type(const struct btrfsic_state *state,
24095db02760SStefan Behrens 				   const struct btrfsic_block *block)
24105db02760SStefan Behrens {
24115db02760SStefan Behrens 	if (block->is_superblock &&
24125db02760SStefan Behrens 	    state->latest_superblock->dev_bytenr == block->dev_bytenr &&
24135db02760SStefan Behrens 	    state->latest_superblock->dev_state->bdev == block->dev_state->bdev)
24145db02760SStefan Behrens 		return 'S';
24155db02760SStefan Behrens 	else if (block->is_superblock)
24165db02760SStefan Behrens 		return 's';
24175db02760SStefan Behrens 	else if (block->is_metadata)
24185db02760SStefan Behrens 		return 'M';
24195db02760SStefan Behrens 	else
24205db02760SStefan Behrens 		return 'D';
24215db02760SStefan Behrens }
24225db02760SStefan Behrens 
btrfsic_dump_tree(const struct btrfsic_state * state)24235db02760SStefan Behrens static void btrfsic_dump_tree(const struct btrfsic_state *state)
24245db02760SStefan Behrens {
24255db02760SStefan Behrens 	btrfsic_dump_tree_sub(state, state->latest_superblock, 0);
24265db02760SStefan Behrens }
24275db02760SStefan Behrens 
btrfsic_dump_tree_sub(const struct btrfsic_state * state,const struct btrfsic_block * block,int indent_level)24285db02760SStefan Behrens static void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
24295db02760SStefan Behrens 				  const struct btrfsic_block *block,
24305db02760SStefan Behrens 				  int indent_level)
24315db02760SStefan Behrens {
2432b69f2befSGeliang Tang 	const struct btrfsic_block_link *l;
24335db02760SStefan Behrens 	int indent_add;
24345db02760SStefan Behrens 	static char buf[80];
24355db02760SStefan Behrens 	int cursor_position;
24365db02760SStefan Behrens 
24375db02760SStefan Behrens 	/*
24385db02760SStefan Behrens 	 * Should better fill an on-stack buffer with a complete line and
24395db02760SStefan Behrens 	 * dump it at once when it is time to print a newline character.
24405db02760SStefan Behrens 	 */
24415db02760SStefan Behrens 
24425db02760SStefan Behrens 	/*
24435db02760SStefan Behrens 	 * This algorithm is recursive because the amount of used stack space
24445db02760SStefan Behrens 	 * is very small and the max recursion depth is limited.
24455db02760SStefan Behrens 	 */
2446813ebc16SChristoph Hellwig 	indent_add = sprintf(buf, "%c-%llu(%pg/%llu/%u)",
24475db02760SStefan Behrens 			     btrfsic_get_block_type(state, block),
2448813ebc16SChristoph Hellwig 			     block->logical_bytenr, block->dev_state->bdev,
2449c1c9ff7cSGeert Uytterhoeven 			     block->dev_bytenr, block->mirror_num);
24505db02760SStefan Behrens 	if (indent_level + indent_add > BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) {
24515db02760SStefan Behrens 		printk("[...]\n");
24525db02760SStefan Behrens 		return;
24535db02760SStefan Behrens 	}
24545db02760SStefan Behrens 	printk(buf);
24555db02760SStefan Behrens 	indent_level += indent_add;
24565db02760SStefan Behrens 	if (list_empty(&block->ref_to_list)) {
24575db02760SStefan Behrens 		printk("\n");
24585db02760SStefan Behrens 		return;
24595db02760SStefan Behrens 	}
24605db02760SStefan Behrens 	if (block->mirror_num > 1 &&
24615db02760SStefan Behrens 	    !(state->print_mask & BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS)) {
24625db02760SStefan Behrens 		printk(" [...]\n");
24635db02760SStefan Behrens 		return;
24645db02760SStefan Behrens 	}
24655db02760SStefan Behrens 
24665db02760SStefan Behrens 	cursor_position = indent_level;
2467b69f2befSGeliang Tang 	list_for_each_entry(l, &block->ref_to_list, node_ref_to) {
24685db02760SStefan Behrens 		while (cursor_position < indent_level) {
24695db02760SStefan Behrens 			printk(" ");
24705db02760SStefan Behrens 			cursor_position++;
24715db02760SStefan Behrens 		}
24725db02760SStefan Behrens 		if (l->ref_cnt > 1)
24735db02760SStefan Behrens 			indent_add = sprintf(buf, " %d*--> ", l->ref_cnt);
24745db02760SStefan Behrens 		else
24755db02760SStefan Behrens 			indent_add = sprintf(buf, " --> ");
24765db02760SStefan Behrens 		if (indent_level + indent_add >
24775db02760SStefan Behrens 		    BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) {
24785db02760SStefan Behrens 			printk("[...]\n");
24795db02760SStefan Behrens 			cursor_position = 0;
24805db02760SStefan Behrens 			continue;
24815db02760SStefan Behrens 		}
24825db02760SStefan Behrens 
24835db02760SStefan Behrens 		printk(buf);
24845db02760SStefan Behrens 
24855db02760SStefan Behrens 		btrfsic_dump_tree_sub(state, l->block_ref_to,
24865db02760SStefan Behrens 				      indent_level + indent_add);
24875db02760SStefan Behrens 		cursor_position = 0;
24885db02760SStefan Behrens 	}
24895db02760SStefan Behrens }
24905db02760SStefan Behrens 
btrfsic_block_link_lookup_or_add(struct btrfsic_state * state,struct btrfsic_block_data_ctx * next_block_ctx,struct btrfsic_block * next_block,struct btrfsic_block * from_block,u64 parent_generation)24915db02760SStefan Behrens static struct btrfsic_block_link *btrfsic_block_link_lookup_or_add(
24925db02760SStefan Behrens 		struct btrfsic_state *state,
24935db02760SStefan Behrens 		struct btrfsic_block_data_ctx *next_block_ctx,
24945db02760SStefan Behrens 		struct btrfsic_block *next_block,
24955db02760SStefan Behrens 		struct btrfsic_block *from_block,
24965db02760SStefan Behrens 		u64 parent_generation)
24975db02760SStefan Behrens {
24985db02760SStefan Behrens 	struct btrfsic_block_link *l;
24995db02760SStefan Behrens 
25005db02760SStefan Behrens 	l = btrfsic_block_link_hashtable_lookup(next_block_ctx->dev->bdev,
25015db02760SStefan Behrens 						next_block_ctx->dev_bytenr,
25025db02760SStefan Behrens 						from_block->dev_state->bdev,
25035db02760SStefan Behrens 						from_block->dev_bytenr,
25045db02760SStefan Behrens 						&state->block_link_hashtable);
25055db02760SStefan Behrens 	if (NULL == l) {
25065db02760SStefan Behrens 		l = btrfsic_block_link_alloc();
2507ab483009SLiao Pingfang 		if (!l)
25085db02760SStefan Behrens 			return NULL;
25095db02760SStefan Behrens 
25105db02760SStefan Behrens 		l->block_ref_to = next_block;
25115db02760SStefan Behrens 		l->block_ref_from = from_block;
25125db02760SStefan Behrens 		l->ref_cnt = 1;
25135db02760SStefan Behrens 		l->parent_generation = parent_generation;
25145db02760SStefan Behrens 
25155db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
25165db02760SStefan Behrens 			btrfsic_print_add_link(state, l);
25175db02760SStefan Behrens 
25185db02760SStefan Behrens 		list_add(&l->node_ref_to, &from_block->ref_to_list);
25195db02760SStefan Behrens 		list_add(&l->node_ref_from, &next_block->ref_from_list);
25205db02760SStefan Behrens 
25215db02760SStefan Behrens 		btrfsic_block_link_hashtable_add(l,
25225db02760SStefan Behrens 						 &state->block_link_hashtable);
25235db02760SStefan Behrens 	} else {
25245db02760SStefan Behrens 		l->ref_cnt++;
25255db02760SStefan Behrens 		l->parent_generation = parent_generation;
25265db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
25275db02760SStefan Behrens 			btrfsic_print_add_link(state, l);
25285db02760SStefan Behrens 	}
25295db02760SStefan Behrens 
25305db02760SStefan Behrens 	return l;
25315db02760SStefan Behrens }
25325db02760SStefan Behrens 
btrfsic_block_lookup_or_add(struct btrfsic_state * state,struct btrfsic_block_data_ctx * block_ctx,const char * additional_string,int is_metadata,int is_iodone,int never_written,int mirror_num,int * was_created)25335db02760SStefan Behrens static struct btrfsic_block *btrfsic_block_lookup_or_add(
25345db02760SStefan Behrens 		struct btrfsic_state *state,
25355db02760SStefan Behrens 		struct btrfsic_block_data_ctx *block_ctx,
25365db02760SStefan Behrens 		const char *additional_string,
25375db02760SStefan Behrens 		int is_metadata,
25385db02760SStefan Behrens 		int is_iodone,
25395db02760SStefan Behrens 		int never_written,
25405db02760SStefan Behrens 		int mirror_num,
25415db02760SStefan Behrens 		int *was_created)
25425db02760SStefan Behrens {
25435db02760SStefan Behrens 	struct btrfsic_block *block;
25445db02760SStefan Behrens 
25455db02760SStefan Behrens 	block = btrfsic_block_hashtable_lookup(block_ctx->dev->bdev,
25465db02760SStefan Behrens 					       block_ctx->dev_bytenr,
25475db02760SStefan Behrens 					       &state->block_hashtable);
25485db02760SStefan Behrens 	if (NULL == block) {
25495db02760SStefan Behrens 		struct btrfsic_dev_state *dev_state;
25505db02760SStefan Behrens 
25515db02760SStefan Behrens 		block = btrfsic_block_alloc();
2552ab483009SLiao Pingfang 		if (!block)
25535db02760SStefan Behrens 			return NULL;
2554ab483009SLiao Pingfang 
2555f8f84b2dSChristoph Hellwig 		dev_state = btrfsic_dev_state_lookup(block_ctx->dev->bdev->bd_dev);
25565db02760SStefan Behrens 		if (NULL == dev_state) {
255762e85577SJeff Mahoney 			pr_info("btrfsic: error, lookup dev_state failed!\n");
25585db02760SStefan Behrens 			btrfsic_block_free(block);
25595db02760SStefan Behrens 			return NULL;
25605db02760SStefan Behrens 		}
25615db02760SStefan Behrens 		block->dev_state = dev_state;
25625db02760SStefan Behrens 		block->dev_bytenr = block_ctx->dev_bytenr;
25635db02760SStefan Behrens 		block->logical_bytenr = block_ctx->start;
25645db02760SStefan Behrens 		block->is_metadata = is_metadata;
25655db02760SStefan Behrens 		block->is_iodone = is_iodone;
25665db02760SStefan Behrens 		block->never_written = never_written;
25675db02760SStefan Behrens 		block->mirror_num = mirror_num;
25685db02760SStefan Behrens 		if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
2569813ebc16SChristoph Hellwig 			pr_info("New %s%c-block @%llu (%pg/%llu/%d)\n",
25705db02760SStefan Behrens 			       additional_string,
25715db02760SStefan Behrens 			       btrfsic_get_block_type(state, block),
2572813ebc16SChristoph Hellwig 			       block->logical_bytenr, dev_state->bdev,
2573c1c9ff7cSGeert Uytterhoeven 			       block->dev_bytenr, mirror_num);
25745db02760SStefan Behrens 		list_add(&block->all_blocks_node, &state->all_blocks_list);
25755db02760SStefan Behrens 		btrfsic_block_hashtable_add(block, &state->block_hashtable);
25765db02760SStefan Behrens 		if (NULL != was_created)
25775db02760SStefan Behrens 			*was_created = 1;
25785db02760SStefan Behrens 	} else {
25795db02760SStefan Behrens 		if (NULL != was_created)
25805db02760SStefan Behrens 			*was_created = 0;
25815db02760SStefan Behrens 	}
25825db02760SStefan Behrens 
25835db02760SStefan Behrens 	return block;
25845db02760SStefan Behrens }
25855db02760SStefan Behrens 
btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state * state,u64 bytenr,struct btrfsic_dev_state * dev_state,u64 dev_bytenr)25865db02760SStefan Behrens static void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state,
25875db02760SStefan Behrens 					   u64 bytenr,
25885db02760SStefan Behrens 					   struct btrfsic_dev_state *dev_state,
2589e06baab4SStefan Behrens 					   u64 dev_bytenr)
25905db02760SStefan Behrens {
25910b246afaSJeff Mahoney 	struct btrfs_fs_info *fs_info = state->fs_info;
25920b246afaSJeff Mahoney 	struct btrfsic_block_data_ctx block_ctx;
25935db02760SStefan Behrens 	int num_copies;
25945db02760SStefan Behrens 	int mirror_num;
25955db02760SStefan Behrens 	int match = 0;
25960b246afaSJeff Mahoney 	int ret;
25975db02760SStefan Behrens 
25980b246afaSJeff Mahoney 	num_copies = btrfs_num_copies(fs_info, bytenr, state->metablock_size);
25995db02760SStefan Behrens 
26005db02760SStefan Behrens 	for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
2601e06baab4SStefan Behrens 		ret = btrfsic_map_block(state, bytenr, state->metablock_size,
26025db02760SStefan Behrens 					&block_ctx, mirror_num);
26035db02760SStefan Behrens 		if (ret) {
260462e85577SJeff Mahoney 			pr_info("btrfsic: btrfsic_map_block(logical @%llu, mirror %d) failed!\n",
2605c1c9ff7cSGeert Uytterhoeven 			       bytenr, mirror_num);
26065db02760SStefan Behrens 			continue;
26075db02760SStefan Behrens 		}
26085db02760SStefan Behrens 
26095db02760SStefan Behrens 		if (dev_state->bdev == block_ctx.dev->bdev &&
26105db02760SStefan Behrens 		    dev_bytenr == block_ctx.dev_bytenr) {
26115db02760SStefan Behrens 			match++;
26125db02760SStefan Behrens 			btrfsic_release_block_ctx(&block_ctx);
26135db02760SStefan Behrens 			break;
26145db02760SStefan Behrens 		}
26155db02760SStefan Behrens 		btrfsic_release_block_ctx(&block_ctx);
26165db02760SStefan Behrens 	}
26175db02760SStefan Behrens 
2618fae7f21cSDulshani Gunawardhana 	if (WARN_ON(!match)) {
2619813ebc16SChristoph Hellwig 		pr_info(
2620813ebc16SChristoph Hellwig "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",
2621813ebc16SChristoph Hellwig 		       bytenr, dev_state->bdev, dev_bytenr);
26225db02760SStefan Behrens 		for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) {
2623e06baab4SStefan Behrens 			ret = btrfsic_map_block(state, bytenr,
2624e06baab4SStefan Behrens 						state->metablock_size,
26255db02760SStefan Behrens 						&block_ctx, mirror_num);
26265db02760SStefan Behrens 			if (ret)
26275db02760SStefan Behrens 				continue;
26285db02760SStefan Behrens 
2629813ebc16SChristoph Hellwig 			pr_info("read logical bytenr @%llu maps to (%pg/%llu/%d)\n",
2630813ebc16SChristoph Hellwig 			       bytenr, block_ctx.dev->bdev,
2631c1c9ff7cSGeert Uytterhoeven 			       block_ctx.dev_bytenr, mirror_num);
26325db02760SStefan Behrens 		}
26335db02760SStefan Behrens 	}
26345db02760SStefan Behrens }
26355db02760SStefan Behrens 
btrfsic_dev_state_lookup(dev_t dev)2636f8f84b2dSChristoph Hellwig static struct btrfsic_dev_state *btrfsic_dev_state_lookup(dev_t dev)
26375db02760SStefan Behrens {
2638f8f84b2dSChristoph Hellwig 	return btrfsic_dev_state_hashtable_lookup(dev,
26395db02760SStefan Behrens 						  &btrfsic_dev_state_hashtable);
26405db02760SStefan Behrens }
26415db02760SStefan Behrens 
btrfsic_check_write_bio(struct bio * bio,struct btrfsic_dev_state * dev_state)264257906d58SChristoph Hellwig static void btrfsic_check_write_bio(struct bio *bio, struct btrfsic_dev_state *dev_state)
26435db02760SStefan Behrens {
264411b56165SLiu Bo 	unsigned int segs = bio_segments(bio);
264557906d58SChristoph Hellwig 	u64 dev_bytenr = 512 * bio->bi_iter.bi_sector;
264657906d58SChristoph Hellwig 	u64 cur_bytenr = dev_bytenr;
264757906d58SChristoph Hellwig 	struct bvec_iter iter;
264857906d58SChristoph Hellwig 	struct bio_vec bvec;
264957906d58SChristoph Hellwig 	char **mapped_datav;
265057906d58SChristoph Hellwig 	int bio_is_patched = 0;
265157906d58SChristoph Hellwig 	int i = 0;
26525db02760SStefan Behrens 
265357906d58SChristoph Hellwig 	if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
265457906d58SChristoph Hellwig 		pr_info(
265557906d58SChristoph Hellwig "submit_bio(rw=%d,0x%x, bi_vcnt=%u, bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n",
265611b56165SLiu Bo 		       bio_op(bio), bio->bi_opf, segs,
2657309dca30SChristoph Hellwig 		       bio->bi_iter.bi_sector, dev_bytenr, bio->bi_bdev);
26585db02760SStefan Behrens 
265957906d58SChristoph Hellwig 	mapped_datav = kmalloc_array(segs, sizeof(*mapped_datav), GFP_NOFS);
2660e06baab4SStefan Behrens 	if (!mapped_datav)
266157906d58SChristoph Hellwig 		return;
26621621f8f3SChristoph Hellwig 
266311b56165SLiu Bo 	bio_for_each_segment(bvec, bio, iter) {
266411b56165SLiu Bo 		BUG_ON(bvec.bv_len != PAGE_SIZE);
26655da38479SDavid Sterba 		mapped_datav[i] = page_address(bvec.bv_page);
266611b56165SLiu Bo 		i++;
26671621f8f3SChristoph Hellwig 
266856d140f5SStefan Behrens 		if (dev_state->state->print_mask &
266956d140f5SStefan Behrens 		    BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE)
267062e85577SJeff Mahoney 			pr_info("#%u: bytenr=%llu, len=%u, offset=%u\n",
267111b56165SLiu Bo 			       i, cur_bytenr, bvec.bv_len, bvec.bv_offset);
267211b56165SLiu Bo 		cur_bytenr += bvec.bv_len;
2673e06baab4SStefan Behrens 	}
267457906d58SChristoph Hellwig 
267557906d58SChristoph Hellwig 	btrfsic_process_written_block(dev_state, dev_bytenr, mapped_datav, segs,
267657906d58SChristoph Hellwig 				      bio, &bio_is_patched, bio->bi_opf);
2677e06baab4SStefan Behrens 	kfree(mapped_datav);
267857906d58SChristoph Hellwig }
267957906d58SChristoph Hellwig 
btrfsic_check_flush_bio(struct bio * bio,struct btrfsic_dev_state * dev_state)268057906d58SChristoph Hellwig static void btrfsic_check_flush_bio(struct bio *bio, struct btrfsic_dev_state *dev_state)
268157906d58SChristoph Hellwig {
268257906d58SChristoph Hellwig 	if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
2683309dca30SChristoph Hellwig 		pr_info("submit_bio(rw=%d,0x%x FLUSH, bdev=%p)\n",
2684309dca30SChristoph Hellwig 		       bio_op(bio), bio->bi_opf, bio->bi_bdev);
268557906d58SChristoph Hellwig 
268657906d58SChristoph Hellwig 	if (dev_state->dummy_block_for_bio_bh_flush.is_iodone) {
26875db02760SStefan Behrens 		struct btrfsic_block *const block =
26885db02760SStefan Behrens 			&dev_state->dummy_block_for_bio_bh_flush;
26895db02760SStefan Behrens 
26905db02760SStefan Behrens 		block->is_iodone = 0;
26915db02760SStefan Behrens 		block->never_written = 0;
26925db02760SStefan Behrens 		block->iodone_w_error = 0;
26935db02760SStefan Behrens 		block->flush_gen = dev_state->last_flush_gen + 1;
26941eff9d32SJens Axboe 		block->submit_bio_bh_rw = bio->bi_opf;
269559aaad50SJohannes Thumshirn 		block->orig_bio_private = bio->bi_private;
269659aaad50SJohannes Thumshirn 		block->orig_bio_end_io = bio->bi_end_io;
26975db02760SStefan Behrens 		block->next_in_same_bio = NULL;
26985db02760SStefan Behrens 		bio->bi_private = block;
26995db02760SStefan Behrens 		bio->bi_end_io = btrfsic_bio_end_io;
270057906d58SChristoph Hellwig 	} else if ((dev_state->state->print_mask &
270157906d58SChristoph Hellwig 		   (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
270257906d58SChristoph Hellwig 		    BTRFSIC_PRINT_MASK_VERBOSE))) {
270357906d58SChristoph Hellwig 		pr_info(
270457906d58SChristoph Hellwig "btrfsic_submit_bio(%pg) with FLUSH but dummy block already in use (ignored)!\n",
270557906d58SChristoph Hellwig 		       dev_state->bdev);
27065db02760SStefan Behrens 	}
27075db02760SStefan Behrens }
270857906d58SChristoph Hellwig 
btrfsic_check_bio(struct bio * bio)270958ff51f1SChristoph Hellwig void btrfsic_check_bio(struct bio *bio)
271057906d58SChristoph Hellwig {
271157906d58SChristoph Hellwig 	struct btrfsic_dev_state *dev_state;
271257906d58SChristoph Hellwig 
271357906d58SChristoph Hellwig 	if (!btrfsic_is_initialized)
271457906d58SChristoph Hellwig 		return;
271557906d58SChristoph Hellwig 
271657906d58SChristoph Hellwig 	/*
271757906d58SChristoph Hellwig 	 * We can be called before btrfsic_mount, so there might not be a
271857906d58SChristoph Hellwig 	 * dev_state.
271957906d58SChristoph Hellwig 	 */
272057906d58SChristoph Hellwig 	dev_state = btrfsic_dev_state_lookup(bio->bi_bdev->bd_dev);
272157906d58SChristoph Hellwig 	mutex_lock(&btrfsic_mutex);
272257906d58SChristoph Hellwig 	if (dev_state) {
272357906d58SChristoph Hellwig 		if (bio_op(bio) == REQ_OP_WRITE && bio_has_data(bio))
272457906d58SChristoph Hellwig 			btrfsic_check_write_bio(bio, dev_state);
272557906d58SChristoph Hellwig 		else if (bio->bi_opf & REQ_PREFLUSH)
272657906d58SChristoph Hellwig 			btrfsic_check_flush_bio(bio, dev_state);
272757906d58SChristoph Hellwig 	}
27285db02760SStefan Behrens 	mutex_unlock(&btrfsic_mutex);
272933879d45SKent Overstreet }
27305db02760SStefan Behrens 
btrfsic_mount(struct btrfs_fs_info * fs_info,struct btrfs_fs_devices * fs_devices,int including_extent_data,u32 print_mask)27312ff7e61eSJeff Mahoney int btrfsic_mount(struct btrfs_fs_info *fs_info,
27325db02760SStefan Behrens 		  struct btrfs_fs_devices *fs_devices,
27335db02760SStefan Behrens 		  int including_extent_data, u32 print_mask)
27345db02760SStefan Behrens {
27355db02760SStefan Behrens 	int ret;
27365db02760SStefan Behrens 	struct btrfsic_state *state;
27375db02760SStefan Behrens 	struct list_head *dev_head = &fs_devices->devices;
27385db02760SStefan Behrens 	struct btrfs_device *device;
27395db02760SStefan Behrens 
2740fdb1e121SJohannes Thumshirn 	if (!PAGE_ALIGNED(fs_info->nodesize)) {
274162e85577SJeff Mahoney 		pr_info("btrfsic: cannot handle nodesize %d not being a multiple of PAGE_SIZE %ld!\n",
27420b246afaSJeff Mahoney 		       fs_info->nodesize, PAGE_SIZE);
2743e06baab4SStefan Behrens 		return -1;
2744e06baab4SStefan Behrens 	}
2745fdb1e121SJohannes Thumshirn 	if (!PAGE_ALIGNED(fs_info->sectorsize)) {
274662e85577SJeff Mahoney 		pr_info("btrfsic: cannot handle sectorsize %d not being a multiple of PAGE_SIZE %ld!\n",
27470b246afaSJeff Mahoney 		       fs_info->sectorsize, PAGE_SIZE);
2748e06baab4SStefan Behrens 		return -1;
2749e06baab4SStefan Behrens 	}
2750818e010bSDavid Sterba 	state = kvzalloc(sizeof(*state), GFP_KERNEL);
2751ab483009SLiao Pingfang 	if (!state)
27523afb0c50SAllen Pais 		return -ENOMEM;
27535db02760SStefan Behrens 
27545db02760SStefan Behrens 	if (!btrfsic_is_initialized) {
27555db02760SStefan Behrens 		mutex_init(&btrfsic_mutex);
27565db02760SStefan Behrens 		btrfsic_dev_state_hashtable_init(&btrfsic_dev_state_hashtable);
27575db02760SStefan Behrens 		btrfsic_is_initialized = 1;
27585db02760SStefan Behrens 	}
27595db02760SStefan Behrens 	mutex_lock(&btrfsic_mutex);
27602ff7e61eSJeff Mahoney 	state->fs_info = fs_info;
27615db02760SStefan Behrens 	state->print_mask = print_mask;
27625db02760SStefan Behrens 	state->include_extent_data = including_extent_data;
27630b246afaSJeff Mahoney 	state->metablock_size = fs_info->nodesize;
27640b246afaSJeff Mahoney 	state->datablock_size = fs_info->sectorsize;
27655db02760SStefan Behrens 	INIT_LIST_HEAD(&state->all_blocks_list);
27665db02760SStefan Behrens 	btrfsic_block_hashtable_init(&state->block_hashtable);
27675db02760SStefan Behrens 	btrfsic_block_link_hashtable_init(&state->block_link_hashtable);
27685db02760SStefan Behrens 	state->max_superblock_generation = 0;
27695db02760SStefan Behrens 	state->latest_superblock = NULL;
27705db02760SStefan Behrens 
27715db02760SStefan Behrens 	list_for_each_entry(device, dev_head, dev_list) {
27725db02760SStefan Behrens 		struct btrfsic_dev_state *ds;
27735db02760SStefan Behrens 
27745db02760SStefan Behrens 		if (!device->bdev || !device->name)
27755db02760SStefan Behrens 			continue;
27765db02760SStefan Behrens 
27775db02760SStefan Behrens 		ds = btrfsic_dev_state_alloc();
27785db02760SStefan Behrens 		if (NULL == ds) {
27795db02760SStefan Behrens 			mutex_unlock(&btrfsic_mutex);
27803afb0c50SAllen Pais 			return -ENOMEM;
27815db02760SStefan Behrens 		}
27825db02760SStefan Behrens 		ds->bdev = device->bdev;
27835db02760SStefan Behrens 		ds->state = state;
27845db02760SStefan Behrens 		btrfsic_dev_state_hashtable_add(ds,
27855db02760SStefan Behrens 						&btrfsic_dev_state_hashtable);
27865db02760SStefan Behrens 	}
27875db02760SStefan Behrens 
27885db02760SStefan Behrens 	ret = btrfsic_process_superblock(state, fs_devices);
27895db02760SStefan Behrens 	if (0 != ret) {
27905db02760SStefan Behrens 		mutex_unlock(&btrfsic_mutex);
27912ff7e61eSJeff Mahoney 		btrfsic_unmount(fs_devices);
27925db02760SStefan Behrens 		return ret;
27935db02760SStefan Behrens 	}
27945db02760SStefan Behrens 
27955db02760SStefan Behrens 	if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_DATABASE)
27965db02760SStefan Behrens 		btrfsic_dump_database(state);
27975db02760SStefan Behrens 	if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_TREE)
27985db02760SStefan Behrens 		btrfsic_dump_tree(state);
27995db02760SStefan Behrens 
28005db02760SStefan Behrens 	mutex_unlock(&btrfsic_mutex);
28015db02760SStefan Behrens 	return 0;
28025db02760SStefan Behrens }
28035db02760SStefan Behrens 
btrfsic_unmount(struct btrfs_fs_devices * fs_devices)28042ff7e61eSJeff Mahoney void btrfsic_unmount(struct btrfs_fs_devices *fs_devices)
28055db02760SStefan Behrens {
2806b69f2befSGeliang Tang 	struct btrfsic_block *b_all, *tmp_all;
28075db02760SStefan Behrens 	struct btrfsic_state *state;
28085db02760SStefan Behrens 	struct list_head *dev_head = &fs_devices->devices;
28095db02760SStefan Behrens 	struct btrfs_device *device;
28105db02760SStefan Behrens 
28115db02760SStefan Behrens 	if (!btrfsic_is_initialized)
28125db02760SStefan Behrens 		return;
28135db02760SStefan Behrens 
28145db02760SStefan Behrens 	mutex_lock(&btrfsic_mutex);
28155db02760SStefan Behrens 
28165db02760SStefan Behrens 	state = NULL;
28175db02760SStefan Behrens 	list_for_each_entry(device, dev_head, dev_list) {
28185db02760SStefan Behrens 		struct btrfsic_dev_state *ds;
28195db02760SStefan Behrens 
28205db02760SStefan Behrens 		if (!device->bdev || !device->name)
28215db02760SStefan Behrens 			continue;
28225db02760SStefan Behrens 
28235db02760SStefan Behrens 		ds = btrfsic_dev_state_hashtable_lookup(
2824f8f84b2dSChristoph Hellwig 				device->bdev->bd_dev,
28255db02760SStefan Behrens 				&btrfsic_dev_state_hashtable);
28265db02760SStefan Behrens 		if (NULL != ds) {
28275db02760SStefan Behrens 			state = ds->state;
28285db02760SStefan Behrens 			btrfsic_dev_state_hashtable_remove(ds);
28295db02760SStefan Behrens 			btrfsic_dev_state_free(ds);
28305db02760SStefan Behrens 		}
28315db02760SStefan Behrens 	}
28325db02760SStefan Behrens 
28335db02760SStefan Behrens 	if (NULL == state) {
283462e85577SJeff Mahoney 		pr_info("btrfsic: error, cannot find state information on umount!\n");
28355db02760SStefan Behrens 		mutex_unlock(&btrfsic_mutex);
28365db02760SStefan Behrens 		return;
28375db02760SStefan Behrens 	}
28385db02760SStefan Behrens 
28395db02760SStefan Behrens 	/*
28405db02760SStefan Behrens 	 * Don't care about keeping the lists' state up to date,
28415db02760SStefan Behrens 	 * just free all memory that was allocated dynamically.
28425db02760SStefan Behrens 	 * Free the blocks and the block_links.
28435db02760SStefan Behrens 	 */
2844b69f2befSGeliang Tang 	list_for_each_entry_safe(b_all, tmp_all, &state->all_blocks_list,
2845b69f2befSGeliang Tang 				 all_blocks_node) {
2846b69f2befSGeliang Tang 		struct btrfsic_block_link *l, *tmp;
28475db02760SStefan Behrens 
2848b69f2befSGeliang Tang 		list_for_each_entry_safe(l, tmp, &b_all->ref_to_list,
2849b69f2befSGeliang Tang 					 node_ref_to) {
28505db02760SStefan Behrens 			if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE)
28515db02760SStefan Behrens 				btrfsic_print_rem_link(state, l);
28525db02760SStefan Behrens 
28535db02760SStefan Behrens 			l->ref_cnt--;
28545db02760SStefan Behrens 			if (0 == l->ref_cnt)
28555db02760SStefan Behrens 				btrfsic_block_link_free(l);
28565db02760SStefan Behrens 		}
28575db02760SStefan Behrens 
285848235a68SStefan Behrens 		if (b_all->is_iodone || b_all->never_written)
28595db02760SStefan Behrens 			btrfsic_block_free(b_all);
28605db02760SStefan Behrens 		else
2861813ebc16SChristoph Hellwig 			pr_info(
2862813ebc16SChristoph Hellwig "btrfs: attempt to free %c-block @%llu (%pg/%llu/%d) on umount which is not yet iodone!\n",
28635db02760SStefan Behrens 			       btrfsic_get_block_type(state, b_all),
2864813ebc16SChristoph Hellwig 			       b_all->logical_bytenr, b_all->dev_state->bdev,
2865c1c9ff7cSGeert Uytterhoeven 			       b_all->dev_bytenr, b_all->mirror_num);
28665db02760SStefan Behrens 	}
28675db02760SStefan Behrens 
28685db02760SStefan Behrens 	mutex_unlock(&btrfsic_mutex);
28695db02760SStefan Behrens 
2870f749303bSWang Shilong 	kvfree(state);
28715db02760SStefan Behrens }
2872