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