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