18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) STRATO AG 2011. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/* 78c2ecf20Sopenharmony_ci * This module can be used to catch cases when the btrfs kernel 88c2ecf20Sopenharmony_ci * code executes write requests to the disk that bring the file 98c2ecf20Sopenharmony_ci * system in an inconsistent state. In such a state, a power-loss 108c2ecf20Sopenharmony_ci * or kernel panic event would cause that the data on disk is 118c2ecf20Sopenharmony_ci * lost or at least damaged. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Code is added that examines all block write requests during 148c2ecf20Sopenharmony_ci * runtime (including writes of the super block). Three rules 158c2ecf20Sopenharmony_ci * are verified and an error is printed on violation of the 168c2ecf20Sopenharmony_ci * rules: 178c2ecf20Sopenharmony_ci * 1. It is not allowed to write a disk block which is 188c2ecf20Sopenharmony_ci * currently referenced by the super block (either directly 198c2ecf20Sopenharmony_ci * or indirectly). 208c2ecf20Sopenharmony_ci * 2. When a super block is written, it is verified that all 218c2ecf20Sopenharmony_ci * referenced (directly or indirectly) blocks fulfill the 228c2ecf20Sopenharmony_ci * following requirements: 238c2ecf20Sopenharmony_ci * 2a. All referenced blocks have either been present when 248c2ecf20Sopenharmony_ci * the file system was mounted, (i.e., they have been 258c2ecf20Sopenharmony_ci * referenced by the super block) or they have been 268c2ecf20Sopenharmony_ci * written since then and the write completion callback 278c2ecf20Sopenharmony_ci * was called and no write error was indicated and a 288c2ecf20Sopenharmony_ci * FLUSH request to the device where these blocks are 298c2ecf20Sopenharmony_ci * located was received and completed. 308c2ecf20Sopenharmony_ci * 2b. All referenced blocks need to have a generation 318c2ecf20Sopenharmony_ci * number which is equal to the parent's number. 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * One issue that was found using this module was that the log 348c2ecf20Sopenharmony_ci * tree on disk became temporarily corrupted because disk blocks 358c2ecf20Sopenharmony_ci * that had been in use for the log tree had been freed and 368c2ecf20Sopenharmony_ci * reused too early, while being referenced by the written super 378c2ecf20Sopenharmony_ci * block. 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * The search term in the kernel log that can be used to filter 408c2ecf20Sopenharmony_ci * on the existence of detected integrity issues is 418c2ecf20Sopenharmony_ci * "btrfs: attempt". 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * The integrity check is enabled via mount options. These 448c2ecf20Sopenharmony_ci * mount options are only supported if the integrity check 458c2ecf20Sopenharmony_ci * tool is compiled by defining BTRFS_FS_CHECK_INTEGRITY. 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * Example #1, apply integrity checks to all metadata: 488c2ecf20Sopenharmony_ci * mount /dev/sdb1 /mnt -o check_int 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * Example #2, apply integrity checks to all metadata and 518c2ecf20Sopenharmony_ci * to data extents: 528c2ecf20Sopenharmony_ci * mount /dev/sdb1 /mnt -o check_int_data 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * Example #3, apply integrity checks to all metadata and dump 558c2ecf20Sopenharmony_ci * the tree that the super block references to kernel messages 568c2ecf20Sopenharmony_ci * each time after a super block was written: 578c2ecf20Sopenharmony_ci * mount /dev/sdb1 /mnt -o check_int,check_int_print_mask=263 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * If the integrity check tool is included and activated in 608c2ecf20Sopenharmony_ci * the mount options, plenty of kernel memory is used, and 618c2ecf20Sopenharmony_ci * plenty of additional CPU cycles are spent. Enabling this 628c2ecf20Sopenharmony_ci * functionality is not intended for normal use. In most 638c2ecf20Sopenharmony_ci * cases, unless you are a btrfs developer who needs to verify 648c2ecf20Sopenharmony_ci * the integrity of (super)-block write requests, do not 658c2ecf20Sopenharmony_ci * enable the config option BTRFS_FS_CHECK_INTEGRITY to 668c2ecf20Sopenharmony_ci * include and compile the integrity check tool. 678c2ecf20Sopenharmony_ci * 688c2ecf20Sopenharmony_ci * Expect millions of lines of information in the kernel log with an 698c2ecf20Sopenharmony_ci * enabled check_int_print_mask. Therefore set LOG_BUF_SHIFT in the 708c2ecf20Sopenharmony_ci * kernel config to at least 26 (which is 64MB). Usually the value is 718c2ecf20Sopenharmony_ci * limited to 21 (which is 2MB) in init/Kconfig. The file needs to be 728c2ecf20Sopenharmony_ci * changed like this before LOG_BUF_SHIFT can be set to a high value: 738c2ecf20Sopenharmony_ci * config LOG_BUF_SHIFT 748c2ecf20Sopenharmony_ci * int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" 758c2ecf20Sopenharmony_ci * range 12 30 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#include <linux/sched.h> 798c2ecf20Sopenharmony_ci#include <linux/slab.h> 808c2ecf20Sopenharmony_ci#include <linux/mutex.h> 818c2ecf20Sopenharmony_ci#include <linux/genhd.h> 828c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 838c2ecf20Sopenharmony_ci#include <linux/mm.h> 848c2ecf20Sopenharmony_ci#include <linux/string.h> 858c2ecf20Sopenharmony_ci#include <crypto/hash.h> 868c2ecf20Sopenharmony_ci#include "ctree.h" 878c2ecf20Sopenharmony_ci#include "disk-io.h" 888c2ecf20Sopenharmony_ci#include "transaction.h" 898c2ecf20Sopenharmony_ci#include "extent_io.h" 908c2ecf20Sopenharmony_ci#include "volumes.h" 918c2ecf20Sopenharmony_ci#include "print-tree.h" 928c2ecf20Sopenharmony_ci#include "locking.h" 938c2ecf20Sopenharmony_ci#include "check-integrity.h" 948c2ecf20Sopenharmony_ci#include "rcu-string.h" 958c2ecf20Sopenharmony_ci#include "compression.h" 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000 988c2ecf20Sopenharmony_ci#define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000 998c2ecf20Sopenharmony_ci#define BTRFSIC_DEV2STATE_HASHTABLE_SIZE 0x100 1008c2ecf20Sopenharmony_ci#define BTRFSIC_BLOCK_MAGIC_NUMBER 0x14491051 1018c2ecf20Sopenharmony_ci#define BTRFSIC_BLOCK_LINK_MAGIC_NUMBER 0x11070807 1028c2ecf20Sopenharmony_ci#define BTRFSIC_DEV2STATE_MAGIC_NUMBER 0x20111530 1038c2ecf20Sopenharmony_ci#define BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER 20111300 1048c2ecf20Sopenharmony_ci#define BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL (200 - 6) /* in characters, 1058c2ecf20Sopenharmony_ci * excluding " [...]" */ 1068c2ecf20Sopenharmony_ci#define BTRFSIC_GENERATION_UNKNOWN ((u64)-1) 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* 1098c2ecf20Sopenharmony_ci * The definition of the bitmask fields for the print_mask. 1108c2ecf20Sopenharmony_ci * They are specified with the mount option check_integrity_print_mask. 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE 0x00000001 1138c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION 0x00000002 1148c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE 0x00000004 1158c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE 0x00000008 1168c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH 0x00000010 1178c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_END_IO_BIO_BH 0x00000020 1188c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_VERBOSE 0x00000040 1198c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_VERY_VERBOSE 0x00000080 1208c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_INITIAL_TREE 0x00000100 1218c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES 0x00000200 1228c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_INITIAL_DATABASE 0x00000400 1238c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_NUM_COPIES 0x00000800 1248c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS 0x00001000 1258c2ecf20Sopenharmony_ci#define BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE 0x00002000 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistruct btrfsic_dev_state; 1288c2ecf20Sopenharmony_cistruct btrfsic_state; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistruct btrfsic_block { 1318c2ecf20Sopenharmony_ci u32 magic_num; /* only used for debug purposes */ 1328c2ecf20Sopenharmony_ci unsigned int is_metadata:1; /* if it is meta-data, not data-data */ 1338c2ecf20Sopenharmony_ci unsigned int is_superblock:1; /* if it is one of the superblocks */ 1348c2ecf20Sopenharmony_ci unsigned int is_iodone:1; /* if is done by lower subsystem */ 1358c2ecf20Sopenharmony_ci unsigned int iodone_w_error:1; /* error was indicated to endio */ 1368c2ecf20Sopenharmony_ci unsigned int never_written:1; /* block was added because it was 1378c2ecf20Sopenharmony_ci * referenced, not because it was 1388c2ecf20Sopenharmony_ci * written */ 1398c2ecf20Sopenharmony_ci unsigned int mirror_num; /* large enough to hold 1408c2ecf20Sopenharmony_ci * BTRFS_SUPER_MIRROR_MAX */ 1418c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state; 1428c2ecf20Sopenharmony_ci u64 dev_bytenr; /* key, physical byte num on disk */ 1438c2ecf20Sopenharmony_ci u64 logical_bytenr; /* logical byte num on disk */ 1448c2ecf20Sopenharmony_ci u64 generation; 1458c2ecf20Sopenharmony_ci struct btrfs_disk_key disk_key; /* extra info to print in case of 1468c2ecf20Sopenharmony_ci * issues, will not always be correct */ 1478c2ecf20Sopenharmony_ci struct list_head collision_resolving_node; /* list node */ 1488c2ecf20Sopenharmony_ci struct list_head all_blocks_node; /* list node */ 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* the following two lists contain block_link items */ 1518c2ecf20Sopenharmony_ci struct list_head ref_to_list; /* list */ 1528c2ecf20Sopenharmony_ci struct list_head ref_from_list; /* list */ 1538c2ecf20Sopenharmony_ci struct btrfsic_block *next_in_same_bio; 1548c2ecf20Sopenharmony_ci void *orig_bio_private; 1558c2ecf20Sopenharmony_ci bio_end_io_t *orig_bio_end_io; 1568c2ecf20Sopenharmony_ci int submit_bio_bh_rw; 1578c2ecf20Sopenharmony_ci u64 flush_gen; /* only valid if !never_written */ 1588c2ecf20Sopenharmony_ci}; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * Elements of this type are allocated dynamically and required because 1628c2ecf20Sopenharmony_ci * each block object can refer to and can be ref from multiple blocks. 1638c2ecf20Sopenharmony_ci * The key to lookup them in the hashtable is the dev_bytenr of 1648c2ecf20Sopenharmony_ci * the block ref to plus the one from the block referred from. 1658c2ecf20Sopenharmony_ci * The fact that they are searchable via a hashtable and that a 1668c2ecf20Sopenharmony_ci * ref_cnt is maintained is not required for the btrfs integrity 1678c2ecf20Sopenharmony_ci * check algorithm itself, it is only used to make the output more 1688c2ecf20Sopenharmony_ci * beautiful in case that an error is detected (an error is defined 1698c2ecf20Sopenharmony_ci * as a write operation to a block while that block is still referenced). 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_cistruct btrfsic_block_link { 1728c2ecf20Sopenharmony_ci u32 magic_num; /* only used for debug purposes */ 1738c2ecf20Sopenharmony_ci u32 ref_cnt; 1748c2ecf20Sopenharmony_ci struct list_head node_ref_to; /* list node */ 1758c2ecf20Sopenharmony_ci struct list_head node_ref_from; /* list node */ 1768c2ecf20Sopenharmony_ci struct list_head collision_resolving_node; /* list node */ 1778c2ecf20Sopenharmony_ci struct btrfsic_block *block_ref_to; 1788c2ecf20Sopenharmony_ci struct btrfsic_block *block_ref_from; 1798c2ecf20Sopenharmony_ci u64 parent_generation; 1808c2ecf20Sopenharmony_ci}; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistruct btrfsic_dev_state { 1838c2ecf20Sopenharmony_ci u32 magic_num; /* only used for debug purposes */ 1848c2ecf20Sopenharmony_ci struct block_device *bdev; 1858c2ecf20Sopenharmony_ci struct btrfsic_state *state; 1868c2ecf20Sopenharmony_ci struct list_head collision_resolving_node; /* list node */ 1878c2ecf20Sopenharmony_ci struct btrfsic_block dummy_block_for_bio_bh_flush; 1888c2ecf20Sopenharmony_ci u64 last_flush_gen; 1898c2ecf20Sopenharmony_ci char name[BDEVNAME_SIZE]; 1908c2ecf20Sopenharmony_ci}; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistruct btrfsic_block_hashtable { 1938c2ecf20Sopenharmony_ci struct list_head table[BTRFSIC_BLOCK_HASHTABLE_SIZE]; 1948c2ecf20Sopenharmony_ci}; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistruct btrfsic_block_link_hashtable { 1978c2ecf20Sopenharmony_ci struct list_head table[BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE]; 1988c2ecf20Sopenharmony_ci}; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistruct btrfsic_dev_state_hashtable { 2018c2ecf20Sopenharmony_ci struct list_head table[BTRFSIC_DEV2STATE_HASHTABLE_SIZE]; 2028c2ecf20Sopenharmony_ci}; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistruct btrfsic_block_data_ctx { 2058c2ecf20Sopenharmony_ci u64 start; /* virtual bytenr */ 2068c2ecf20Sopenharmony_ci u64 dev_bytenr; /* physical bytenr on device */ 2078c2ecf20Sopenharmony_ci u32 len; 2088c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev; 2098c2ecf20Sopenharmony_ci char **datav; 2108c2ecf20Sopenharmony_ci struct page **pagev; 2118c2ecf20Sopenharmony_ci void *mem_to_free; 2128c2ecf20Sopenharmony_ci}; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci/* This structure is used to implement recursion without occupying 2158c2ecf20Sopenharmony_ci * any stack space, refer to btrfsic_process_metablock() */ 2168c2ecf20Sopenharmony_cistruct btrfsic_stack_frame { 2178c2ecf20Sopenharmony_ci u32 magic; 2188c2ecf20Sopenharmony_ci u32 nr; 2198c2ecf20Sopenharmony_ci int error; 2208c2ecf20Sopenharmony_ci int i; 2218c2ecf20Sopenharmony_ci int limit_nesting; 2228c2ecf20Sopenharmony_ci int num_copies; 2238c2ecf20Sopenharmony_ci int mirror_num; 2248c2ecf20Sopenharmony_ci struct btrfsic_block *block; 2258c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx; 2268c2ecf20Sopenharmony_ci struct btrfsic_block *next_block; 2278c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx next_block_ctx; 2288c2ecf20Sopenharmony_ci struct btrfs_header *hdr; 2298c2ecf20Sopenharmony_ci struct btrfsic_stack_frame *prev; 2308c2ecf20Sopenharmony_ci}; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/* Some state per mounted filesystem */ 2338c2ecf20Sopenharmony_cistruct btrfsic_state { 2348c2ecf20Sopenharmony_ci u32 print_mask; 2358c2ecf20Sopenharmony_ci int include_extent_data; 2368c2ecf20Sopenharmony_ci int csum_size; 2378c2ecf20Sopenharmony_ci struct list_head all_blocks_list; 2388c2ecf20Sopenharmony_ci struct btrfsic_block_hashtable block_hashtable; 2398c2ecf20Sopenharmony_ci struct btrfsic_block_link_hashtable block_link_hashtable; 2408c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info; 2418c2ecf20Sopenharmony_ci u64 max_superblock_generation; 2428c2ecf20Sopenharmony_ci struct btrfsic_block *latest_superblock; 2438c2ecf20Sopenharmony_ci u32 metablock_size; 2448c2ecf20Sopenharmony_ci u32 datablock_size; 2458c2ecf20Sopenharmony_ci}; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic void btrfsic_block_init(struct btrfsic_block *b); 2488c2ecf20Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_alloc(void); 2498c2ecf20Sopenharmony_cistatic void btrfsic_block_free(struct btrfsic_block *b); 2508c2ecf20Sopenharmony_cistatic void btrfsic_block_link_init(struct btrfsic_block_link *n); 2518c2ecf20Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_alloc(void); 2528c2ecf20Sopenharmony_cistatic void btrfsic_block_link_free(struct btrfsic_block_link *n); 2538c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_init(struct btrfsic_dev_state *ds); 2548c2ecf20Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_alloc(void); 2558c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_free(struct btrfsic_dev_state *ds); 2568c2ecf20Sopenharmony_cistatic void btrfsic_block_hashtable_init(struct btrfsic_block_hashtable *h); 2578c2ecf20Sopenharmony_cistatic void btrfsic_block_hashtable_add(struct btrfsic_block *b, 2588c2ecf20Sopenharmony_ci struct btrfsic_block_hashtable *h); 2598c2ecf20Sopenharmony_cistatic void btrfsic_block_hashtable_remove(struct btrfsic_block *b); 2608c2ecf20Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_hashtable_lookup( 2618c2ecf20Sopenharmony_ci struct block_device *bdev, 2628c2ecf20Sopenharmony_ci u64 dev_bytenr, 2638c2ecf20Sopenharmony_ci struct btrfsic_block_hashtable *h); 2648c2ecf20Sopenharmony_cistatic void btrfsic_block_link_hashtable_init( 2658c2ecf20Sopenharmony_ci struct btrfsic_block_link_hashtable *h); 2668c2ecf20Sopenharmony_cistatic void btrfsic_block_link_hashtable_add( 2678c2ecf20Sopenharmony_ci struct btrfsic_block_link *l, 2688c2ecf20Sopenharmony_ci struct btrfsic_block_link_hashtable *h); 2698c2ecf20Sopenharmony_cistatic void btrfsic_block_link_hashtable_remove(struct btrfsic_block_link *l); 2708c2ecf20Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_hashtable_lookup( 2718c2ecf20Sopenharmony_ci struct block_device *bdev_ref_to, 2728c2ecf20Sopenharmony_ci u64 dev_bytenr_ref_to, 2738c2ecf20Sopenharmony_ci struct block_device *bdev_ref_from, 2748c2ecf20Sopenharmony_ci u64 dev_bytenr_ref_from, 2758c2ecf20Sopenharmony_ci struct btrfsic_block_link_hashtable *h); 2768c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_hashtable_init( 2778c2ecf20Sopenharmony_ci struct btrfsic_dev_state_hashtable *h); 2788c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_hashtable_add( 2798c2ecf20Sopenharmony_ci struct btrfsic_dev_state *ds, 2808c2ecf20Sopenharmony_ci struct btrfsic_dev_state_hashtable *h); 2818c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_hashtable_remove(struct btrfsic_dev_state *ds); 2828c2ecf20Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(dev_t dev, 2838c2ecf20Sopenharmony_ci struct btrfsic_dev_state_hashtable *h); 2848c2ecf20Sopenharmony_cistatic struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void); 2858c2ecf20Sopenharmony_cistatic void btrfsic_stack_frame_free(struct btrfsic_stack_frame *sf); 2868c2ecf20Sopenharmony_cistatic int btrfsic_process_superblock(struct btrfsic_state *state, 2878c2ecf20Sopenharmony_ci struct btrfs_fs_devices *fs_devices); 2888c2ecf20Sopenharmony_cistatic int btrfsic_process_metablock(struct btrfsic_state *state, 2898c2ecf20Sopenharmony_ci struct btrfsic_block *block, 2908c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 2918c2ecf20Sopenharmony_ci int limit_nesting, int force_iodone_flag); 2928c2ecf20Sopenharmony_cistatic void btrfsic_read_from_block_data( 2938c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 2948c2ecf20Sopenharmony_ci void *dst, u32 offset, size_t len); 2958c2ecf20Sopenharmony_cistatic int btrfsic_create_link_to_next_block( 2968c2ecf20Sopenharmony_ci struct btrfsic_state *state, 2978c2ecf20Sopenharmony_ci struct btrfsic_block *block, 2988c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx 2998c2ecf20Sopenharmony_ci *block_ctx, u64 next_bytenr, 3008c2ecf20Sopenharmony_ci int limit_nesting, 3018c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *next_block_ctx, 3028c2ecf20Sopenharmony_ci struct btrfsic_block **next_blockp, 3038c2ecf20Sopenharmony_ci int force_iodone_flag, 3048c2ecf20Sopenharmony_ci int *num_copiesp, int *mirror_nump, 3058c2ecf20Sopenharmony_ci struct btrfs_disk_key *disk_key, 3068c2ecf20Sopenharmony_ci u64 parent_generation); 3078c2ecf20Sopenharmony_cistatic int btrfsic_handle_extent_data(struct btrfsic_state *state, 3088c2ecf20Sopenharmony_ci struct btrfsic_block *block, 3098c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 3108c2ecf20Sopenharmony_ci u32 item_offset, int force_iodone_flag); 3118c2ecf20Sopenharmony_cistatic int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len, 3128c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx_out, 3138c2ecf20Sopenharmony_ci int mirror_num); 3148c2ecf20Sopenharmony_cistatic void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx); 3158c2ecf20Sopenharmony_cistatic int btrfsic_read_block(struct btrfsic_state *state, 3168c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx); 3178c2ecf20Sopenharmony_cistatic void btrfsic_dump_database(struct btrfsic_state *state); 3188c2ecf20Sopenharmony_cistatic int btrfsic_test_for_metadata(struct btrfsic_state *state, 3198c2ecf20Sopenharmony_ci char **datav, unsigned int num_pages); 3208c2ecf20Sopenharmony_cistatic void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, 3218c2ecf20Sopenharmony_ci u64 dev_bytenr, char **mapped_datav, 3228c2ecf20Sopenharmony_ci unsigned int num_pages, 3238c2ecf20Sopenharmony_ci struct bio *bio, int *bio_is_patched, 3248c2ecf20Sopenharmony_ci int submit_bio_bh_rw); 3258c2ecf20Sopenharmony_cistatic int btrfsic_process_written_superblock( 3268c2ecf20Sopenharmony_ci struct btrfsic_state *state, 3278c2ecf20Sopenharmony_ci struct btrfsic_block *const block, 3288c2ecf20Sopenharmony_ci struct btrfs_super_block *const super_hdr); 3298c2ecf20Sopenharmony_cistatic void btrfsic_bio_end_io(struct bio *bp); 3308c2ecf20Sopenharmony_cistatic int btrfsic_is_block_ref_by_superblock(const struct btrfsic_state *state, 3318c2ecf20Sopenharmony_ci const struct btrfsic_block *block, 3328c2ecf20Sopenharmony_ci int recursion_level); 3338c2ecf20Sopenharmony_cistatic int btrfsic_check_all_ref_blocks(struct btrfsic_state *state, 3348c2ecf20Sopenharmony_ci struct btrfsic_block *const block, 3358c2ecf20Sopenharmony_ci int recursion_level); 3368c2ecf20Sopenharmony_cistatic void btrfsic_print_add_link(const struct btrfsic_state *state, 3378c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l); 3388c2ecf20Sopenharmony_cistatic void btrfsic_print_rem_link(const struct btrfsic_state *state, 3398c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l); 3408c2ecf20Sopenharmony_cistatic char btrfsic_get_block_type(const struct btrfsic_state *state, 3418c2ecf20Sopenharmony_ci const struct btrfsic_block *block); 3428c2ecf20Sopenharmony_cistatic void btrfsic_dump_tree(const struct btrfsic_state *state); 3438c2ecf20Sopenharmony_cistatic void btrfsic_dump_tree_sub(const struct btrfsic_state *state, 3448c2ecf20Sopenharmony_ci const struct btrfsic_block *block, 3458c2ecf20Sopenharmony_ci int indent_level); 3468c2ecf20Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_lookup_or_add( 3478c2ecf20Sopenharmony_ci struct btrfsic_state *state, 3488c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *next_block_ctx, 3498c2ecf20Sopenharmony_ci struct btrfsic_block *next_block, 3508c2ecf20Sopenharmony_ci struct btrfsic_block *from_block, 3518c2ecf20Sopenharmony_ci u64 parent_generation); 3528c2ecf20Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_lookup_or_add( 3538c2ecf20Sopenharmony_ci struct btrfsic_state *state, 3548c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 3558c2ecf20Sopenharmony_ci const char *additional_string, 3568c2ecf20Sopenharmony_ci int is_metadata, 3578c2ecf20Sopenharmony_ci int is_iodone, 3588c2ecf20Sopenharmony_ci int never_written, 3598c2ecf20Sopenharmony_ci int mirror_num, 3608c2ecf20Sopenharmony_ci int *was_created); 3618c2ecf20Sopenharmony_cistatic int btrfsic_process_superblock_dev_mirror( 3628c2ecf20Sopenharmony_ci struct btrfsic_state *state, 3638c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state, 3648c2ecf20Sopenharmony_ci struct btrfs_device *device, 3658c2ecf20Sopenharmony_ci int superblock_mirror_num, 3668c2ecf20Sopenharmony_ci struct btrfsic_dev_state **selected_dev_state, 3678c2ecf20Sopenharmony_ci struct btrfs_super_block *selected_super); 3688c2ecf20Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_lookup(dev_t dev); 3698c2ecf20Sopenharmony_cistatic void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state, 3708c2ecf20Sopenharmony_ci u64 bytenr, 3718c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state, 3728c2ecf20Sopenharmony_ci u64 dev_bytenr); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic struct mutex btrfsic_mutex; 3758c2ecf20Sopenharmony_cistatic int btrfsic_is_initialized; 3768c2ecf20Sopenharmony_cistatic struct btrfsic_dev_state_hashtable btrfsic_dev_state_hashtable; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic void btrfsic_block_init(struct btrfsic_block *b) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci b->magic_num = BTRFSIC_BLOCK_MAGIC_NUMBER; 3828c2ecf20Sopenharmony_ci b->dev_state = NULL; 3838c2ecf20Sopenharmony_ci b->dev_bytenr = 0; 3848c2ecf20Sopenharmony_ci b->logical_bytenr = 0; 3858c2ecf20Sopenharmony_ci b->generation = BTRFSIC_GENERATION_UNKNOWN; 3868c2ecf20Sopenharmony_ci b->disk_key.objectid = 0; 3878c2ecf20Sopenharmony_ci b->disk_key.type = 0; 3888c2ecf20Sopenharmony_ci b->disk_key.offset = 0; 3898c2ecf20Sopenharmony_ci b->is_metadata = 0; 3908c2ecf20Sopenharmony_ci b->is_superblock = 0; 3918c2ecf20Sopenharmony_ci b->is_iodone = 0; 3928c2ecf20Sopenharmony_ci b->iodone_w_error = 0; 3938c2ecf20Sopenharmony_ci b->never_written = 0; 3948c2ecf20Sopenharmony_ci b->mirror_num = 0; 3958c2ecf20Sopenharmony_ci b->next_in_same_bio = NULL; 3968c2ecf20Sopenharmony_ci b->orig_bio_private = NULL; 3978c2ecf20Sopenharmony_ci b->orig_bio_end_io = NULL; 3988c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&b->collision_resolving_node); 3998c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&b->all_blocks_node); 4008c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&b->ref_to_list); 4018c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&b->ref_from_list); 4028c2ecf20Sopenharmony_ci b->submit_bio_bh_rw = 0; 4038c2ecf20Sopenharmony_ci b->flush_gen = 0; 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_alloc(void) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci struct btrfsic_block *b; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci b = kzalloc(sizeof(*b), GFP_NOFS); 4118c2ecf20Sopenharmony_ci if (NULL != b) 4128c2ecf20Sopenharmony_ci btrfsic_block_init(b); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci return b; 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cistatic void btrfsic_block_free(struct btrfsic_block *b) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci BUG_ON(!(NULL == b || BTRFSIC_BLOCK_MAGIC_NUMBER == b->magic_num)); 4208c2ecf20Sopenharmony_ci kfree(b); 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cistatic void btrfsic_block_link_init(struct btrfsic_block_link *l) 4248c2ecf20Sopenharmony_ci{ 4258c2ecf20Sopenharmony_ci l->magic_num = BTRFSIC_BLOCK_LINK_MAGIC_NUMBER; 4268c2ecf20Sopenharmony_ci l->ref_cnt = 1; 4278c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&l->node_ref_to); 4288c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&l->node_ref_from); 4298c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&l->collision_resolving_node); 4308c2ecf20Sopenharmony_ci l->block_ref_to = NULL; 4318c2ecf20Sopenharmony_ci l->block_ref_from = NULL; 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_alloc(void) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci l = kzalloc(sizeof(*l), GFP_NOFS); 4398c2ecf20Sopenharmony_ci if (NULL != l) 4408c2ecf20Sopenharmony_ci btrfsic_block_link_init(l); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci return l; 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic void btrfsic_block_link_free(struct btrfsic_block_link *l) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci BUG_ON(!(NULL == l || BTRFSIC_BLOCK_LINK_MAGIC_NUMBER == l->magic_num)); 4488c2ecf20Sopenharmony_ci kfree(l); 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_init(struct btrfsic_dev_state *ds) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci ds->magic_num = BTRFSIC_DEV2STATE_MAGIC_NUMBER; 4548c2ecf20Sopenharmony_ci ds->bdev = NULL; 4558c2ecf20Sopenharmony_ci ds->state = NULL; 4568c2ecf20Sopenharmony_ci ds->name[0] = '\0'; 4578c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ds->collision_resolving_node); 4588c2ecf20Sopenharmony_ci ds->last_flush_gen = 0; 4598c2ecf20Sopenharmony_ci btrfsic_block_init(&ds->dummy_block_for_bio_bh_flush); 4608c2ecf20Sopenharmony_ci ds->dummy_block_for_bio_bh_flush.is_iodone = 1; 4618c2ecf20Sopenharmony_ci ds->dummy_block_for_bio_bh_flush.dev_state = ds; 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_alloc(void) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci struct btrfsic_dev_state *ds; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci ds = kzalloc(sizeof(*ds), GFP_NOFS); 4698c2ecf20Sopenharmony_ci if (NULL != ds) 4708c2ecf20Sopenharmony_ci btrfsic_dev_state_init(ds); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci return ds; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_free(struct btrfsic_dev_state *ds) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci BUG_ON(!(NULL == ds || 4788c2ecf20Sopenharmony_ci BTRFSIC_DEV2STATE_MAGIC_NUMBER == ds->magic_num)); 4798c2ecf20Sopenharmony_ci kfree(ds); 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic void btrfsic_block_hashtable_init(struct btrfsic_block_hashtable *h) 4838c2ecf20Sopenharmony_ci{ 4848c2ecf20Sopenharmony_ci int i; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci for (i = 0; i < BTRFSIC_BLOCK_HASHTABLE_SIZE; i++) 4878c2ecf20Sopenharmony_ci INIT_LIST_HEAD(h->table + i); 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistatic void btrfsic_block_hashtable_add(struct btrfsic_block *b, 4918c2ecf20Sopenharmony_ci struct btrfsic_block_hashtable *h) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci const unsigned int hashval = 4948c2ecf20Sopenharmony_ci (((unsigned int)(b->dev_bytenr >> 16)) ^ 4958c2ecf20Sopenharmony_ci ((unsigned int)((uintptr_t)b->dev_state->bdev))) & 4968c2ecf20Sopenharmony_ci (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci list_add(&b->collision_resolving_node, h->table + hashval); 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_cistatic void btrfsic_block_hashtable_remove(struct btrfsic_block *b) 5028c2ecf20Sopenharmony_ci{ 5038c2ecf20Sopenharmony_ci list_del(&b->collision_resolving_node); 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_hashtable_lookup( 5078c2ecf20Sopenharmony_ci struct block_device *bdev, 5088c2ecf20Sopenharmony_ci u64 dev_bytenr, 5098c2ecf20Sopenharmony_ci struct btrfsic_block_hashtable *h) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci const unsigned int hashval = 5128c2ecf20Sopenharmony_ci (((unsigned int)(dev_bytenr >> 16)) ^ 5138c2ecf20Sopenharmony_ci ((unsigned int)((uintptr_t)bdev))) & 5148c2ecf20Sopenharmony_ci (BTRFSIC_BLOCK_HASHTABLE_SIZE - 1); 5158c2ecf20Sopenharmony_ci struct btrfsic_block *b; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci list_for_each_entry(b, h->table + hashval, collision_resolving_node) { 5188c2ecf20Sopenharmony_ci if (b->dev_state->bdev == bdev && b->dev_bytenr == dev_bytenr) 5198c2ecf20Sopenharmony_ci return b; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci return NULL; 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cistatic void btrfsic_block_link_hashtable_init( 5268c2ecf20Sopenharmony_ci struct btrfsic_block_link_hashtable *h) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci int i; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci for (i = 0; i < BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE; i++) 5318c2ecf20Sopenharmony_ci INIT_LIST_HEAD(h->table + i); 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic void btrfsic_block_link_hashtable_add( 5358c2ecf20Sopenharmony_ci struct btrfsic_block_link *l, 5368c2ecf20Sopenharmony_ci struct btrfsic_block_link_hashtable *h) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci const unsigned int hashval = 5398c2ecf20Sopenharmony_ci (((unsigned int)(l->block_ref_to->dev_bytenr >> 16)) ^ 5408c2ecf20Sopenharmony_ci ((unsigned int)(l->block_ref_from->dev_bytenr >> 16)) ^ 5418c2ecf20Sopenharmony_ci ((unsigned int)((uintptr_t)l->block_ref_to->dev_state->bdev)) ^ 5428c2ecf20Sopenharmony_ci ((unsigned int)((uintptr_t)l->block_ref_from->dev_state->bdev))) 5438c2ecf20Sopenharmony_ci & (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1); 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci BUG_ON(NULL == l->block_ref_to); 5468c2ecf20Sopenharmony_ci BUG_ON(NULL == l->block_ref_from); 5478c2ecf20Sopenharmony_ci list_add(&l->collision_resolving_node, h->table + hashval); 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_cistatic void btrfsic_block_link_hashtable_remove(struct btrfsic_block_link *l) 5518c2ecf20Sopenharmony_ci{ 5528c2ecf20Sopenharmony_ci list_del(&l->collision_resolving_node); 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_hashtable_lookup( 5568c2ecf20Sopenharmony_ci struct block_device *bdev_ref_to, 5578c2ecf20Sopenharmony_ci u64 dev_bytenr_ref_to, 5588c2ecf20Sopenharmony_ci struct block_device *bdev_ref_from, 5598c2ecf20Sopenharmony_ci u64 dev_bytenr_ref_from, 5608c2ecf20Sopenharmony_ci struct btrfsic_block_link_hashtable *h) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci const unsigned int hashval = 5638c2ecf20Sopenharmony_ci (((unsigned int)(dev_bytenr_ref_to >> 16)) ^ 5648c2ecf20Sopenharmony_ci ((unsigned int)(dev_bytenr_ref_from >> 16)) ^ 5658c2ecf20Sopenharmony_ci ((unsigned int)((uintptr_t)bdev_ref_to)) ^ 5668c2ecf20Sopenharmony_ci ((unsigned int)((uintptr_t)bdev_ref_from))) & 5678c2ecf20Sopenharmony_ci (BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE - 1); 5688c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci list_for_each_entry(l, h->table + hashval, collision_resolving_node) { 5718c2ecf20Sopenharmony_ci BUG_ON(NULL == l->block_ref_to); 5728c2ecf20Sopenharmony_ci BUG_ON(NULL == l->block_ref_from); 5738c2ecf20Sopenharmony_ci if (l->block_ref_to->dev_state->bdev == bdev_ref_to && 5748c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr == dev_bytenr_ref_to && 5758c2ecf20Sopenharmony_ci l->block_ref_from->dev_state->bdev == bdev_ref_from && 5768c2ecf20Sopenharmony_ci l->block_ref_from->dev_bytenr == dev_bytenr_ref_from) 5778c2ecf20Sopenharmony_ci return l; 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci return NULL; 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_hashtable_init( 5848c2ecf20Sopenharmony_ci struct btrfsic_dev_state_hashtable *h) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci int i; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci for (i = 0; i < BTRFSIC_DEV2STATE_HASHTABLE_SIZE; i++) 5898c2ecf20Sopenharmony_ci INIT_LIST_HEAD(h->table + i); 5908c2ecf20Sopenharmony_ci} 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_hashtable_add( 5938c2ecf20Sopenharmony_ci struct btrfsic_dev_state *ds, 5948c2ecf20Sopenharmony_ci struct btrfsic_dev_state_hashtable *h) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci const unsigned int hashval = 5978c2ecf20Sopenharmony_ci (((unsigned int)((uintptr_t)ds->bdev->bd_dev)) & 5988c2ecf20Sopenharmony_ci (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1)); 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci list_add(&ds->collision_resolving_node, h->table + hashval); 6018c2ecf20Sopenharmony_ci} 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_cistatic void btrfsic_dev_state_hashtable_remove(struct btrfsic_dev_state *ds) 6048c2ecf20Sopenharmony_ci{ 6058c2ecf20Sopenharmony_ci list_del(&ds->collision_resolving_node); 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(dev_t dev, 6098c2ecf20Sopenharmony_ci struct btrfsic_dev_state_hashtable *h) 6108c2ecf20Sopenharmony_ci{ 6118c2ecf20Sopenharmony_ci const unsigned int hashval = 6128c2ecf20Sopenharmony_ci dev & (BTRFSIC_DEV2STATE_HASHTABLE_SIZE - 1); 6138c2ecf20Sopenharmony_ci struct btrfsic_dev_state *ds; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci list_for_each_entry(ds, h->table + hashval, collision_resolving_node) { 6168c2ecf20Sopenharmony_ci if (ds->bdev->bd_dev == dev) 6178c2ecf20Sopenharmony_ci return ds; 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci return NULL; 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_cistatic int btrfsic_process_superblock(struct btrfsic_state *state, 6248c2ecf20Sopenharmony_ci struct btrfs_fs_devices *fs_devices) 6258c2ecf20Sopenharmony_ci{ 6268c2ecf20Sopenharmony_ci struct btrfs_super_block *selected_super; 6278c2ecf20Sopenharmony_ci struct list_head *dev_head = &fs_devices->devices; 6288c2ecf20Sopenharmony_ci struct btrfs_device *device; 6298c2ecf20Sopenharmony_ci struct btrfsic_dev_state *selected_dev_state = NULL; 6308c2ecf20Sopenharmony_ci int ret = 0; 6318c2ecf20Sopenharmony_ci int pass; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci selected_super = kzalloc(sizeof(*selected_super), GFP_NOFS); 6348c2ecf20Sopenharmony_ci if (!selected_super) 6358c2ecf20Sopenharmony_ci return -ENOMEM; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci list_for_each_entry(device, dev_head, dev_list) { 6388c2ecf20Sopenharmony_ci int i; 6398c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (!device->bdev || !device->name) 6428c2ecf20Sopenharmony_ci continue; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci dev_state = btrfsic_dev_state_lookup(device->bdev->bd_dev); 6458c2ecf20Sopenharmony_ci BUG_ON(NULL == dev_state); 6468c2ecf20Sopenharmony_ci for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { 6478c2ecf20Sopenharmony_ci ret = btrfsic_process_superblock_dev_mirror( 6488c2ecf20Sopenharmony_ci state, dev_state, device, i, 6498c2ecf20Sopenharmony_ci &selected_dev_state, selected_super); 6508c2ecf20Sopenharmony_ci if (0 != ret && 0 == i) { 6518c2ecf20Sopenharmony_ci kfree(selected_super); 6528c2ecf20Sopenharmony_ci return ret; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci if (NULL == state->latest_superblock) { 6588c2ecf20Sopenharmony_ci pr_info("btrfsic: no superblock found!\n"); 6598c2ecf20Sopenharmony_ci kfree(selected_super); 6608c2ecf20Sopenharmony_ci return -1; 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci state->csum_size = btrfs_super_csum_size(selected_super); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci for (pass = 0; pass < 3; pass++) { 6668c2ecf20Sopenharmony_ci int num_copies; 6678c2ecf20Sopenharmony_ci int mirror_num; 6688c2ecf20Sopenharmony_ci u64 next_bytenr; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci switch (pass) { 6718c2ecf20Sopenharmony_ci case 0: 6728c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_root(selected_super); 6738c2ecf20Sopenharmony_ci if (state->print_mask & 6748c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION) 6758c2ecf20Sopenharmony_ci pr_info("root@%llu\n", next_bytenr); 6768c2ecf20Sopenharmony_ci break; 6778c2ecf20Sopenharmony_ci case 1: 6788c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_chunk_root(selected_super); 6798c2ecf20Sopenharmony_ci if (state->print_mask & 6808c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION) 6818c2ecf20Sopenharmony_ci pr_info("chunk@%llu\n", next_bytenr); 6828c2ecf20Sopenharmony_ci break; 6838c2ecf20Sopenharmony_ci case 2: 6848c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_log_root(selected_super); 6858c2ecf20Sopenharmony_ci if (0 == next_bytenr) 6868c2ecf20Sopenharmony_ci continue; 6878c2ecf20Sopenharmony_ci if (state->print_mask & 6888c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION) 6898c2ecf20Sopenharmony_ci pr_info("log@%llu\n", next_bytenr); 6908c2ecf20Sopenharmony_ci break; 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci num_copies = btrfs_num_copies(state->fs_info, next_bytenr, 6948c2ecf20Sopenharmony_ci state->metablock_size); 6958c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) 6968c2ecf20Sopenharmony_ci pr_info("num_copies(log_bytenr=%llu) = %d\n", 6978c2ecf20Sopenharmony_ci next_bytenr, num_copies); 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) { 7008c2ecf20Sopenharmony_ci struct btrfsic_block *next_block; 7018c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx tmp_next_block_ctx; 7028c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci ret = btrfsic_map_block(state, next_bytenr, 7058c2ecf20Sopenharmony_ci state->metablock_size, 7068c2ecf20Sopenharmony_ci &tmp_next_block_ctx, 7078c2ecf20Sopenharmony_ci mirror_num); 7088c2ecf20Sopenharmony_ci if (ret) { 7098c2ecf20Sopenharmony_ci pr_info("btrfsic: btrfsic_map_block(root @%llu, mirror %d) failed!\n", 7108c2ecf20Sopenharmony_ci next_bytenr, mirror_num); 7118c2ecf20Sopenharmony_ci kfree(selected_super); 7128c2ecf20Sopenharmony_ci return -1; 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci next_block = btrfsic_block_hashtable_lookup( 7168c2ecf20Sopenharmony_ci tmp_next_block_ctx.dev->bdev, 7178c2ecf20Sopenharmony_ci tmp_next_block_ctx.dev_bytenr, 7188c2ecf20Sopenharmony_ci &state->block_hashtable); 7198c2ecf20Sopenharmony_ci BUG_ON(NULL == next_block); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci l = btrfsic_block_link_hashtable_lookup( 7228c2ecf20Sopenharmony_ci tmp_next_block_ctx.dev->bdev, 7238c2ecf20Sopenharmony_ci tmp_next_block_ctx.dev_bytenr, 7248c2ecf20Sopenharmony_ci state->latest_superblock->dev_state-> 7258c2ecf20Sopenharmony_ci bdev, 7268c2ecf20Sopenharmony_ci state->latest_superblock->dev_bytenr, 7278c2ecf20Sopenharmony_ci &state->block_link_hashtable); 7288c2ecf20Sopenharmony_ci BUG_ON(NULL == l); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci ret = btrfsic_read_block(state, &tmp_next_block_ctx); 7318c2ecf20Sopenharmony_ci if (ret < (int)PAGE_SIZE) { 7328c2ecf20Sopenharmony_ci pr_info("btrfsic: read @logical %llu failed!\n", 7338c2ecf20Sopenharmony_ci tmp_next_block_ctx.start); 7348c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&tmp_next_block_ctx); 7358c2ecf20Sopenharmony_ci kfree(selected_super); 7368c2ecf20Sopenharmony_ci return -1; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci ret = btrfsic_process_metablock(state, 7408c2ecf20Sopenharmony_ci next_block, 7418c2ecf20Sopenharmony_ci &tmp_next_block_ctx, 7428c2ecf20Sopenharmony_ci BTRFS_MAX_LEVEL + 3, 1); 7438c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&tmp_next_block_ctx); 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci kfree(selected_super); 7488c2ecf20Sopenharmony_ci return ret; 7498c2ecf20Sopenharmony_ci} 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistatic int btrfsic_process_superblock_dev_mirror( 7528c2ecf20Sopenharmony_ci struct btrfsic_state *state, 7538c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state, 7548c2ecf20Sopenharmony_ci struct btrfs_device *device, 7558c2ecf20Sopenharmony_ci int superblock_mirror_num, 7568c2ecf20Sopenharmony_ci struct btrfsic_dev_state **selected_dev_state, 7578c2ecf20Sopenharmony_ci struct btrfs_super_block *selected_super) 7588c2ecf20Sopenharmony_ci{ 7598c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = state->fs_info; 7608c2ecf20Sopenharmony_ci struct btrfs_super_block *super_tmp; 7618c2ecf20Sopenharmony_ci u64 dev_bytenr; 7628c2ecf20Sopenharmony_ci struct btrfsic_block *superblock_tmp; 7638c2ecf20Sopenharmony_ci int pass; 7648c2ecf20Sopenharmony_ci struct block_device *const superblock_bdev = device->bdev; 7658c2ecf20Sopenharmony_ci struct page *page; 7668c2ecf20Sopenharmony_ci struct address_space *mapping = superblock_bdev->bd_inode->i_mapping; 7678c2ecf20Sopenharmony_ci int ret = 0; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* super block bytenr is always the unmapped device bytenr */ 7708c2ecf20Sopenharmony_ci dev_bytenr = btrfs_sb_offset(superblock_mirror_num); 7718c2ecf20Sopenharmony_ci if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes) 7728c2ecf20Sopenharmony_ci return -1; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci page = read_cache_page_gfp(mapping, dev_bytenr >> PAGE_SHIFT, GFP_NOFS); 7758c2ecf20Sopenharmony_ci if (IS_ERR(page)) 7768c2ecf20Sopenharmony_ci return -1; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci super_tmp = page_address(page); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci if (btrfs_super_bytenr(super_tmp) != dev_bytenr || 7818c2ecf20Sopenharmony_ci btrfs_super_magic(super_tmp) != BTRFS_MAGIC || 7828c2ecf20Sopenharmony_ci memcmp(device->uuid, super_tmp->dev_item.uuid, BTRFS_UUID_SIZE) || 7838c2ecf20Sopenharmony_ci btrfs_super_nodesize(super_tmp) != state->metablock_size || 7848c2ecf20Sopenharmony_ci btrfs_super_sectorsize(super_tmp) != state->datablock_size) { 7858c2ecf20Sopenharmony_ci ret = 0; 7868c2ecf20Sopenharmony_ci goto out; 7878c2ecf20Sopenharmony_ci } 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci superblock_tmp = 7908c2ecf20Sopenharmony_ci btrfsic_block_hashtable_lookup(superblock_bdev, 7918c2ecf20Sopenharmony_ci dev_bytenr, 7928c2ecf20Sopenharmony_ci &state->block_hashtable); 7938c2ecf20Sopenharmony_ci if (NULL == superblock_tmp) { 7948c2ecf20Sopenharmony_ci superblock_tmp = btrfsic_block_alloc(); 7958c2ecf20Sopenharmony_ci if (NULL == superblock_tmp) { 7968c2ecf20Sopenharmony_ci ret = -1; 7978c2ecf20Sopenharmony_ci goto out; 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci /* for superblock, only the dev_bytenr makes sense */ 8008c2ecf20Sopenharmony_ci superblock_tmp->dev_bytenr = dev_bytenr; 8018c2ecf20Sopenharmony_ci superblock_tmp->dev_state = dev_state; 8028c2ecf20Sopenharmony_ci superblock_tmp->logical_bytenr = dev_bytenr; 8038c2ecf20Sopenharmony_ci superblock_tmp->generation = btrfs_super_generation(super_tmp); 8048c2ecf20Sopenharmony_ci superblock_tmp->is_metadata = 1; 8058c2ecf20Sopenharmony_ci superblock_tmp->is_superblock = 1; 8068c2ecf20Sopenharmony_ci superblock_tmp->is_iodone = 1; 8078c2ecf20Sopenharmony_ci superblock_tmp->never_written = 0; 8088c2ecf20Sopenharmony_ci superblock_tmp->mirror_num = 1 + superblock_mirror_num; 8098c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE) 8108c2ecf20Sopenharmony_ci btrfs_info_in_rcu(fs_info, 8118c2ecf20Sopenharmony_ci "new initial S-block (bdev %p, %s) @%llu (%s/%llu/%d)", 8128c2ecf20Sopenharmony_ci superblock_bdev, 8138c2ecf20Sopenharmony_ci rcu_str_deref(device->name), dev_bytenr, 8148c2ecf20Sopenharmony_ci dev_state->name, dev_bytenr, 8158c2ecf20Sopenharmony_ci superblock_mirror_num); 8168c2ecf20Sopenharmony_ci list_add(&superblock_tmp->all_blocks_node, 8178c2ecf20Sopenharmony_ci &state->all_blocks_list); 8188c2ecf20Sopenharmony_ci btrfsic_block_hashtable_add(superblock_tmp, 8198c2ecf20Sopenharmony_ci &state->block_hashtable); 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci /* select the one with the highest generation field */ 8238c2ecf20Sopenharmony_ci if (btrfs_super_generation(super_tmp) > 8248c2ecf20Sopenharmony_ci state->max_superblock_generation || 8258c2ecf20Sopenharmony_ci 0 == state->max_superblock_generation) { 8268c2ecf20Sopenharmony_ci memcpy(selected_super, super_tmp, sizeof(*selected_super)); 8278c2ecf20Sopenharmony_ci *selected_dev_state = dev_state; 8288c2ecf20Sopenharmony_ci state->max_superblock_generation = 8298c2ecf20Sopenharmony_ci btrfs_super_generation(super_tmp); 8308c2ecf20Sopenharmony_ci state->latest_superblock = superblock_tmp; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci for (pass = 0; pass < 3; pass++) { 8348c2ecf20Sopenharmony_ci u64 next_bytenr; 8358c2ecf20Sopenharmony_ci int num_copies; 8368c2ecf20Sopenharmony_ci int mirror_num; 8378c2ecf20Sopenharmony_ci const char *additional_string = NULL; 8388c2ecf20Sopenharmony_ci struct btrfs_disk_key tmp_disk_key; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci tmp_disk_key.type = BTRFS_ROOT_ITEM_KEY; 8418c2ecf20Sopenharmony_ci tmp_disk_key.offset = 0; 8428c2ecf20Sopenharmony_ci switch (pass) { 8438c2ecf20Sopenharmony_ci case 0: 8448c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 8458c2ecf20Sopenharmony_ci BTRFS_ROOT_TREE_OBJECTID); 8468c2ecf20Sopenharmony_ci additional_string = "initial root "; 8478c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_root(super_tmp); 8488c2ecf20Sopenharmony_ci break; 8498c2ecf20Sopenharmony_ci case 1: 8508c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 8518c2ecf20Sopenharmony_ci BTRFS_CHUNK_TREE_OBJECTID); 8528c2ecf20Sopenharmony_ci additional_string = "initial chunk "; 8538c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_chunk_root(super_tmp); 8548c2ecf20Sopenharmony_ci break; 8558c2ecf20Sopenharmony_ci case 2: 8568c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 8578c2ecf20Sopenharmony_ci BTRFS_TREE_LOG_OBJECTID); 8588c2ecf20Sopenharmony_ci additional_string = "initial log "; 8598c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_log_root(super_tmp); 8608c2ecf20Sopenharmony_ci if (0 == next_bytenr) 8618c2ecf20Sopenharmony_ci continue; 8628c2ecf20Sopenharmony_ci break; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci num_copies = btrfs_num_copies(fs_info, next_bytenr, 8668c2ecf20Sopenharmony_ci state->metablock_size); 8678c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) 8688c2ecf20Sopenharmony_ci pr_info("num_copies(log_bytenr=%llu) = %d\n", 8698c2ecf20Sopenharmony_ci next_bytenr, num_copies); 8708c2ecf20Sopenharmony_ci for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) { 8718c2ecf20Sopenharmony_ci struct btrfsic_block *next_block; 8728c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx tmp_next_block_ctx; 8738c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci if (btrfsic_map_block(state, next_bytenr, 8768c2ecf20Sopenharmony_ci state->metablock_size, 8778c2ecf20Sopenharmony_ci &tmp_next_block_ctx, 8788c2ecf20Sopenharmony_ci mirror_num)) { 8798c2ecf20Sopenharmony_ci pr_info("btrfsic: btrfsic_map_block(bytenr @%llu, mirror %d) failed!\n", 8808c2ecf20Sopenharmony_ci next_bytenr, mirror_num); 8818c2ecf20Sopenharmony_ci ret = -1; 8828c2ecf20Sopenharmony_ci goto out; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci next_block = btrfsic_block_lookup_or_add( 8868c2ecf20Sopenharmony_ci state, &tmp_next_block_ctx, 8878c2ecf20Sopenharmony_ci additional_string, 1, 1, 0, 8888c2ecf20Sopenharmony_ci mirror_num, NULL); 8898c2ecf20Sopenharmony_ci if (NULL == next_block) { 8908c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&tmp_next_block_ctx); 8918c2ecf20Sopenharmony_ci ret = -1; 8928c2ecf20Sopenharmony_ci goto out; 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci next_block->disk_key = tmp_disk_key; 8968c2ecf20Sopenharmony_ci next_block->generation = BTRFSIC_GENERATION_UNKNOWN; 8978c2ecf20Sopenharmony_ci l = btrfsic_block_link_lookup_or_add( 8988c2ecf20Sopenharmony_ci state, &tmp_next_block_ctx, 8998c2ecf20Sopenharmony_ci next_block, superblock_tmp, 9008c2ecf20Sopenharmony_ci BTRFSIC_GENERATION_UNKNOWN); 9018c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&tmp_next_block_ctx); 9028c2ecf20Sopenharmony_ci if (NULL == l) { 9038c2ecf20Sopenharmony_ci ret = -1; 9048c2ecf20Sopenharmony_ci goto out; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES) 9098c2ecf20Sopenharmony_ci btrfsic_dump_tree_sub(state, superblock_tmp, 0); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ciout: 9128c2ecf20Sopenharmony_ci put_page(page); 9138c2ecf20Sopenharmony_ci return ret; 9148c2ecf20Sopenharmony_ci} 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_cistatic struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void) 9178c2ecf20Sopenharmony_ci{ 9188c2ecf20Sopenharmony_ci struct btrfsic_stack_frame *sf; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci sf = kzalloc(sizeof(*sf), GFP_NOFS); 9218c2ecf20Sopenharmony_ci if (sf) 9228c2ecf20Sopenharmony_ci sf->magic = BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER; 9238c2ecf20Sopenharmony_ci return sf; 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_cistatic void btrfsic_stack_frame_free(struct btrfsic_stack_frame *sf) 9278c2ecf20Sopenharmony_ci{ 9288c2ecf20Sopenharmony_ci BUG_ON(!(NULL == sf || 9298c2ecf20Sopenharmony_ci BTRFSIC_BLOCK_STACK_FRAME_MAGIC_NUMBER == sf->magic)); 9308c2ecf20Sopenharmony_ci kfree(sf); 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_cistatic noinline_for_stack int btrfsic_process_metablock( 9348c2ecf20Sopenharmony_ci struct btrfsic_state *state, 9358c2ecf20Sopenharmony_ci struct btrfsic_block *const first_block, 9368c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *const first_block_ctx, 9378c2ecf20Sopenharmony_ci int first_limit_nesting, int force_iodone_flag) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci struct btrfsic_stack_frame initial_stack_frame = { 0 }; 9408c2ecf20Sopenharmony_ci struct btrfsic_stack_frame *sf; 9418c2ecf20Sopenharmony_ci struct btrfsic_stack_frame *next_stack; 9428c2ecf20Sopenharmony_ci struct btrfs_header *const first_hdr = 9438c2ecf20Sopenharmony_ci (struct btrfs_header *)first_block_ctx->datav[0]; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci BUG_ON(!first_hdr); 9468c2ecf20Sopenharmony_ci sf = &initial_stack_frame; 9478c2ecf20Sopenharmony_ci sf->error = 0; 9488c2ecf20Sopenharmony_ci sf->i = -1; 9498c2ecf20Sopenharmony_ci sf->limit_nesting = first_limit_nesting; 9508c2ecf20Sopenharmony_ci sf->block = first_block; 9518c2ecf20Sopenharmony_ci sf->block_ctx = first_block_ctx; 9528c2ecf20Sopenharmony_ci sf->next_block = NULL; 9538c2ecf20Sopenharmony_ci sf->hdr = first_hdr; 9548c2ecf20Sopenharmony_ci sf->prev = NULL; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_cicontinue_with_new_stack_frame: 9578c2ecf20Sopenharmony_ci sf->block->generation = le64_to_cpu(sf->hdr->generation); 9588c2ecf20Sopenharmony_ci if (0 == sf->hdr->level) { 9598c2ecf20Sopenharmony_ci struct btrfs_leaf *const leafhdr = 9608c2ecf20Sopenharmony_ci (struct btrfs_leaf *)sf->hdr; 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci if (-1 == sf->i) { 9638c2ecf20Sopenharmony_ci sf->nr = btrfs_stack_header_nritems(&leafhdr->header); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 9668c2ecf20Sopenharmony_ci pr_info("leaf %llu items %d generation %llu owner %llu\n", 9678c2ecf20Sopenharmony_ci sf->block_ctx->start, sf->nr, 9688c2ecf20Sopenharmony_ci btrfs_stack_header_generation( 9698c2ecf20Sopenharmony_ci &leafhdr->header), 9708c2ecf20Sopenharmony_ci btrfs_stack_header_owner( 9718c2ecf20Sopenharmony_ci &leafhdr->header)); 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_cicontinue_with_current_leaf_stack_frame: 9758c2ecf20Sopenharmony_ci if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) { 9768c2ecf20Sopenharmony_ci sf->i++; 9778c2ecf20Sopenharmony_ci sf->num_copies = 0; 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (sf->i < sf->nr) { 9818c2ecf20Sopenharmony_ci struct btrfs_item disk_item; 9828c2ecf20Sopenharmony_ci u32 disk_item_offset = 9838c2ecf20Sopenharmony_ci (uintptr_t)(leafhdr->items + sf->i) - 9848c2ecf20Sopenharmony_ci (uintptr_t)leafhdr; 9858c2ecf20Sopenharmony_ci struct btrfs_disk_key *disk_key; 9868c2ecf20Sopenharmony_ci u8 type; 9878c2ecf20Sopenharmony_ci u32 item_offset; 9888c2ecf20Sopenharmony_ci u32 item_size; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci if (disk_item_offset + sizeof(struct btrfs_item) > 9918c2ecf20Sopenharmony_ci sf->block_ctx->len) { 9928c2ecf20Sopenharmony_cileaf_item_out_of_bounce_error: 9938c2ecf20Sopenharmony_ci pr_info("btrfsic: leaf item out of bounce at logical %llu, dev %s\n", 9948c2ecf20Sopenharmony_ci sf->block_ctx->start, 9958c2ecf20Sopenharmony_ci sf->block_ctx->dev->name); 9968c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci btrfsic_read_from_block_data(sf->block_ctx, 9998c2ecf20Sopenharmony_ci &disk_item, 10008c2ecf20Sopenharmony_ci disk_item_offset, 10018c2ecf20Sopenharmony_ci sizeof(struct btrfs_item)); 10028c2ecf20Sopenharmony_ci item_offset = btrfs_stack_item_offset(&disk_item); 10038c2ecf20Sopenharmony_ci item_size = btrfs_stack_item_size(&disk_item); 10048c2ecf20Sopenharmony_ci disk_key = &disk_item.key; 10058c2ecf20Sopenharmony_ci type = btrfs_disk_key_type(disk_key); 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (BTRFS_ROOT_ITEM_KEY == type) { 10088c2ecf20Sopenharmony_ci struct btrfs_root_item root_item; 10098c2ecf20Sopenharmony_ci u32 root_item_offset; 10108c2ecf20Sopenharmony_ci u64 next_bytenr; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci root_item_offset = item_offset + 10138c2ecf20Sopenharmony_ci offsetof(struct btrfs_leaf, items); 10148c2ecf20Sopenharmony_ci if (root_item_offset + item_size > 10158c2ecf20Sopenharmony_ci sf->block_ctx->len) 10168c2ecf20Sopenharmony_ci goto leaf_item_out_of_bounce_error; 10178c2ecf20Sopenharmony_ci btrfsic_read_from_block_data( 10188c2ecf20Sopenharmony_ci sf->block_ctx, &root_item, 10198c2ecf20Sopenharmony_ci root_item_offset, 10208c2ecf20Sopenharmony_ci item_size); 10218c2ecf20Sopenharmony_ci next_bytenr = btrfs_root_bytenr(&root_item); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci sf->error = 10248c2ecf20Sopenharmony_ci btrfsic_create_link_to_next_block( 10258c2ecf20Sopenharmony_ci state, 10268c2ecf20Sopenharmony_ci sf->block, 10278c2ecf20Sopenharmony_ci sf->block_ctx, 10288c2ecf20Sopenharmony_ci next_bytenr, 10298c2ecf20Sopenharmony_ci sf->limit_nesting, 10308c2ecf20Sopenharmony_ci &sf->next_block_ctx, 10318c2ecf20Sopenharmony_ci &sf->next_block, 10328c2ecf20Sopenharmony_ci force_iodone_flag, 10338c2ecf20Sopenharmony_ci &sf->num_copies, 10348c2ecf20Sopenharmony_ci &sf->mirror_num, 10358c2ecf20Sopenharmony_ci disk_key, 10368c2ecf20Sopenharmony_ci btrfs_root_generation( 10378c2ecf20Sopenharmony_ci &root_item)); 10388c2ecf20Sopenharmony_ci if (sf->error) 10398c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci if (NULL != sf->next_block) { 10428c2ecf20Sopenharmony_ci struct btrfs_header *const next_hdr = 10438c2ecf20Sopenharmony_ci (struct btrfs_header *) 10448c2ecf20Sopenharmony_ci sf->next_block_ctx.datav[0]; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci next_stack = 10478c2ecf20Sopenharmony_ci btrfsic_stack_frame_alloc(); 10488c2ecf20Sopenharmony_ci if (NULL == next_stack) { 10498c2ecf20Sopenharmony_ci sf->error = -1; 10508c2ecf20Sopenharmony_ci btrfsic_release_block_ctx( 10518c2ecf20Sopenharmony_ci &sf-> 10528c2ecf20Sopenharmony_ci next_block_ctx); 10538c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 10548c2ecf20Sopenharmony_ci } 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci next_stack->i = -1; 10578c2ecf20Sopenharmony_ci next_stack->block = sf->next_block; 10588c2ecf20Sopenharmony_ci next_stack->block_ctx = 10598c2ecf20Sopenharmony_ci &sf->next_block_ctx; 10608c2ecf20Sopenharmony_ci next_stack->next_block = NULL; 10618c2ecf20Sopenharmony_ci next_stack->hdr = next_hdr; 10628c2ecf20Sopenharmony_ci next_stack->limit_nesting = 10638c2ecf20Sopenharmony_ci sf->limit_nesting - 1; 10648c2ecf20Sopenharmony_ci next_stack->prev = sf; 10658c2ecf20Sopenharmony_ci sf = next_stack; 10668c2ecf20Sopenharmony_ci goto continue_with_new_stack_frame; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci } else if (BTRFS_EXTENT_DATA_KEY == type && 10698c2ecf20Sopenharmony_ci state->include_extent_data) { 10708c2ecf20Sopenharmony_ci sf->error = btrfsic_handle_extent_data( 10718c2ecf20Sopenharmony_ci state, 10728c2ecf20Sopenharmony_ci sf->block, 10738c2ecf20Sopenharmony_ci sf->block_ctx, 10748c2ecf20Sopenharmony_ci item_offset, 10758c2ecf20Sopenharmony_ci force_iodone_flag); 10768c2ecf20Sopenharmony_ci if (sf->error) 10778c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci goto continue_with_current_leaf_stack_frame; 10818c2ecf20Sopenharmony_ci } 10828c2ecf20Sopenharmony_ci } else { 10838c2ecf20Sopenharmony_ci struct btrfs_node *const nodehdr = (struct btrfs_node *)sf->hdr; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci if (-1 == sf->i) { 10868c2ecf20Sopenharmony_ci sf->nr = btrfs_stack_header_nritems(&nodehdr->header); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 10898c2ecf20Sopenharmony_ci pr_info("node %llu level %d items %d generation %llu owner %llu\n", 10908c2ecf20Sopenharmony_ci sf->block_ctx->start, 10918c2ecf20Sopenharmony_ci nodehdr->header.level, sf->nr, 10928c2ecf20Sopenharmony_ci btrfs_stack_header_generation( 10938c2ecf20Sopenharmony_ci &nodehdr->header), 10948c2ecf20Sopenharmony_ci btrfs_stack_header_owner( 10958c2ecf20Sopenharmony_ci &nodehdr->header)); 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_cicontinue_with_current_node_stack_frame: 10998c2ecf20Sopenharmony_ci if (0 == sf->num_copies || sf->mirror_num > sf->num_copies) { 11008c2ecf20Sopenharmony_ci sf->i++; 11018c2ecf20Sopenharmony_ci sf->num_copies = 0; 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (sf->i < sf->nr) { 11058c2ecf20Sopenharmony_ci struct btrfs_key_ptr key_ptr; 11068c2ecf20Sopenharmony_ci u32 key_ptr_offset; 11078c2ecf20Sopenharmony_ci u64 next_bytenr; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci key_ptr_offset = (uintptr_t)(nodehdr->ptrs + sf->i) - 11108c2ecf20Sopenharmony_ci (uintptr_t)nodehdr; 11118c2ecf20Sopenharmony_ci if (key_ptr_offset + sizeof(struct btrfs_key_ptr) > 11128c2ecf20Sopenharmony_ci sf->block_ctx->len) { 11138c2ecf20Sopenharmony_ci pr_info("btrfsic: node item out of bounce at logical %llu, dev %s\n", 11148c2ecf20Sopenharmony_ci sf->block_ctx->start, 11158c2ecf20Sopenharmony_ci sf->block_ctx->dev->name); 11168c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci btrfsic_read_from_block_data( 11198c2ecf20Sopenharmony_ci sf->block_ctx, &key_ptr, key_ptr_offset, 11208c2ecf20Sopenharmony_ci sizeof(struct btrfs_key_ptr)); 11218c2ecf20Sopenharmony_ci next_bytenr = btrfs_stack_key_blockptr(&key_ptr); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci sf->error = btrfsic_create_link_to_next_block( 11248c2ecf20Sopenharmony_ci state, 11258c2ecf20Sopenharmony_ci sf->block, 11268c2ecf20Sopenharmony_ci sf->block_ctx, 11278c2ecf20Sopenharmony_ci next_bytenr, 11288c2ecf20Sopenharmony_ci sf->limit_nesting, 11298c2ecf20Sopenharmony_ci &sf->next_block_ctx, 11308c2ecf20Sopenharmony_ci &sf->next_block, 11318c2ecf20Sopenharmony_ci force_iodone_flag, 11328c2ecf20Sopenharmony_ci &sf->num_copies, 11338c2ecf20Sopenharmony_ci &sf->mirror_num, 11348c2ecf20Sopenharmony_ci &key_ptr.key, 11358c2ecf20Sopenharmony_ci btrfs_stack_key_generation(&key_ptr)); 11368c2ecf20Sopenharmony_ci if (sf->error) 11378c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci if (NULL != sf->next_block) { 11408c2ecf20Sopenharmony_ci struct btrfs_header *const next_hdr = 11418c2ecf20Sopenharmony_ci (struct btrfs_header *) 11428c2ecf20Sopenharmony_ci sf->next_block_ctx.datav[0]; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci next_stack = btrfsic_stack_frame_alloc(); 11458c2ecf20Sopenharmony_ci if (NULL == next_stack) { 11468c2ecf20Sopenharmony_ci sf->error = -1; 11478c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci next_stack->i = -1; 11518c2ecf20Sopenharmony_ci next_stack->block = sf->next_block; 11528c2ecf20Sopenharmony_ci next_stack->block_ctx = &sf->next_block_ctx; 11538c2ecf20Sopenharmony_ci next_stack->next_block = NULL; 11548c2ecf20Sopenharmony_ci next_stack->hdr = next_hdr; 11558c2ecf20Sopenharmony_ci next_stack->limit_nesting = 11568c2ecf20Sopenharmony_ci sf->limit_nesting - 1; 11578c2ecf20Sopenharmony_ci next_stack->prev = sf; 11588c2ecf20Sopenharmony_ci sf = next_stack; 11598c2ecf20Sopenharmony_ci goto continue_with_new_stack_frame; 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci goto continue_with_current_node_stack_frame; 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cione_stack_frame_backwards: 11678c2ecf20Sopenharmony_ci if (NULL != sf->prev) { 11688c2ecf20Sopenharmony_ci struct btrfsic_stack_frame *const prev = sf->prev; 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci /* the one for the initial block is freed in the caller */ 11718c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(sf->block_ctx); 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci if (sf->error) { 11748c2ecf20Sopenharmony_ci prev->error = sf->error; 11758c2ecf20Sopenharmony_ci btrfsic_stack_frame_free(sf); 11768c2ecf20Sopenharmony_ci sf = prev; 11778c2ecf20Sopenharmony_ci goto one_stack_frame_backwards; 11788c2ecf20Sopenharmony_ci } 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci btrfsic_stack_frame_free(sf); 11818c2ecf20Sopenharmony_ci sf = prev; 11828c2ecf20Sopenharmony_ci goto continue_with_new_stack_frame; 11838c2ecf20Sopenharmony_ci } else { 11848c2ecf20Sopenharmony_ci BUG_ON(&initial_stack_frame != sf); 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci return sf->error; 11888c2ecf20Sopenharmony_ci} 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_cistatic void btrfsic_read_from_block_data( 11918c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 11928c2ecf20Sopenharmony_ci void *dstv, u32 offset, size_t len) 11938c2ecf20Sopenharmony_ci{ 11948c2ecf20Sopenharmony_ci size_t cur; 11958c2ecf20Sopenharmony_ci size_t pgoff; 11968c2ecf20Sopenharmony_ci char *kaddr; 11978c2ecf20Sopenharmony_ci char *dst = (char *)dstv; 11988c2ecf20Sopenharmony_ci size_t start_offset = offset_in_page(block_ctx->start); 11998c2ecf20Sopenharmony_ci unsigned long i = (start_offset + offset) >> PAGE_SHIFT; 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci WARN_ON(offset + len > block_ctx->len); 12028c2ecf20Sopenharmony_ci pgoff = offset_in_page(start_offset + offset); 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci while (len > 0) { 12058c2ecf20Sopenharmony_ci cur = min(len, ((size_t)PAGE_SIZE - pgoff)); 12068c2ecf20Sopenharmony_ci BUG_ON(i >= DIV_ROUND_UP(block_ctx->len, PAGE_SIZE)); 12078c2ecf20Sopenharmony_ci kaddr = block_ctx->datav[i]; 12088c2ecf20Sopenharmony_ci memcpy(dst, kaddr + pgoff, cur); 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci dst += cur; 12118c2ecf20Sopenharmony_ci len -= cur; 12128c2ecf20Sopenharmony_ci pgoff = 0; 12138c2ecf20Sopenharmony_ci i++; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic int btrfsic_create_link_to_next_block( 12188c2ecf20Sopenharmony_ci struct btrfsic_state *state, 12198c2ecf20Sopenharmony_ci struct btrfsic_block *block, 12208c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 12218c2ecf20Sopenharmony_ci u64 next_bytenr, 12228c2ecf20Sopenharmony_ci int limit_nesting, 12238c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *next_block_ctx, 12248c2ecf20Sopenharmony_ci struct btrfsic_block **next_blockp, 12258c2ecf20Sopenharmony_ci int force_iodone_flag, 12268c2ecf20Sopenharmony_ci int *num_copiesp, int *mirror_nump, 12278c2ecf20Sopenharmony_ci struct btrfs_disk_key *disk_key, 12288c2ecf20Sopenharmony_ci u64 parent_generation) 12298c2ecf20Sopenharmony_ci{ 12308c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = state->fs_info; 12318c2ecf20Sopenharmony_ci struct btrfsic_block *next_block = NULL; 12328c2ecf20Sopenharmony_ci int ret; 12338c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 12348c2ecf20Sopenharmony_ci int did_alloc_block_link; 12358c2ecf20Sopenharmony_ci int block_was_created; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci *next_blockp = NULL; 12388c2ecf20Sopenharmony_ci if (0 == *num_copiesp) { 12398c2ecf20Sopenharmony_ci *num_copiesp = btrfs_num_copies(fs_info, next_bytenr, 12408c2ecf20Sopenharmony_ci state->metablock_size); 12418c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) 12428c2ecf20Sopenharmony_ci pr_info("num_copies(log_bytenr=%llu) = %d\n", 12438c2ecf20Sopenharmony_ci next_bytenr, *num_copiesp); 12448c2ecf20Sopenharmony_ci *mirror_nump = 1; 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci if (*mirror_nump > *num_copiesp) 12488c2ecf20Sopenharmony_ci return 0; 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 12518c2ecf20Sopenharmony_ci pr_info("btrfsic_create_link_to_next_block(mirror_num=%d)\n", 12528c2ecf20Sopenharmony_ci *mirror_nump); 12538c2ecf20Sopenharmony_ci ret = btrfsic_map_block(state, next_bytenr, 12548c2ecf20Sopenharmony_ci state->metablock_size, 12558c2ecf20Sopenharmony_ci next_block_ctx, *mirror_nump); 12568c2ecf20Sopenharmony_ci if (ret) { 12578c2ecf20Sopenharmony_ci pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n", 12588c2ecf20Sopenharmony_ci next_bytenr, *mirror_nump); 12598c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(next_block_ctx); 12608c2ecf20Sopenharmony_ci *next_blockp = NULL; 12618c2ecf20Sopenharmony_ci return -1; 12628c2ecf20Sopenharmony_ci } 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci next_block = btrfsic_block_lookup_or_add(state, 12658c2ecf20Sopenharmony_ci next_block_ctx, "referenced ", 12668c2ecf20Sopenharmony_ci 1, force_iodone_flag, 12678c2ecf20Sopenharmony_ci !force_iodone_flag, 12688c2ecf20Sopenharmony_ci *mirror_nump, 12698c2ecf20Sopenharmony_ci &block_was_created); 12708c2ecf20Sopenharmony_ci if (NULL == next_block) { 12718c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(next_block_ctx); 12728c2ecf20Sopenharmony_ci *next_blockp = NULL; 12738c2ecf20Sopenharmony_ci return -1; 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci if (block_was_created) { 12768c2ecf20Sopenharmony_ci l = NULL; 12778c2ecf20Sopenharmony_ci next_block->generation = BTRFSIC_GENERATION_UNKNOWN; 12788c2ecf20Sopenharmony_ci } else { 12798c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) { 12808c2ecf20Sopenharmony_ci if (next_block->logical_bytenr != next_bytenr && 12818c2ecf20Sopenharmony_ci !(!next_block->is_metadata && 12828c2ecf20Sopenharmony_ci 0 == next_block->logical_bytenr)) 12838c2ecf20Sopenharmony_ci pr_info("Referenced block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n", 12848c2ecf20Sopenharmony_ci next_bytenr, next_block_ctx->dev->name, 12858c2ecf20Sopenharmony_ci next_block_ctx->dev_bytenr, *mirror_nump, 12868c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, 12878c2ecf20Sopenharmony_ci next_block), 12888c2ecf20Sopenharmony_ci next_block->logical_bytenr); 12898c2ecf20Sopenharmony_ci else 12908c2ecf20Sopenharmony_ci pr_info("Referenced block @%llu (%s/%llu/%d) found in hash table, %c.\n", 12918c2ecf20Sopenharmony_ci next_bytenr, next_block_ctx->dev->name, 12928c2ecf20Sopenharmony_ci next_block_ctx->dev_bytenr, *mirror_nump, 12938c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, 12948c2ecf20Sopenharmony_ci next_block)); 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci next_block->logical_bytenr = next_bytenr; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci next_block->mirror_num = *mirror_nump; 12998c2ecf20Sopenharmony_ci l = btrfsic_block_link_hashtable_lookup( 13008c2ecf20Sopenharmony_ci next_block_ctx->dev->bdev, 13018c2ecf20Sopenharmony_ci next_block_ctx->dev_bytenr, 13028c2ecf20Sopenharmony_ci block_ctx->dev->bdev, 13038c2ecf20Sopenharmony_ci block_ctx->dev_bytenr, 13048c2ecf20Sopenharmony_ci &state->block_link_hashtable); 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci next_block->disk_key = *disk_key; 13088c2ecf20Sopenharmony_ci if (NULL == l) { 13098c2ecf20Sopenharmony_ci l = btrfsic_block_link_alloc(); 13108c2ecf20Sopenharmony_ci if (NULL == l) { 13118c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(next_block_ctx); 13128c2ecf20Sopenharmony_ci *next_blockp = NULL; 13138c2ecf20Sopenharmony_ci return -1; 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci did_alloc_block_link = 1; 13178c2ecf20Sopenharmony_ci l->block_ref_to = next_block; 13188c2ecf20Sopenharmony_ci l->block_ref_from = block; 13198c2ecf20Sopenharmony_ci l->ref_cnt = 1; 13208c2ecf20Sopenharmony_ci l->parent_generation = parent_generation; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 13238c2ecf20Sopenharmony_ci btrfsic_print_add_link(state, l); 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci list_add(&l->node_ref_to, &block->ref_to_list); 13268c2ecf20Sopenharmony_ci list_add(&l->node_ref_from, &next_block->ref_from_list); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci btrfsic_block_link_hashtable_add(l, 13298c2ecf20Sopenharmony_ci &state->block_link_hashtable); 13308c2ecf20Sopenharmony_ci } else { 13318c2ecf20Sopenharmony_ci did_alloc_block_link = 0; 13328c2ecf20Sopenharmony_ci if (0 == limit_nesting) { 13338c2ecf20Sopenharmony_ci l->ref_cnt++; 13348c2ecf20Sopenharmony_ci l->parent_generation = parent_generation; 13358c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 13368c2ecf20Sopenharmony_ci btrfsic_print_add_link(state, l); 13378c2ecf20Sopenharmony_ci } 13388c2ecf20Sopenharmony_ci } 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci if (limit_nesting > 0 && did_alloc_block_link) { 13418c2ecf20Sopenharmony_ci ret = btrfsic_read_block(state, next_block_ctx); 13428c2ecf20Sopenharmony_ci if (ret < (int)next_block_ctx->len) { 13438c2ecf20Sopenharmony_ci pr_info("btrfsic: read block @logical %llu failed!\n", 13448c2ecf20Sopenharmony_ci next_bytenr); 13458c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(next_block_ctx); 13468c2ecf20Sopenharmony_ci *next_blockp = NULL; 13478c2ecf20Sopenharmony_ci return -1; 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci *next_blockp = next_block; 13518c2ecf20Sopenharmony_ci } else { 13528c2ecf20Sopenharmony_ci *next_blockp = NULL; 13538c2ecf20Sopenharmony_ci } 13548c2ecf20Sopenharmony_ci (*mirror_nump)++; 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci return 0; 13578c2ecf20Sopenharmony_ci} 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_cistatic int btrfsic_handle_extent_data( 13608c2ecf20Sopenharmony_ci struct btrfsic_state *state, 13618c2ecf20Sopenharmony_ci struct btrfsic_block *block, 13628c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 13638c2ecf20Sopenharmony_ci u32 item_offset, int force_iodone_flag) 13648c2ecf20Sopenharmony_ci{ 13658c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = state->fs_info; 13668c2ecf20Sopenharmony_ci struct btrfs_file_extent_item file_extent_item; 13678c2ecf20Sopenharmony_ci u64 file_extent_item_offset; 13688c2ecf20Sopenharmony_ci u64 next_bytenr; 13698c2ecf20Sopenharmony_ci u64 num_bytes; 13708c2ecf20Sopenharmony_ci u64 generation; 13718c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 13728c2ecf20Sopenharmony_ci int ret; 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci file_extent_item_offset = offsetof(struct btrfs_leaf, items) + 13758c2ecf20Sopenharmony_ci item_offset; 13768c2ecf20Sopenharmony_ci if (file_extent_item_offset + 13778c2ecf20Sopenharmony_ci offsetof(struct btrfs_file_extent_item, disk_num_bytes) > 13788c2ecf20Sopenharmony_ci block_ctx->len) { 13798c2ecf20Sopenharmony_ci pr_info("btrfsic: file item out of bounce at logical %llu, dev %s\n", 13808c2ecf20Sopenharmony_ci block_ctx->start, block_ctx->dev->name); 13818c2ecf20Sopenharmony_ci return -1; 13828c2ecf20Sopenharmony_ci } 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci btrfsic_read_from_block_data(block_ctx, &file_extent_item, 13858c2ecf20Sopenharmony_ci file_extent_item_offset, 13868c2ecf20Sopenharmony_ci offsetof(struct btrfs_file_extent_item, disk_num_bytes)); 13878c2ecf20Sopenharmony_ci if (BTRFS_FILE_EXTENT_REG != file_extent_item.type || 13888c2ecf20Sopenharmony_ci btrfs_stack_file_extent_disk_bytenr(&file_extent_item) == 0) { 13898c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE) 13908c2ecf20Sopenharmony_ci pr_info("extent_data: type %u, disk_bytenr = %llu\n", 13918c2ecf20Sopenharmony_ci file_extent_item.type, 13928c2ecf20Sopenharmony_ci btrfs_stack_file_extent_disk_bytenr( 13938c2ecf20Sopenharmony_ci &file_extent_item)); 13948c2ecf20Sopenharmony_ci return 0; 13958c2ecf20Sopenharmony_ci } 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci if (file_extent_item_offset + sizeof(struct btrfs_file_extent_item) > 13988c2ecf20Sopenharmony_ci block_ctx->len) { 13998c2ecf20Sopenharmony_ci pr_info("btrfsic: file item out of bounce at logical %llu, dev %s\n", 14008c2ecf20Sopenharmony_ci block_ctx->start, block_ctx->dev->name); 14018c2ecf20Sopenharmony_ci return -1; 14028c2ecf20Sopenharmony_ci } 14038c2ecf20Sopenharmony_ci btrfsic_read_from_block_data(block_ctx, &file_extent_item, 14048c2ecf20Sopenharmony_ci file_extent_item_offset, 14058c2ecf20Sopenharmony_ci sizeof(struct btrfs_file_extent_item)); 14068c2ecf20Sopenharmony_ci next_bytenr = btrfs_stack_file_extent_disk_bytenr(&file_extent_item); 14078c2ecf20Sopenharmony_ci if (btrfs_stack_file_extent_compression(&file_extent_item) == 14088c2ecf20Sopenharmony_ci BTRFS_COMPRESS_NONE) { 14098c2ecf20Sopenharmony_ci next_bytenr += btrfs_stack_file_extent_offset(&file_extent_item); 14108c2ecf20Sopenharmony_ci num_bytes = btrfs_stack_file_extent_num_bytes(&file_extent_item); 14118c2ecf20Sopenharmony_ci } else { 14128c2ecf20Sopenharmony_ci num_bytes = btrfs_stack_file_extent_disk_num_bytes(&file_extent_item); 14138c2ecf20Sopenharmony_ci } 14148c2ecf20Sopenharmony_ci generation = btrfs_stack_file_extent_generation(&file_extent_item); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE) 14178c2ecf20Sopenharmony_ci pr_info("extent_data: type %u, disk_bytenr = %llu, offset = %llu, num_bytes = %llu\n", 14188c2ecf20Sopenharmony_ci file_extent_item.type, 14198c2ecf20Sopenharmony_ci btrfs_stack_file_extent_disk_bytenr(&file_extent_item), 14208c2ecf20Sopenharmony_ci btrfs_stack_file_extent_offset(&file_extent_item), 14218c2ecf20Sopenharmony_ci num_bytes); 14228c2ecf20Sopenharmony_ci while (num_bytes > 0) { 14238c2ecf20Sopenharmony_ci u32 chunk_len; 14248c2ecf20Sopenharmony_ci int num_copies; 14258c2ecf20Sopenharmony_ci int mirror_num; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci if (num_bytes > state->datablock_size) 14288c2ecf20Sopenharmony_ci chunk_len = state->datablock_size; 14298c2ecf20Sopenharmony_ci else 14308c2ecf20Sopenharmony_ci chunk_len = num_bytes; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci num_copies = btrfs_num_copies(fs_info, next_bytenr, 14338c2ecf20Sopenharmony_ci state->datablock_size); 14348c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) 14358c2ecf20Sopenharmony_ci pr_info("num_copies(log_bytenr=%llu) = %d\n", 14368c2ecf20Sopenharmony_ci next_bytenr, num_copies); 14378c2ecf20Sopenharmony_ci for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) { 14388c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx next_block_ctx; 14398c2ecf20Sopenharmony_ci struct btrfsic_block *next_block; 14408c2ecf20Sopenharmony_ci int block_was_created; 14418c2ecf20Sopenharmony_ci 14428c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 14438c2ecf20Sopenharmony_ci pr_info("btrfsic_handle_extent_data(mirror_num=%d)\n", 14448c2ecf20Sopenharmony_ci mirror_num); 14458c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERY_VERBOSE) 14468c2ecf20Sopenharmony_ci pr_info("\tdisk_bytenr = %llu, num_bytes %u\n", 14478c2ecf20Sopenharmony_ci next_bytenr, chunk_len); 14488c2ecf20Sopenharmony_ci ret = btrfsic_map_block(state, next_bytenr, 14498c2ecf20Sopenharmony_ci chunk_len, &next_block_ctx, 14508c2ecf20Sopenharmony_ci mirror_num); 14518c2ecf20Sopenharmony_ci if (ret) { 14528c2ecf20Sopenharmony_ci pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n", 14538c2ecf20Sopenharmony_ci next_bytenr, mirror_num); 14548c2ecf20Sopenharmony_ci return -1; 14558c2ecf20Sopenharmony_ci } 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci next_block = btrfsic_block_lookup_or_add( 14588c2ecf20Sopenharmony_ci state, 14598c2ecf20Sopenharmony_ci &next_block_ctx, 14608c2ecf20Sopenharmony_ci "referenced ", 14618c2ecf20Sopenharmony_ci 0, 14628c2ecf20Sopenharmony_ci force_iodone_flag, 14638c2ecf20Sopenharmony_ci !force_iodone_flag, 14648c2ecf20Sopenharmony_ci mirror_num, 14658c2ecf20Sopenharmony_ci &block_was_created); 14668c2ecf20Sopenharmony_ci if (NULL == next_block) { 14678c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&next_block_ctx); 14688c2ecf20Sopenharmony_ci return -1; 14698c2ecf20Sopenharmony_ci } 14708c2ecf20Sopenharmony_ci if (!block_was_created) { 14718c2ecf20Sopenharmony_ci if ((state->print_mask & 14728c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_VERBOSE) && 14738c2ecf20Sopenharmony_ci next_block->logical_bytenr != next_bytenr && 14748c2ecf20Sopenharmony_ci !(!next_block->is_metadata && 14758c2ecf20Sopenharmony_ci 0 == next_block->logical_bytenr)) { 14768c2ecf20Sopenharmony_ci pr_info("Referenced block @%llu (%s/%llu/%d) found in hash table, D, bytenr mismatch (!= stored %llu).\n", 14778c2ecf20Sopenharmony_ci next_bytenr, 14788c2ecf20Sopenharmony_ci next_block_ctx.dev->name, 14798c2ecf20Sopenharmony_ci next_block_ctx.dev_bytenr, 14808c2ecf20Sopenharmony_ci mirror_num, 14818c2ecf20Sopenharmony_ci next_block->logical_bytenr); 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci next_block->logical_bytenr = next_bytenr; 14848c2ecf20Sopenharmony_ci next_block->mirror_num = mirror_num; 14858c2ecf20Sopenharmony_ci } 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci l = btrfsic_block_link_lookup_or_add(state, 14888c2ecf20Sopenharmony_ci &next_block_ctx, 14898c2ecf20Sopenharmony_ci next_block, block, 14908c2ecf20Sopenharmony_ci generation); 14918c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&next_block_ctx); 14928c2ecf20Sopenharmony_ci if (NULL == l) 14938c2ecf20Sopenharmony_ci return -1; 14948c2ecf20Sopenharmony_ci } 14958c2ecf20Sopenharmony_ci 14968c2ecf20Sopenharmony_ci next_bytenr += chunk_len; 14978c2ecf20Sopenharmony_ci num_bytes -= chunk_len; 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci return 0; 15018c2ecf20Sopenharmony_ci} 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_cistatic int btrfsic_map_block(struct btrfsic_state *state, u64 bytenr, u32 len, 15048c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx_out, 15058c2ecf20Sopenharmony_ci int mirror_num) 15068c2ecf20Sopenharmony_ci{ 15078c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = state->fs_info; 15088c2ecf20Sopenharmony_ci int ret; 15098c2ecf20Sopenharmony_ci u64 length; 15108c2ecf20Sopenharmony_ci struct btrfs_bio *multi = NULL; 15118c2ecf20Sopenharmony_ci struct btrfs_device *device; 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci length = len; 15148c2ecf20Sopenharmony_ci ret = btrfs_map_block(fs_info, BTRFS_MAP_READ, 15158c2ecf20Sopenharmony_ci bytenr, &length, &multi, mirror_num); 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci if (ret) { 15188c2ecf20Sopenharmony_ci block_ctx_out->start = 0; 15198c2ecf20Sopenharmony_ci block_ctx_out->dev_bytenr = 0; 15208c2ecf20Sopenharmony_ci block_ctx_out->len = 0; 15218c2ecf20Sopenharmony_ci block_ctx_out->dev = NULL; 15228c2ecf20Sopenharmony_ci block_ctx_out->datav = NULL; 15238c2ecf20Sopenharmony_ci block_ctx_out->pagev = NULL; 15248c2ecf20Sopenharmony_ci block_ctx_out->mem_to_free = NULL; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci return ret; 15278c2ecf20Sopenharmony_ci } 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci device = multi->stripes[0].dev; 15308c2ecf20Sopenharmony_ci if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state) || 15318c2ecf20Sopenharmony_ci !device->bdev || !device->name) 15328c2ecf20Sopenharmony_ci block_ctx_out->dev = NULL; 15338c2ecf20Sopenharmony_ci else 15348c2ecf20Sopenharmony_ci block_ctx_out->dev = btrfsic_dev_state_lookup( 15358c2ecf20Sopenharmony_ci device->bdev->bd_dev); 15368c2ecf20Sopenharmony_ci block_ctx_out->dev_bytenr = multi->stripes[0].physical; 15378c2ecf20Sopenharmony_ci block_ctx_out->start = bytenr; 15388c2ecf20Sopenharmony_ci block_ctx_out->len = len; 15398c2ecf20Sopenharmony_ci block_ctx_out->datav = NULL; 15408c2ecf20Sopenharmony_ci block_ctx_out->pagev = NULL; 15418c2ecf20Sopenharmony_ci block_ctx_out->mem_to_free = NULL; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci kfree(multi); 15448c2ecf20Sopenharmony_ci if (NULL == block_ctx_out->dev) { 15458c2ecf20Sopenharmony_ci ret = -ENXIO; 15468c2ecf20Sopenharmony_ci pr_info("btrfsic: error, cannot lookup dev (#1)!\n"); 15478c2ecf20Sopenharmony_ci } 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci return ret; 15508c2ecf20Sopenharmony_ci} 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_cistatic void btrfsic_release_block_ctx(struct btrfsic_block_data_ctx *block_ctx) 15538c2ecf20Sopenharmony_ci{ 15548c2ecf20Sopenharmony_ci if (block_ctx->mem_to_free) { 15558c2ecf20Sopenharmony_ci unsigned int num_pages; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci BUG_ON(!block_ctx->datav); 15588c2ecf20Sopenharmony_ci BUG_ON(!block_ctx->pagev); 15598c2ecf20Sopenharmony_ci num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >> 15608c2ecf20Sopenharmony_ci PAGE_SHIFT; 15618c2ecf20Sopenharmony_ci while (num_pages > 0) { 15628c2ecf20Sopenharmony_ci num_pages--; 15638c2ecf20Sopenharmony_ci if (block_ctx->datav[num_pages]) { 15648c2ecf20Sopenharmony_ci kunmap(block_ctx->pagev[num_pages]); 15658c2ecf20Sopenharmony_ci block_ctx->datav[num_pages] = NULL; 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci if (block_ctx->pagev[num_pages]) { 15688c2ecf20Sopenharmony_ci __free_page(block_ctx->pagev[num_pages]); 15698c2ecf20Sopenharmony_ci block_ctx->pagev[num_pages] = NULL; 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci } 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci kfree(block_ctx->mem_to_free); 15748c2ecf20Sopenharmony_ci block_ctx->mem_to_free = NULL; 15758c2ecf20Sopenharmony_ci block_ctx->pagev = NULL; 15768c2ecf20Sopenharmony_ci block_ctx->datav = NULL; 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci} 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_cistatic int btrfsic_read_block(struct btrfsic_state *state, 15818c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx) 15828c2ecf20Sopenharmony_ci{ 15838c2ecf20Sopenharmony_ci unsigned int num_pages; 15848c2ecf20Sopenharmony_ci unsigned int i; 15858c2ecf20Sopenharmony_ci size_t size; 15868c2ecf20Sopenharmony_ci u64 dev_bytenr; 15878c2ecf20Sopenharmony_ci int ret; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci BUG_ON(block_ctx->datav); 15908c2ecf20Sopenharmony_ci BUG_ON(block_ctx->pagev); 15918c2ecf20Sopenharmony_ci BUG_ON(block_ctx->mem_to_free); 15928c2ecf20Sopenharmony_ci if (!PAGE_ALIGNED(block_ctx->dev_bytenr)) { 15938c2ecf20Sopenharmony_ci pr_info("btrfsic: read_block() with unaligned bytenr %llu\n", 15948c2ecf20Sopenharmony_ci block_ctx->dev_bytenr); 15958c2ecf20Sopenharmony_ci return -1; 15968c2ecf20Sopenharmony_ci } 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >> 15998c2ecf20Sopenharmony_ci PAGE_SHIFT; 16008c2ecf20Sopenharmony_ci size = sizeof(*block_ctx->datav) + sizeof(*block_ctx->pagev); 16018c2ecf20Sopenharmony_ci block_ctx->mem_to_free = kcalloc(num_pages, size, GFP_NOFS); 16028c2ecf20Sopenharmony_ci if (!block_ctx->mem_to_free) 16038c2ecf20Sopenharmony_ci return -ENOMEM; 16048c2ecf20Sopenharmony_ci block_ctx->datav = block_ctx->mem_to_free; 16058c2ecf20Sopenharmony_ci block_ctx->pagev = (struct page **)(block_ctx->datav + num_pages); 16068c2ecf20Sopenharmony_ci for (i = 0; i < num_pages; i++) { 16078c2ecf20Sopenharmony_ci block_ctx->pagev[i] = alloc_page(GFP_NOFS); 16088c2ecf20Sopenharmony_ci if (!block_ctx->pagev[i]) 16098c2ecf20Sopenharmony_ci return -1; 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_ci dev_bytenr = block_ctx->dev_bytenr; 16138c2ecf20Sopenharmony_ci for (i = 0; i < num_pages;) { 16148c2ecf20Sopenharmony_ci struct bio *bio; 16158c2ecf20Sopenharmony_ci unsigned int j; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci bio = btrfs_io_bio_alloc(num_pages - i); 16188c2ecf20Sopenharmony_ci bio_set_dev(bio, block_ctx->dev->bdev); 16198c2ecf20Sopenharmony_ci bio->bi_iter.bi_sector = dev_bytenr >> 9; 16208c2ecf20Sopenharmony_ci bio->bi_opf = REQ_OP_READ; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci for (j = i; j < num_pages; j++) { 16238c2ecf20Sopenharmony_ci ret = bio_add_page(bio, block_ctx->pagev[j], 16248c2ecf20Sopenharmony_ci PAGE_SIZE, 0); 16258c2ecf20Sopenharmony_ci if (PAGE_SIZE != ret) 16268c2ecf20Sopenharmony_ci break; 16278c2ecf20Sopenharmony_ci } 16288c2ecf20Sopenharmony_ci if (j == i) { 16298c2ecf20Sopenharmony_ci pr_info("btrfsic: error, failed to add a single page!\n"); 16308c2ecf20Sopenharmony_ci return -1; 16318c2ecf20Sopenharmony_ci } 16328c2ecf20Sopenharmony_ci if (submit_bio_wait(bio)) { 16338c2ecf20Sopenharmony_ci pr_info("btrfsic: read error at logical %llu dev %s!\n", 16348c2ecf20Sopenharmony_ci block_ctx->start, block_ctx->dev->name); 16358c2ecf20Sopenharmony_ci bio_put(bio); 16368c2ecf20Sopenharmony_ci return -1; 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci bio_put(bio); 16398c2ecf20Sopenharmony_ci dev_bytenr += (j - i) * PAGE_SIZE; 16408c2ecf20Sopenharmony_ci i = j; 16418c2ecf20Sopenharmony_ci } 16428c2ecf20Sopenharmony_ci for (i = 0; i < num_pages; i++) 16438c2ecf20Sopenharmony_ci block_ctx->datav[i] = kmap(block_ctx->pagev[i]); 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci return block_ctx->len; 16468c2ecf20Sopenharmony_ci} 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_cistatic void btrfsic_dump_database(struct btrfsic_state *state) 16498c2ecf20Sopenharmony_ci{ 16508c2ecf20Sopenharmony_ci const struct btrfsic_block *b_all; 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci BUG_ON(NULL == state); 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci pr_info("all_blocks_list:\n"); 16558c2ecf20Sopenharmony_ci list_for_each_entry(b_all, &state->all_blocks_list, all_blocks_node) { 16568c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci pr_info("%c-block @%llu (%s/%llu/%d)\n", 16598c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, b_all), 16608c2ecf20Sopenharmony_ci b_all->logical_bytenr, b_all->dev_state->name, 16618c2ecf20Sopenharmony_ci b_all->dev_bytenr, b_all->mirror_num); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci list_for_each_entry(l, &b_all->ref_to_list, node_ref_to) { 16648c2ecf20Sopenharmony_ci pr_info(" %c @%llu (%s/%llu/%d) refers %u* to %c @%llu (%s/%llu/%d)\n", 16658c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, b_all), 16668c2ecf20Sopenharmony_ci b_all->logical_bytenr, b_all->dev_state->name, 16678c2ecf20Sopenharmony_ci b_all->dev_bytenr, b_all->mirror_num, 16688c2ecf20Sopenharmony_ci l->ref_cnt, 16698c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 16708c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 16718c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, 16728c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr, 16738c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num); 16748c2ecf20Sopenharmony_ci } 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci list_for_each_entry(l, &b_all->ref_from_list, node_ref_from) { 16778c2ecf20Sopenharmony_ci pr_info(" %c @%llu (%s/%llu/%d) is ref %u* from %c @%llu (%s/%llu/%d)\n", 16788c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, b_all), 16798c2ecf20Sopenharmony_ci b_all->logical_bytenr, b_all->dev_state->name, 16808c2ecf20Sopenharmony_ci b_all->dev_bytenr, b_all->mirror_num, 16818c2ecf20Sopenharmony_ci l->ref_cnt, 16828c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_from), 16838c2ecf20Sopenharmony_ci l->block_ref_from->logical_bytenr, 16848c2ecf20Sopenharmony_ci l->block_ref_from->dev_state->name, 16858c2ecf20Sopenharmony_ci l->block_ref_from->dev_bytenr, 16868c2ecf20Sopenharmony_ci l->block_ref_from->mirror_num); 16878c2ecf20Sopenharmony_ci } 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci pr_info("\n"); 16908c2ecf20Sopenharmony_ci } 16918c2ecf20Sopenharmony_ci} 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci/* 16948c2ecf20Sopenharmony_ci * Test whether the disk block contains a tree block (leaf or node) 16958c2ecf20Sopenharmony_ci * (note that this test fails for the super block) 16968c2ecf20Sopenharmony_ci */ 16978c2ecf20Sopenharmony_cistatic noinline_for_stack int btrfsic_test_for_metadata( 16988c2ecf20Sopenharmony_ci struct btrfsic_state *state, 16998c2ecf20Sopenharmony_ci char **datav, unsigned int num_pages) 17008c2ecf20Sopenharmony_ci{ 17018c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = state->fs_info; 17028c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); 17038c2ecf20Sopenharmony_ci struct btrfs_header *h; 17048c2ecf20Sopenharmony_ci u8 csum[BTRFS_CSUM_SIZE]; 17058c2ecf20Sopenharmony_ci unsigned int i; 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci if (num_pages * PAGE_SIZE < state->metablock_size) 17088c2ecf20Sopenharmony_ci return 1; /* not metadata */ 17098c2ecf20Sopenharmony_ci num_pages = state->metablock_size >> PAGE_SHIFT; 17108c2ecf20Sopenharmony_ci h = (struct btrfs_header *)datav[0]; 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci if (memcmp(h->fsid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE)) 17138c2ecf20Sopenharmony_ci return 1; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci shash->tfm = fs_info->csum_shash; 17168c2ecf20Sopenharmony_ci crypto_shash_init(shash); 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci for (i = 0; i < num_pages; i++) { 17198c2ecf20Sopenharmony_ci u8 *data = i ? datav[i] : (datav[i] + BTRFS_CSUM_SIZE); 17208c2ecf20Sopenharmony_ci size_t sublen = i ? PAGE_SIZE : 17218c2ecf20Sopenharmony_ci (PAGE_SIZE - BTRFS_CSUM_SIZE); 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci crypto_shash_update(shash, data, sublen); 17248c2ecf20Sopenharmony_ci } 17258c2ecf20Sopenharmony_ci crypto_shash_final(shash, csum); 17268c2ecf20Sopenharmony_ci if (memcmp(csum, h->csum, state->csum_size)) 17278c2ecf20Sopenharmony_ci return 1; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci return 0; /* is metadata */ 17308c2ecf20Sopenharmony_ci} 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_cistatic void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, 17338c2ecf20Sopenharmony_ci u64 dev_bytenr, char **mapped_datav, 17348c2ecf20Sopenharmony_ci unsigned int num_pages, 17358c2ecf20Sopenharmony_ci struct bio *bio, int *bio_is_patched, 17368c2ecf20Sopenharmony_ci int submit_bio_bh_rw) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci int is_metadata; 17398c2ecf20Sopenharmony_ci struct btrfsic_block *block; 17408c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx block_ctx; 17418c2ecf20Sopenharmony_ci int ret; 17428c2ecf20Sopenharmony_ci struct btrfsic_state *state = dev_state->state; 17438c2ecf20Sopenharmony_ci struct block_device *bdev = dev_state->bdev; 17448c2ecf20Sopenharmony_ci unsigned int processed_len; 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci if (NULL != bio_is_patched) 17478c2ecf20Sopenharmony_ci *bio_is_patched = 0; 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ciagain: 17508c2ecf20Sopenharmony_ci if (num_pages == 0) 17518c2ecf20Sopenharmony_ci return; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci processed_len = 0; 17548c2ecf20Sopenharmony_ci is_metadata = (0 == btrfsic_test_for_metadata(state, mapped_datav, 17558c2ecf20Sopenharmony_ci num_pages)); 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr, 17588c2ecf20Sopenharmony_ci &state->block_hashtable); 17598c2ecf20Sopenharmony_ci if (NULL != block) { 17608c2ecf20Sopenharmony_ci u64 bytenr = 0; 17618c2ecf20Sopenharmony_ci struct btrfsic_block_link *l, *tmp; 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci if (block->is_superblock) { 17648c2ecf20Sopenharmony_ci bytenr = btrfs_super_bytenr((struct btrfs_super_block *) 17658c2ecf20Sopenharmony_ci mapped_datav[0]); 17668c2ecf20Sopenharmony_ci if (num_pages * PAGE_SIZE < 17678c2ecf20Sopenharmony_ci BTRFS_SUPER_INFO_SIZE) { 17688c2ecf20Sopenharmony_ci pr_info("btrfsic: cannot work with too short bios!\n"); 17698c2ecf20Sopenharmony_ci return; 17708c2ecf20Sopenharmony_ci } 17718c2ecf20Sopenharmony_ci is_metadata = 1; 17728c2ecf20Sopenharmony_ci BUG_ON(!PAGE_ALIGNED(BTRFS_SUPER_INFO_SIZE)); 17738c2ecf20Sopenharmony_ci processed_len = BTRFS_SUPER_INFO_SIZE; 17748c2ecf20Sopenharmony_ci if (state->print_mask & 17758c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_TREE_BEFORE_SB_WRITE) { 17768c2ecf20Sopenharmony_ci pr_info("[before new superblock is written]:\n"); 17778c2ecf20Sopenharmony_ci btrfsic_dump_tree_sub(state, block, 0); 17788c2ecf20Sopenharmony_ci } 17798c2ecf20Sopenharmony_ci } 17808c2ecf20Sopenharmony_ci if (is_metadata) { 17818c2ecf20Sopenharmony_ci if (!block->is_superblock) { 17828c2ecf20Sopenharmony_ci if (num_pages * PAGE_SIZE < 17838c2ecf20Sopenharmony_ci state->metablock_size) { 17848c2ecf20Sopenharmony_ci pr_info("btrfsic: cannot work with too short bios!\n"); 17858c2ecf20Sopenharmony_ci return; 17868c2ecf20Sopenharmony_ci } 17878c2ecf20Sopenharmony_ci processed_len = state->metablock_size; 17888c2ecf20Sopenharmony_ci bytenr = btrfs_stack_header_bytenr( 17898c2ecf20Sopenharmony_ci (struct btrfs_header *) 17908c2ecf20Sopenharmony_ci mapped_datav[0]); 17918c2ecf20Sopenharmony_ci btrfsic_cmp_log_and_dev_bytenr(state, bytenr, 17928c2ecf20Sopenharmony_ci dev_state, 17938c2ecf20Sopenharmony_ci dev_bytenr); 17948c2ecf20Sopenharmony_ci } 17958c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) { 17968c2ecf20Sopenharmony_ci if (block->logical_bytenr != bytenr && 17978c2ecf20Sopenharmony_ci !(!block->is_metadata && 17988c2ecf20Sopenharmony_ci block->logical_bytenr == 0)) 17998c2ecf20Sopenharmony_ci pr_info("Written block @%llu (%s/%llu/%d) found in hash table, %c, bytenr mismatch (!= stored %llu).\n", 18008c2ecf20Sopenharmony_ci bytenr, dev_state->name, 18018c2ecf20Sopenharmony_ci dev_bytenr, 18028c2ecf20Sopenharmony_ci block->mirror_num, 18038c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, 18048c2ecf20Sopenharmony_ci block), 18058c2ecf20Sopenharmony_ci block->logical_bytenr); 18068c2ecf20Sopenharmony_ci else 18078c2ecf20Sopenharmony_ci pr_info("Written block @%llu (%s/%llu/%d) found in hash table, %c.\n", 18088c2ecf20Sopenharmony_ci bytenr, dev_state->name, 18098c2ecf20Sopenharmony_ci dev_bytenr, block->mirror_num, 18108c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, 18118c2ecf20Sopenharmony_ci block)); 18128c2ecf20Sopenharmony_ci } 18138c2ecf20Sopenharmony_ci block->logical_bytenr = bytenr; 18148c2ecf20Sopenharmony_ci } else { 18158c2ecf20Sopenharmony_ci if (num_pages * PAGE_SIZE < 18168c2ecf20Sopenharmony_ci state->datablock_size) { 18178c2ecf20Sopenharmony_ci pr_info("btrfsic: cannot work with too short bios!\n"); 18188c2ecf20Sopenharmony_ci return; 18198c2ecf20Sopenharmony_ci } 18208c2ecf20Sopenharmony_ci processed_len = state->datablock_size; 18218c2ecf20Sopenharmony_ci bytenr = block->logical_bytenr; 18228c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 18238c2ecf20Sopenharmony_ci pr_info("Written block @%llu (%s/%llu/%d) found in hash table, %c.\n", 18248c2ecf20Sopenharmony_ci bytenr, dev_state->name, dev_bytenr, 18258c2ecf20Sopenharmony_ci block->mirror_num, 18268c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, block)); 18278c2ecf20Sopenharmony_ci } 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 18308c2ecf20Sopenharmony_ci pr_info("ref_to_list: %cE, ref_from_list: %cE\n", 18318c2ecf20Sopenharmony_ci list_empty(&block->ref_to_list) ? ' ' : '!', 18328c2ecf20Sopenharmony_ci list_empty(&block->ref_from_list) ? ' ' : '!'); 18338c2ecf20Sopenharmony_ci if (btrfsic_is_block_ref_by_superblock(state, block, 0)) { 18348c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to overwrite %c-block @%llu (%s/%llu/%d), old(gen=%llu, objectid=%llu, type=%d, offset=%llu), new(gen=%llu), which is referenced by most recent superblock (superblockgen=%llu)!\n", 18358c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, block), bytenr, 18368c2ecf20Sopenharmony_ci dev_state->name, dev_bytenr, block->mirror_num, 18378c2ecf20Sopenharmony_ci block->generation, 18388c2ecf20Sopenharmony_ci btrfs_disk_key_objectid(&block->disk_key), 18398c2ecf20Sopenharmony_ci block->disk_key.type, 18408c2ecf20Sopenharmony_ci btrfs_disk_key_offset(&block->disk_key), 18418c2ecf20Sopenharmony_ci btrfs_stack_header_generation( 18428c2ecf20Sopenharmony_ci (struct btrfs_header *) mapped_datav[0]), 18438c2ecf20Sopenharmony_ci state->max_superblock_generation); 18448c2ecf20Sopenharmony_ci btrfsic_dump_tree(state); 18458c2ecf20Sopenharmony_ci } 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci if (!block->is_iodone && !block->never_written) { 18488c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to overwrite %c-block @%llu (%s/%llu/%d), oldgen=%llu, newgen=%llu, which is not yet iodone!\n", 18498c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, block), bytenr, 18508c2ecf20Sopenharmony_ci dev_state->name, dev_bytenr, block->mirror_num, 18518c2ecf20Sopenharmony_ci block->generation, 18528c2ecf20Sopenharmony_ci btrfs_stack_header_generation( 18538c2ecf20Sopenharmony_ci (struct btrfs_header *) 18548c2ecf20Sopenharmony_ci mapped_datav[0])); 18558c2ecf20Sopenharmony_ci /* it would not be safe to go on */ 18568c2ecf20Sopenharmony_ci btrfsic_dump_tree(state); 18578c2ecf20Sopenharmony_ci goto continue_loop; 18588c2ecf20Sopenharmony_ci } 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci /* 18618c2ecf20Sopenharmony_ci * Clear all references of this block. Do not free 18628c2ecf20Sopenharmony_ci * the block itself even if is not referenced anymore 18638c2ecf20Sopenharmony_ci * because it still carries valuable information 18648c2ecf20Sopenharmony_ci * like whether it was ever written and IO completed. 18658c2ecf20Sopenharmony_ci */ 18668c2ecf20Sopenharmony_ci list_for_each_entry_safe(l, tmp, &block->ref_to_list, 18678c2ecf20Sopenharmony_ci node_ref_to) { 18688c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 18698c2ecf20Sopenharmony_ci btrfsic_print_rem_link(state, l); 18708c2ecf20Sopenharmony_ci l->ref_cnt--; 18718c2ecf20Sopenharmony_ci if (0 == l->ref_cnt) { 18728c2ecf20Sopenharmony_ci list_del(&l->node_ref_to); 18738c2ecf20Sopenharmony_ci list_del(&l->node_ref_from); 18748c2ecf20Sopenharmony_ci btrfsic_block_link_hashtable_remove(l); 18758c2ecf20Sopenharmony_ci btrfsic_block_link_free(l); 18768c2ecf20Sopenharmony_ci } 18778c2ecf20Sopenharmony_ci } 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_ci block_ctx.dev = dev_state; 18808c2ecf20Sopenharmony_ci block_ctx.dev_bytenr = dev_bytenr; 18818c2ecf20Sopenharmony_ci block_ctx.start = bytenr; 18828c2ecf20Sopenharmony_ci block_ctx.len = processed_len; 18838c2ecf20Sopenharmony_ci block_ctx.pagev = NULL; 18848c2ecf20Sopenharmony_ci block_ctx.mem_to_free = NULL; 18858c2ecf20Sopenharmony_ci block_ctx.datav = mapped_datav; 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci if (is_metadata || state->include_extent_data) { 18888c2ecf20Sopenharmony_ci block->never_written = 0; 18898c2ecf20Sopenharmony_ci block->iodone_w_error = 0; 18908c2ecf20Sopenharmony_ci if (NULL != bio) { 18918c2ecf20Sopenharmony_ci block->is_iodone = 0; 18928c2ecf20Sopenharmony_ci BUG_ON(NULL == bio_is_patched); 18938c2ecf20Sopenharmony_ci if (!*bio_is_patched) { 18948c2ecf20Sopenharmony_ci block->orig_bio_private = 18958c2ecf20Sopenharmony_ci bio->bi_private; 18968c2ecf20Sopenharmony_ci block->orig_bio_end_io = 18978c2ecf20Sopenharmony_ci bio->bi_end_io; 18988c2ecf20Sopenharmony_ci block->next_in_same_bio = NULL; 18998c2ecf20Sopenharmony_ci bio->bi_private = block; 19008c2ecf20Sopenharmony_ci bio->bi_end_io = btrfsic_bio_end_io; 19018c2ecf20Sopenharmony_ci *bio_is_patched = 1; 19028c2ecf20Sopenharmony_ci } else { 19038c2ecf20Sopenharmony_ci struct btrfsic_block *chained_block = 19048c2ecf20Sopenharmony_ci (struct btrfsic_block *) 19058c2ecf20Sopenharmony_ci bio->bi_private; 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci BUG_ON(NULL == chained_block); 19088c2ecf20Sopenharmony_ci block->orig_bio_private = 19098c2ecf20Sopenharmony_ci chained_block->orig_bio_private; 19108c2ecf20Sopenharmony_ci block->orig_bio_end_io = 19118c2ecf20Sopenharmony_ci chained_block->orig_bio_end_io; 19128c2ecf20Sopenharmony_ci block->next_in_same_bio = chained_block; 19138c2ecf20Sopenharmony_ci bio->bi_private = block; 19148c2ecf20Sopenharmony_ci } 19158c2ecf20Sopenharmony_ci } else { 19168c2ecf20Sopenharmony_ci block->is_iodone = 1; 19178c2ecf20Sopenharmony_ci block->orig_bio_private = NULL; 19188c2ecf20Sopenharmony_ci block->orig_bio_end_io = NULL; 19198c2ecf20Sopenharmony_ci block->next_in_same_bio = NULL; 19208c2ecf20Sopenharmony_ci } 19218c2ecf20Sopenharmony_ci } 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci block->flush_gen = dev_state->last_flush_gen + 1; 19248c2ecf20Sopenharmony_ci block->submit_bio_bh_rw = submit_bio_bh_rw; 19258c2ecf20Sopenharmony_ci if (is_metadata) { 19268c2ecf20Sopenharmony_ci block->logical_bytenr = bytenr; 19278c2ecf20Sopenharmony_ci block->is_metadata = 1; 19288c2ecf20Sopenharmony_ci if (block->is_superblock) { 19298c2ecf20Sopenharmony_ci BUG_ON(PAGE_SIZE != 19308c2ecf20Sopenharmony_ci BTRFS_SUPER_INFO_SIZE); 19318c2ecf20Sopenharmony_ci ret = btrfsic_process_written_superblock( 19328c2ecf20Sopenharmony_ci state, 19338c2ecf20Sopenharmony_ci block, 19348c2ecf20Sopenharmony_ci (struct btrfs_super_block *) 19358c2ecf20Sopenharmony_ci mapped_datav[0]); 19368c2ecf20Sopenharmony_ci if (state->print_mask & 19378c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_TREE_AFTER_SB_WRITE) { 19388c2ecf20Sopenharmony_ci pr_info("[after new superblock is written]:\n"); 19398c2ecf20Sopenharmony_ci btrfsic_dump_tree_sub(state, block, 0); 19408c2ecf20Sopenharmony_ci } 19418c2ecf20Sopenharmony_ci } else { 19428c2ecf20Sopenharmony_ci block->mirror_num = 0; /* unknown */ 19438c2ecf20Sopenharmony_ci ret = btrfsic_process_metablock( 19448c2ecf20Sopenharmony_ci state, 19458c2ecf20Sopenharmony_ci block, 19468c2ecf20Sopenharmony_ci &block_ctx, 19478c2ecf20Sopenharmony_ci 0, 0); 19488c2ecf20Sopenharmony_ci } 19498c2ecf20Sopenharmony_ci if (ret) 19508c2ecf20Sopenharmony_ci pr_info("btrfsic: btrfsic_process_metablock(root @%llu) failed!\n", 19518c2ecf20Sopenharmony_ci dev_bytenr); 19528c2ecf20Sopenharmony_ci } else { 19538c2ecf20Sopenharmony_ci block->is_metadata = 0; 19548c2ecf20Sopenharmony_ci block->mirror_num = 0; /* unknown */ 19558c2ecf20Sopenharmony_ci block->generation = BTRFSIC_GENERATION_UNKNOWN; 19568c2ecf20Sopenharmony_ci if (!state->include_extent_data 19578c2ecf20Sopenharmony_ci && list_empty(&block->ref_from_list)) { 19588c2ecf20Sopenharmony_ci /* 19598c2ecf20Sopenharmony_ci * disk block is overwritten with extent 19608c2ecf20Sopenharmony_ci * data (not meta data) and we are configured 19618c2ecf20Sopenharmony_ci * to not include extent data: take the 19628c2ecf20Sopenharmony_ci * chance and free the block's memory 19638c2ecf20Sopenharmony_ci */ 19648c2ecf20Sopenharmony_ci btrfsic_block_hashtable_remove(block); 19658c2ecf20Sopenharmony_ci list_del(&block->all_blocks_node); 19668c2ecf20Sopenharmony_ci btrfsic_block_free(block); 19678c2ecf20Sopenharmony_ci } 19688c2ecf20Sopenharmony_ci } 19698c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&block_ctx); 19708c2ecf20Sopenharmony_ci } else { 19718c2ecf20Sopenharmony_ci /* block has not been found in hash table */ 19728c2ecf20Sopenharmony_ci u64 bytenr; 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci if (!is_metadata) { 19758c2ecf20Sopenharmony_ci processed_len = state->datablock_size; 19768c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 19778c2ecf20Sopenharmony_ci pr_info("Written block (%s/%llu/?) !found in hash table, D.\n", 19788c2ecf20Sopenharmony_ci dev_state->name, dev_bytenr); 19798c2ecf20Sopenharmony_ci if (!state->include_extent_data) { 19808c2ecf20Sopenharmony_ci /* ignore that written D block */ 19818c2ecf20Sopenharmony_ci goto continue_loop; 19828c2ecf20Sopenharmony_ci } 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci /* this is getting ugly for the 19858c2ecf20Sopenharmony_ci * include_extent_data case... */ 19868c2ecf20Sopenharmony_ci bytenr = 0; /* unknown */ 19878c2ecf20Sopenharmony_ci } else { 19888c2ecf20Sopenharmony_ci processed_len = state->metablock_size; 19898c2ecf20Sopenharmony_ci bytenr = btrfs_stack_header_bytenr( 19908c2ecf20Sopenharmony_ci (struct btrfs_header *) 19918c2ecf20Sopenharmony_ci mapped_datav[0]); 19928c2ecf20Sopenharmony_ci btrfsic_cmp_log_and_dev_bytenr(state, bytenr, dev_state, 19938c2ecf20Sopenharmony_ci dev_bytenr); 19948c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 19958c2ecf20Sopenharmony_ci pr_info("Written block @%llu (%s/%llu/?) !found in hash table, M.\n", 19968c2ecf20Sopenharmony_ci bytenr, dev_state->name, dev_bytenr); 19978c2ecf20Sopenharmony_ci } 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci block_ctx.dev = dev_state; 20008c2ecf20Sopenharmony_ci block_ctx.dev_bytenr = dev_bytenr; 20018c2ecf20Sopenharmony_ci block_ctx.start = bytenr; 20028c2ecf20Sopenharmony_ci block_ctx.len = processed_len; 20038c2ecf20Sopenharmony_ci block_ctx.pagev = NULL; 20048c2ecf20Sopenharmony_ci block_ctx.mem_to_free = NULL; 20058c2ecf20Sopenharmony_ci block_ctx.datav = mapped_datav; 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci block = btrfsic_block_alloc(); 20088c2ecf20Sopenharmony_ci if (NULL == block) { 20098c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&block_ctx); 20108c2ecf20Sopenharmony_ci goto continue_loop; 20118c2ecf20Sopenharmony_ci } 20128c2ecf20Sopenharmony_ci block->dev_state = dev_state; 20138c2ecf20Sopenharmony_ci block->dev_bytenr = dev_bytenr; 20148c2ecf20Sopenharmony_ci block->logical_bytenr = bytenr; 20158c2ecf20Sopenharmony_ci block->is_metadata = is_metadata; 20168c2ecf20Sopenharmony_ci block->never_written = 0; 20178c2ecf20Sopenharmony_ci block->iodone_w_error = 0; 20188c2ecf20Sopenharmony_ci block->mirror_num = 0; /* unknown */ 20198c2ecf20Sopenharmony_ci block->flush_gen = dev_state->last_flush_gen + 1; 20208c2ecf20Sopenharmony_ci block->submit_bio_bh_rw = submit_bio_bh_rw; 20218c2ecf20Sopenharmony_ci if (NULL != bio) { 20228c2ecf20Sopenharmony_ci block->is_iodone = 0; 20238c2ecf20Sopenharmony_ci BUG_ON(NULL == bio_is_patched); 20248c2ecf20Sopenharmony_ci if (!*bio_is_patched) { 20258c2ecf20Sopenharmony_ci block->orig_bio_private = bio->bi_private; 20268c2ecf20Sopenharmony_ci block->orig_bio_end_io = bio->bi_end_io; 20278c2ecf20Sopenharmony_ci block->next_in_same_bio = NULL; 20288c2ecf20Sopenharmony_ci bio->bi_private = block; 20298c2ecf20Sopenharmony_ci bio->bi_end_io = btrfsic_bio_end_io; 20308c2ecf20Sopenharmony_ci *bio_is_patched = 1; 20318c2ecf20Sopenharmony_ci } else { 20328c2ecf20Sopenharmony_ci struct btrfsic_block *chained_block = 20338c2ecf20Sopenharmony_ci (struct btrfsic_block *) 20348c2ecf20Sopenharmony_ci bio->bi_private; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci BUG_ON(NULL == chained_block); 20378c2ecf20Sopenharmony_ci block->orig_bio_private = 20388c2ecf20Sopenharmony_ci chained_block->orig_bio_private; 20398c2ecf20Sopenharmony_ci block->orig_bio_end_io = 20408c2ecf20Sopenharmony_ci chained_block->orig_bio_end_io; 20418c2ecf20Sopenharmony_ci block->next_in_same_bio = chained_block; 20428c2ecf20Sopenharmony_ci bio->bi_private = block; 20438c2ecf20Sopenharmony_ci } 20448c2ecf20Sopenharmony_ci } else { 20458c2ecf20Sopenharmony_ci block->is_iodone = 1; 20468c2ecf20Sopenharmony_ci block->orig_bio_private = NULL; 20478c2ecf20Sopenharmony_ci block->orig_bio_end_io = NULL; 20488c2ecf20Sopenharmony_ci block->next_in_same_bio = NULL; 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 20518c2ecf20Sopenharmony_ci pr_info("New written %c-block @%llu (%s/%llu/%d)\n", 20528c2ecf20Sopenharmony_ci is_metadata ? 'M' : 'D', 20538c2ecf20Sopenharmony_ci block->logical_bytenr, block->dev_state->name, 20548c2ecf20Sopenharmony_ci block->dev_bytenr, block->mirror_num); 20558c2ecf20Sopenharmony_ci list_add(&block->all_blocks_node, &state->all_blocks_list); 20568c2ecf20Sopenharmony_ci btrfsic_block_hashtable_add(block, &state->block_hashtable); 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ci if (is_metadata) { 20598c2ecf20Sopenharmony_ci ret = btrfsic_process_metablock(state, block, 20608c2ecf20Sopenharmony_ci &block_ctx, 0, 0); 20618c2ecf20Sopenharmony_ci if (ret) 20628c2ecf20Sopenharmony_ci pr_info("btrfsic: process_metablock(root @%llu) failed!\n", 20638c2ecf20Sopenharmony_ci dev_bytenr); 20648c2ecf20Sopenharmony_ci } 20658c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&block_ctx); 20668c2ecf20Sopenharmony_ci } 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_cicontinue_loop: 20698c2ecf20Sopenharmony_ci BUG_ON(!processed_len); 20708c2ecf20Sopenharmony_ci dev_bytenr += processed_len; 20718c2ecf20Sopenharmony_ci mapped_datav += processed_len >> PAGE_SHIFT; 20728c2ecf20Sopenharmony_ci num_pages -= processed_len >> PAGE_SHIFT; 20738c2ecf20Sopenharmony_ci goto again; 20748c2ecf20Sopenharmony_ci} 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_cistatic void btrfsic_bio_end_io(struct bio *bp) 20778c2ecf20Sopenharmony_ci{ 20788c2ecf20Sopenharmony_ci struct btrfsic_block *block = (struct btrfsic_block *)bp->bi_private; 20798c2ecf20Sopenharmony_ci int iodone_w_error; 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci /* mutex is not held! This is not save if IO is not yet completed 20828c2ecf20Sopenharmony_ci * on umount */ 20838c2ecf20Sopenharmony_ci iodone_w_error = 0; 20848c2ecf20Sopenharmony_ci if (bp->bi_status) 20858c2ecf20Sopenharmony_ci iodone_w_error = 1; 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci BUG_ON(NULL == block); 20888c2ecf20Sopenharmony_ci bp->bi_private = block->orig_bio_private; 20898c2ecf20Sopenharmony_ci bp->bi_end_io = block->orig_bio_end_io; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci do { 20928c2ecf20Sopenharmony_ci struct btrfsic_block *next_block; 20938c2ecf20Sopenharmony_ci struct btrfsic_dev_state *const dev_state = block->dev_state; 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_ci if ((dev_state->state->print_mask & 20968c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_END_IO_BIO_BH)) 20978c2ecf20Sopenharmony_ci pr_info("bio_end_io(err=%d) for %c @%llu (%s/%llu/%d)\n", 20988c2ecf20Sopenharmony_ci bp->bi_status, 20998c2ecf20Sopenharmony_ci btrfsic_get_block_type(dev_state->state, block), 21008c2ecf20Sopenharmony_ci block->logical_bytenr, dev_state->name, 21018c2ecf20Sopenharmony_ci block->dev_bytenr, block->mirror_num); 21028c2ecf20Sopenharmony_ci next_block = block->next_in_same_bio; 21038c2ecf20Sopenharmony_ci block->iodone_w_error = iodone_w_error; 21048c2ecf20Sopenharmony_ci if (block->submit_bio_bh_rw & REQ_PREFLUSH) { 21058c2ecf20Sopenharmony_ci dev_state->last_flush_gen++; 21068c2ecf20Sopenharmony_ci if ((dev_state->state->print_mask & 21078c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_END_IO_BIO_BH)) 21088c2ecf20Sopenharmony_ci pr_info("bio_end_io() new %s flush_gen=%llu\n", 21098c2ecf20Sopenharmony_ci dev_state->name, 21108c2ecf20Sopenharmony_ci dev_state->last_flush_gen); 21118c2ecf20Sopenharmony_ci } 21128c2ecf20Sopenharmony_ci if (block->submit_bio_bh_rw & REQ_FUA) 21138c2ecf20Sopenharmony_ci block->flush_gen = 0; /* FUA completed means block is 21148c2ecf20Sopenharmony_ci * on disk */ 21158c2ecf20Sopenharmony_ci block->is_iodone = 1; /* for FLUSH, this releases the block */ 21168c2ecf20Sopenharmony_ci block = next_block; 21178c2ecf20Sopenharmony_ci } while (NULL != block); 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci bp->bi_end_io(bp); 21208c2ecf20Sopenharmony_ci} 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_cistatic int btrfsic_process_written_superblock( 21238c2ecf20Sopenharmony_ci struct btrfsic_state *state, 21248c2ecf20Sopenharmony_ci struct btrfsic_block *const superblock, 21258c2ecf20Sopenharmony_ci struct btrfs_super_block *const super_hdr) 21268c2ecf20Sopenharmony_ci{ 21278c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = state->fs_info; 21288c2ecf20Sopenharmony_ci int pass; 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci superblock->generation = btrfs_super_generation(super_hdr); 21318c2ecf20Sopenharmony_ci if (!(superblock->generation > state->max_superblock_generation || 21328c2ecf20Sopenharmony_ci 0 == state->max_superblock_generation)) { 21338c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE) 21348c2ecf20Sopenharmony_ci pr_info("btrfsic: superblock @%llu (%s/%llu/%d) with old gen %llu <= %llu\n", 21358c2ecf20Sopenharmony_ci superblock->logical_bytenr, 21368c2ecf20Sopenharmony_ci superblock->dev_state->name, 21378c2ecf20Sopenharmony_ci superblock->dev_bytenr, superblock->mirror_num, 21388c2ecf20Sopenharmony_ci btrfs_super_generation(super_hdr), 21398c2ecf20Sopenharmony_ci state->max_superblock_generation); 21408c2ecf20Sopenharmony_ci } else { 21418c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE) 21428c2ecf20Sopenharmony_ci pr_info("btrfsic: got new superblock @%llu (%s/%llu/%d) with new gen %llu > %llu\n", 21438c2ecf20Sopenharmony_ci superblock->logical_bytenr, 21448c2ecf20Sopenharmony_ci superblock->dev_state->name, 21458c2ecf20Sopenharmony_ci superblock->dev_bytenr, superblock->mirror_num, 21468c2ecf20Sopenharmony_ci btrfs_super_generation(super_hdr), 21478c2ecf20Sopenharmony_ci state->max_superblock_generation); 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci state->max_superblock_generation = 21508c2ecf20Sopenharmony_ci btrfs_super_generation(super_hdr); 21518c2ecf20Sopenharmony_ci state->latest_superblock = superblock; 21528c2ecf20Sopenharmony_ci } 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci for (pass = 0; pass < 3; pass++) { 21558c2ecf20Sopenharmony_ci int ret; 21568c2ecf20Sopenharmony_ci u64 next_bytenr; 21578c2ecf20Sopenharmony_ci struct btrfsic_block *next_block; 21588c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx tmp_next_block_ctx; 21598c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 21608c2ecf20Sopenharmony_ci int num_copies; 21618c2ecf20Sopenharmony_ci int mirror_num; 21628c2ecf20Sopenharmony_ci const char *additional_string = NULL; 21638c2ecf20Sopenharmony_ci struct btrfs_disk_key tmp_disk_key = {0}; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 21668c2ecf20Sopenharmony_ci BTRFS_ROOT_ITEM_KEY); 21678c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 0); 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci switch (pass) { 21708c2ecf20Sopenharmony_ci case 0: 21718c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 21728c2ecf20Sopenharmony_ci BTRFS_ROOT_TREE_OBJECTID); 21738c2ecf20Sopenharmony_ci additional_string = "root "; 21748c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_root(super_hdr); 21758c2ecf20Sopenharmony_ci if (state->print_mask & 21768c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION) 21778c2ecf20Sopenharmony_ci pr_info("root@%llu\n", next_bytenr); 21788c2ecf20Sopenharmony_ci break; 21798c2ecf20Sopenharmony_ci case 1: 21808c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 21818c2ecf20Sopenharmony_ci BTRFS_CHUNK_TREE_OBJECTID); 21828c2ecf20Sopenharmony_ci additional_string = "chunk "; 21838c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_chunk_root(super_hdr); 21848c2ecf20Sopenharmony_ci if (state->print_mask & 21858c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION) 21868c2ecf20Sopenharmony_ci pr_info("chunk@%llu\n", next_bytenr); 21878c2ecf20Sopenharmony_ci break; 21888c2ecf20Sopenharmony_ci case 2: 21898c2ecf20Sopenharmony_ci btrfs_set_disk_key_objectid(&tmp_disk_key, 21908c2ecf20Sopenharmony_ci BTRFS_TREE_LOG_OBJECTID); 21918c2ecf20Sopenharmony_ci additional_string = "log "; 21928c2ecf20Sopenharmony_ci next_bytenr = btrfs_super_log_root(super_hdr); 21938c2ecf20Sopenharmony_ci if (0 == next_bytenr) 21948c2ecf20Sopenharmony_ci continue; 21958c2ecf20Sopenharmony_ci if (state->print_mask & 21968c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_ROOT_CHUNK_LOG_TREE_LOCATION) 21978c2ecf20Sopenharmony_ci pr_info("log@%llu\n", next_bytenr); 21988c2ecf20Sopenharmony_ci break; 21998c2ecf20Sopenharmony_ci } 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci num_copies = btrfs_num_copies(fs_info, next_bytenr, 22028c2ecf20Sopenharmony_ci BTRFS_SUPER_INFO_SIZE); 22038c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_NUM_COPIES) 22048c2ecf20Sopenharmony_ci pr_info("num_copies(log_bytenr=%llu) = %d\n", 22058c2ecf20Sopenharmony_ci next_bytenr, num_copies); 22068c2ecf20Sopenharmony_ci for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) { 22078c2ecf20Sopenharmony_ci int was_created; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 22108c2ecf20Sopenharmony_ci pr_info("btrfsic_process_written_superblock(mirror_num=%d)\n", mirror_num); 22118c2ecf20Sopenharmony_ci ret = btrfsic_map_block(state, next_bytenr, 22128c2ecf20Sopenharmony_ci BTRFS_SUPER_INFO_SIZE, 22138c2ecf20Sopenharmony_ci &tmp_next_block_ctx, 22148c2ecf20Sopenharmony_ci mirror_num); 22158c2ecf20Sopenharmony_ci if (ret) { 22168c2ecf20Sopenharmony_ci pr_info("btrfsic: btrfsic_map_block(@%llu, mirror=%d) failed!\n", 22178c2ecf20Sopenharmony_ci next_bytenr, mirror_num); 22188c2ecf20Sopenharmony_ci return -1; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci 22218c2ecf20Sopenharmony_ci next_block = btrfsic_block_lookup_or_add( 22228c2ecf20Sopenharmony_ci state, 22238c2ecf20Sopenharmony_ci &tmp_next_block_ctx, 22248c2ecf20Sopenharmony_ci additional_string, 22258c2ecf20Sopenharmony_ci 1, 0, 1, 22268c2ecf20Sopenharmony_ci mirror_num, 22278c2ecf20Sopenharmony_ci &was_created); 22288c2ecf20Sopenharmony_ci if (NULL == next_block) { 22298c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&tmp_next_block_ctx); 22308c2ecf20Sopenharmony_ci return -1; 22318c2ecf20Sopenharmony_ci } 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_ci next_block->disk_key = tmp_disk_key; 22348c2ecf20Sopenharmony_ci if (was_created) 22358c2ecf20Sopenharmony_ci next_block->generation = 22368c2ecf20Sopenharmony_ci BTRFSIC_GENERATION_UNKNOWN; 22378c2ecf20Sopenharmony_ci l = btrfsic_block_link_lookup_or_add( 22388c2ecf20Sopenharmony_ci state, 22398c2ecf20Sopenharmony_ci &tmp_next_block_ctx, 22408c2ecf20Sopenharmony_ci next_block, 22418c2ecf20Sopenharmony_ci superblock, 22428c2ecf20Sopenharmony_ci BTRFSIC_GENERATION_UNKNOWN); 22438c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&tmp_next_block_ctx); 22448c2ecf20Sopenharmony_ci if (NULL == l) 22458c2ecf20Sopenharmony_ci return -1; 22468c2ecf20Sopenharmony_ci } 22478c2ecf20Sopenharmony_ci } 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci if (WARN_ON(-1 == btrfsic_check_all_ref_blocks(state, superblock, 0))) 22508c2ecf20Sopenharmony_ci btrfsic_dump_tree(state); 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci return 0; 22538c2ecf20Sopenharmony_ci} 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_cistatic int btrfsic_check_all_ref_blocks(struct btrfsic_state *state, 22568c2ecf20Sopenharmony_ci struct btrfsic_block *const block, 22578c2ecf20Sopenharmony_ci int recursion_level) 22588c2ecf20Sopenharmony_ci{ 22598c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l; 22608c2ecf20Sopenharmony_ci int ret = 0; 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_ci if (recursion_level >= 3 + BTRFS_MAX_LEVEL) { 22638c2ecf20Sopenharmony_ci /* 22648c2ecf20Sopenharmony_ci * Note that this situation can happen and does not 22658c2ecf20Sopenharmony_ci * indicate an error in regular cases. It happens 22668c2ecf20Sopenharmony_ci * when disk blocks are freed and later reused. 22678c2ecf20Sopenharmony_ci * The check-integrity module is not aware of any 22688c2ecf20Sopenharmony_ci * block free operations, it just recognizes block 22698c2ecf20Sopenharmony_ci * write operations. Therefore it keeps the linkage 22708c2ecf20Sopenharmony_ci * information for a block until a block is 22718c2ecf20Sopenharmony_ci * rewritten. This can temporarily cause incorrect 22728c2ecf20Sopenharmony_ci * and even circular linkage information. This 22738c2ecf20Sopenharmony_ci * causes no harm unless such blocks are referenced 22748c2ecf20Sopenharmony_ci * by the most recent super block. 22758c2ecf20Sopenharmony_ci */ 22768c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 22778c2ecf20Sopenharmony_ci pr_info("btrfsic: abort cyclic linkage (case 1).\n"); 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci return ret; 22808c2ecf20Sopenharmony_ci } 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci /* 22838c2ecf20Sopenharmony_ci * This algorithm is recursive because the amount of used stack 22848c2ecf20Sopenharmony_ci * space is very small and the max recursion depth is limited. 22858c2ecf20Sopenharmony_ci */ 22868c2ecf20Sopenharmony_ci list_for_each_entry(l, &block->ref_to_list, node_ref_to) { 22878c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 22888c2ecf20Sopenharmony_ci pr_info("rl=%d, %c @%llu (%s/%llu/%d) %u* refers to %c @%llu (%s/%llu/%d)\n", 22898c2ecf20Sopenharmony_ci recursion_level, 22908c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, block), 22918c2ecf20Sopenharmony_ci block->logical_bytenr, block->dev_state->name, 22928c2ecf20Sopenharmony_ci block->dev_bytenr, block->mirror_num, 22938c2ecf20Sopenharmony_ci l->ref_cnt, 22948c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 22958c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 22968c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, 22978c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr, 22988c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num); 22998c2ecf20Sopenharmony_ci if (l->block_ref_to->never_written) { 23008c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which is never written!\n", 23018c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 23028c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 23038c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, 23048c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr, 23058c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num); 23068c2ecf20Sopenharmony_ci ret = -1; 23078c2ecf20Sopenharmony_ci } else if (!l->block_ref_to->is_iodone) { 23088c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which is not yet iodone!\n", 23098c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 23108c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 23118c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, 23128c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr, 23138c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num); 23148c2ecf20Sopenharmony_ci ret = -1; 23158c2ecf20Sopenharmony_ci } else if (l->block_ref_to->iodone_w_error) { 23168c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which has write error!\n", 23178c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 23188c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 23198c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, 23208c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr, 23218c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num); 23228c2ecf20Sopenharmony_ci ret = -1; 23238c2ecf20Sopenharmony_ci } else if (l->parent_generation != 23248c2ecf20Sopenharmony_ci l->block_ref_to->generation && 23258c2ecf20Sopenharmony_ci BTRFSIC_GENERATION_UNKNOWN != 23268c2ecf20Sopenharmony_ci l->parent_generation && 23278c2ecf20Sopenharmony_ci BTRFSIC_GENERATION_UNKNOWN != 23288c2ecf20Sopenharmony_ci l->block_ref_to->generation) { 23298c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) with generation %llu != parent generation %llu!\n", 23308c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 23318c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 23328c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, 23338c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr, 23348c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num, 23358c2ecf20Sopenharmony_ci l->block_ref_to->generation, 23368c2ecf20Sopenharmony_ci l->parent_generation); 23378c2ecf20Sopenharmony_ci ret = -1; 23388c2ecf20Sopenharmony_ci } else if (l->block_ref_to->flush_gen > 23398c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->last_flush_gen) { 23408c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to write superblock which references block %c @%llu (%s/%llu/%d) which is not flushed out of disk's write cache (block flush_gen=%llu, dev->flush_gen=%llu)!\n", 23418c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 23428c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 23438c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, 23448c2ecf20Sopenharmony_ci l->block_ref_to->dev_bytenr, 23458c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num, block->flush_gen, 23468c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->last_flush_gen); 23478c2ecf20Sopenharmony_ci ret = -1; 23488c2ecf20Sopenharmony_ci } else if (-1 == btrfsic_check_all_ref_blocks(state, 23498c2ecf20Sopenharmony_ci l->block_ref_to, 23508c2ecf20Sopenharmony_ci recursion_level + 23518c2ecf20Sopenharmony_ci 1)) { 23528c2ecf20Sopenharmony_ci ret = -1; 23538c2ecf20Sopenharmony_ci } 23548c2ecf20Sopenharmony_ci } 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci return ret; 23578c2ecf20Sopenharmony_ci} 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_cistatic int btrfsic_is_block_ref_by_superblock( 23608c2ecf20Sopenharmony_ci const struct btrfsic_state *state, 23618c2ecf20Sopenharmony_ci const struct btrfsic_block *block, 23628c2ecf20Sopenharmony_ci int recursion_level) 23638c2ecf20Sopenharmony_ci{ 23648c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l; 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci if (recursion_level >= 3 + BTRFS_MAX_LEVEL) { 23678c2ecf20Sopenharmony_ci /* refer to comment at "abort cyclic linkage (case 1)" */ 23688c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 23698c2ecf20Sopenharmony_ci pr_info("btrfsic: abort cyclic linkage (case 2).\n"); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci return 0; 23728c2ecf20Sopenharmony_ci } 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci /* 23758c2ecf20Sopenharmony_ci * This algorithm is recursive because the amount of used stack space 23768c2ecf20Sopenharmony_ci * is very small and the max recursion depth is limited. 23778c2ecf20Sopenharmony_ci */ 23788c2ecf20Sopenharmony_ci list_for_each_entry(l, &block->ref_from_list, node_ref_from) { 23798c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 23808c2ecf20Sopenharmony_ci pr_info("rl=%d, %c @%llu (%s/%llu/%d) is ref %u* from %c @%llu (%s/%llu/%d)\n", 23818c2ecf20Sopenharmony_ci recursion_level, 23828c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, block), 23838c2ecf20Sopenharmony_ci block->logical_bytenr, block->dev_state->name, 23848c2ecf20Sopenharmony_ci block->dev_bytenr, block->mirror_num, 23858c2ecf20Sopenharmony_ci l->ref_cnt, 23868c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_from), 23878c2ecf20Sopenharmony_ci l->block_ref_from->logical_bytenr, 23888c2ecf20Sopenharmony_ci l->block_ref_from->dev_state->name, 23898c2ecf20Sopenharmony_ci l->block_ref_from->dev_bytenr, 23908c2ecf20Sopenharmony_ci l->block_ref_from->mirror_num); 23918c2ecf20Sopenharmony_ci if (l->block_ref_from->is_superblock && 23928c2ecf20Sopenharmony_ci state->latest_superblock->dev_bytenr == 23938c2ecf20Sopenharmony_ci l->block_ref_from->dev_bytenr && 23948c2ecf20Sopenharmony_ci state->latest_superblock->dev_state->bdev == 23958c2ecf20Sopenharmony_ci l->block_ref_from->dev_state->bdev) 23968c2ecf20Sopenharmony_ci return 1; 23978c2ecf20Sopenharmony_ci else if (btrfsic_is_block_ref_by_superblock(state, 23988c2ecf20Sopenharmony_ci l->block_ref_from, 23998c2ecf20Sopenharmony_ci recursion_level + 24008c2ecf20Sopenharmony_ci 1)) 24018c2ecf20Sopenharmony_ci return 1; 24028c2ecf20Sopenharmony_ci } 24038c2ecf20Sopenharmony_ci 24048c2ecf20Sopenharmony_ci return 0; 24058c2ecf20Sopenharmony_ci} 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_cistatic void btrfsic_print_add_link(const struct btrfsic_state *state, 24088c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l) 24098c2ecf20Sopenharmony_ci{ 24108c2ecf20Sopenharmony_ci pr_info("Add %u* link from %c @%llu (%s/%llu/%d) to %c @%llu (%s/%llu/%d).\n", 24118c2ecf20Sopenharmony_ci l->ref_cnt, 24128c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_from), 24138c2ecf20Sopenharmony_ci l->block_ref_from->logical_bytenr, 24148c2ecf20Sopenharmony_ci l->block_ref_from->dev_state->name, 24158c2ecf20Sopenharmony_ci l->block_ref_from->dev_bytenr, l->block_ref_from->mirror_num, 24168c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 24178c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 24188c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, l->block_ref_to->dev_bytenr, 24198c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num); 24208c2ecf20Sopenharmony_ci} 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_cistatic void btrfsic_print_rem_link(const struct btrfsic_state *state, 24238c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l) 24248c2ecf20Sopenharmony_ci{ 24258c2ecf20Sopenharmony_ci pr_info("Rem %u* link from %c @%llu (%s/%llu/%d) to %c @%llu (%s/%llu/%d).\n", 24268c2ecf20Sopenharmony_ci l->ref_cnt, 24278c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_from), 24288c2ecf20Sopenharmony_ci l->block_ref_from->logical_bytenr, 24298c2ecf20Sopenharmony_ci l->block_ref_from->dev_state->name, 24308c2ecf20Sopenharmony_ci l->block_ref_from->dev_bytenr, l->block_ref_from->mirror_num, 24318c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, l->block_ref_to), 24328c2ecf20Sopenharmony_ci l->block_ref_to->logical_bytenr, 24338c2ecf20Sopenharmony_ci l->block_ref_to->dev_state->name, l->block_ref_to->dev_bytenr, 24348c2ecf20Sopenharmony_ci l->block_ref_to->mirror_num); 24358c2ecf20Sopenharmony_ci} 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_cistatic char btrfsic_get_block_type(const struct btrfsic_state *state, 24388c2ecf20Sopenharmony_ci const struct btrfsic_block *block) 24398c2ecf20Sopenharmony_ci{ 24408c2ecf20Sopenharmony_ci if (block->is_superblock && 24418c2ecf20Sopenharmony_ci state->latest_superblock->dev_bytenr == block->dev_bytenr && 24428c2ecf20Sopenharmony_ci state->latest_superblock->dev_state->bdev == block->dev_state->bdev) 24438c2ecf20Sopenharmony_ci return 'S'; 24448c2ecf20Sopenharmony_ci else if (block->is_superblock) 24458c2ecf20Sopenharmony_ci return 's'; 24468c2ecf20Sopenharmony_ci else if (block->is_metadata) 24478c2ecf20Sopenharmony_ci return 'M'; 24488c2ecf20Sopenharmony_ci else 24498c2ecf20Sopenharmony_ci return 'D'; 24508c2ecf20Sopenharmony_ci} 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_cistatic void btrfsic_dump_tree(const struct btrfsic_state *state) 24538c2ecf20Sopenharmony_ci{ 24548c2ecf20Sopenharmony_ci btrfsic_dump_tree_sub(state, state->latest_superblock, 0); 24558c2ecf20Sopenharmony_ci} 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_cistatic void btrfsic_dump_tree_sub(const struct btrfsic_state *state, 24588c2ecf20Sopenharmony_ci const struct btrfsic_block *block, 24598c2ecf20Sopenharmony_ci int indent_level) 24608c2ecf20Sopenharmony_ci{ 24618c2ecf20Sopenharmony_ci const struct btrfsic_block_link *l; 24628c2ecf20Sopenharmony_ci int indent_add; 24638c2ecf20Sopenharmony_ci static char buf[80]; 24648c2ecf20Sopenharmony_ci int cursor_position; 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_ci /* 24678c2ecf20Sopenharmony_ci * Should better fill an on-stack buffer with a complete line and 24688c2ecf20Sopenharmony_ci * dump it at once when it is time to print a newline character. 24698c2ecf20Sopenharmony_ci */ 24708c2ecf20Sopenharmony_ci 24718c2ecf20Sopenharmony_ci /* 24728c2ecf20Sopenharmony_ci * This algorithm is recursive because the amount of used stack space 24738c2ecf20Sopenharmony_ci * is very small and the max recursion depth is limited. 24748c2ecf20Sopenharmony_ci */ 24758c2ecf20Sopenharmony_ci indent_add = sprintf(buf, "%c-%llu(%s/%llu/%u)", 24768c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, block), 24778c2ecf20Sopenharmony_ci block->logical_bytenr, block->dev_state->name, 24788c2ecf20Sopenharmony_ci block->dev_bytenr, block->mirror_num); 24798c2ecf20Sopenharmony_ci if (indent_level + indent_add > BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) { 24808c2ecf20Sopenharmony_ci printk("[...]\n"); 24818c2ecf20Sopenharmony_ci return; 24828c2ecf20Sopenharmony_ci } 24838c2ecf20Sopenharmony_ci printk(buf); 24848c2ecf20Sopenharmony_ci indent_level += indent_add; 24858c2ecf20Sopenharmony_ci if (list_empty(&block->ref_to_list)) { 24868c2ecf20Sopenharmony_ci printk("\n"); 24878c2ecf20Sopenharmony_ci return; 24888c2ecf20Sopenharmony_ci } 24898c2ecf20Sopenharmony_ci if (block->mirror_num > 1 && 24908c2ecf20Sopenharmony_ci !(state->print_mask & BTRFSIC_PRINT_MASK_TREE_WITH_ALL_MIRRORS)) { 24918c2ecf20Sopenharmony_ci printk(" [...]\n"); 24928c2ecf20Sopenharmony_ci return; 24938c2ecf20Sopenharmony_ci } 24948c2ecf20Sopenharmony_ci 24958c2ecf20Sopenharmony_ci cursor_position = indent_level; 24968c2ecf20Sopenharmony_ci list_for_each_entry(l, &block->ref_to_list, node_ref_to) { 24978c2ecf20Sopenharmony_ci while (cursor_position < indent_level) { 24988c2ecf20Sopenharmony_ci printk(" "); 24998c2ecf20Sopenharmony_ci cursor_position++; 25008c2ecf20Sopenharmony_ci } 25018c2ecf20Sopenharmony_ci if (l->ref_cnt > 1) 25028c2ecf20Sopenharmony_ci indent_add = sprintf(buf, " %d*--> ", l->ref_cnt); 25038c2ecf20Sopenharmony_ci else 25048c2ecf20Sopenharmony_ci indent_add = sprintf(buf, " --> "); 25058c2ecf20Sopenharmony_ci if (indent_level + indent_add > 25068c2ecf20Sopenharmony_ci BTRFSIC_TREE_DUMP_MAX_INDENT_LEVEL) { 25078c2ecf20Sopenharmony_ci printk("[...]\n"); 25088c2ecf20Sopenharmony_ci cursor_position = 0; 25098c2ecf20Sopenharmony_ci continue; 25108c2ecf20Sopenharmony_ci } 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_ci printk(buf); 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci btrfsic_dump_tree_sub(state, l->block_ref_to, 25158c2ecf20Sopenharmony_ci indent_level + indent_add); 25168c2ecf20Sopenharmony_ci cursor_position = 0; 25178c2ecf20Sopenharmony_ci } 25188c2ecf20Sopenharmony_ci} 25198c2ecf20Sopenharmony_ci 25208c2ecf20Sopenharmony_cistatic struct btrfsic_block_link *btrfsic_block_link_lookup_or_add( 25218c2ecf20Sopenharmony_ci struct btrfsic_state *state, 25228c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *next_block_ctx, 25238c2ecf20Sopenharmony_ci struct btrfsic_block *next_block, 25248c2ecf20Sopenharmony_ci struct btrfsic_block *from_block, 25258c2ecf20Sopenharmony_ci u64 parent_generation) 25268c2ecf20Sopenharmony_ci{ 25278c2ecf20Sopenharmony_ci struct btrfsic_block_link *l; 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci l = btrfsic_block_link_hashtable_lookup(next_block_ctx->dev->bdev, 25308c2ecf20Sopenharmony_ci next_block_ctx->dev_bytenr, 25318c2ecf20Sopenharmony_ci from_block->dev_state->bdev, 25328c2ecf20Sopenharmony_ci from_block->dev_bytenr, 25338c2ecf20Sopenharmony_ci &state->block_link_hashtable); 25348c2ecf20Sopenharmony_ci if (NULL == l) { 25358c2ecf20Sopenharmony_ci l = btrfsic_block_link_alloc(); 25368c2ecf20Sopenharmony_ci if (!l) 25378c2ecf20Sopenharmony_ci return NULL; 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_ci l->block_ref_to = next_block; 25408c2ecf20Sopenharmony_ci l->block_ref_from = from_block; 25418c2ecf20Sopenharmony_ci l->ref_cnt = 1; 25428c2ecf20Sopenharmony_ci l->parent_generation = parent_generation; 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 25458c2ecf20Sopenharmony_ci btrfsic_print_add_link(state, l); 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci list_add(&l->node_ref_to, &from_block->ref_to_list); 25488c2ecf20Sopenharmony_ci list_add(&l->node_ref_from, &next_block->ref_from_list); 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci btrfsic_block_link_hashtable_add(l, 25518c2ecf20Sopenharmony_ci &state->block_link_hashtable); 25528c2ecf20Sopenharmony_ci } else { 25538c2ecf20Sopenharmony_ci l->ref_cnt++; 25548c2ecf20Sopenharmony_ci l->parent_generation = parent_generation; 25558c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 25568c2ecf20Sopenharmony_ci btrfsic_print_add_link(state, l); 25578c2ecf20Sopenharmony_ci } 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci return l; 25608c2ecf20Sopenharmony_ci} 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_cistatic struct btrfsic_block *btrfsic_block_lookup_or_add( 25638c2ecf20Sopenharmony_ci struct btrfsic_state *state, 25648c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx *block_ctx, 25658c2ecf20Sopenharmony_ci const char *additional_string, 25668c2ecf20Sopenharmony_ci int is_metadata, 25678c2ecf20Sopenharmony_ci int is_iodone, 25688c2ecf20Sopenharmony_ci int never_written, 25698c2ecf20Sopenharmony_ci int mirror_num, 25708c2ecf20Sopenharmony_ci int *was_created) 25718c2ecf20Sopenharmony_ci{ 25728c2ecf20Sopenharmony_ci struct btrfsic_block *block; 25738c2ecf20Sopenharmony_ci 25748c2ecf20Sopenharmony_ci block = btrfsic_block_hashtable_lookup(block_ctx->dev->bdev, 25758c2ecf20Sopenharmony_ci block_ctx->dev_bytenr, 25768c2ecf20Sopenharmony_ci &state->block_hashtable); 25778c2ecf20Sopenharmony_ci if (NULL == block) { 25788c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state; 25798c2ecf20Sopenharmony_ci 25808c2ecf20Sopenharmony_ci block = btrfsic_block_alloc(); 25818c2ecf20Sopenharmony_ci if (!block) 25828c2ecf20Sopenharmony_ci return NULL; 25838c2ecf20Sopenharmony_ci 25848c2ecf20Sopenharmony_ci dev_state = btrfsic_dev_state_lookup(block_ctx->dev->bdev->bd_dev); 25858c2ecf20Sopenharmony_ci if (NULL == dev_state) { 25868c2ecf20Sopenharmony_ci pr_info("btrfsic: error, lookup dev_state failed!\n"); 25878c2ecf20Sopenharmony_ci btrfsic_block_free(block); 25888c2ecf20Sopenharmony_ci return NULL; 25898c2ecf20Sopenharmony_ci } 25908c2ecf20Sopenharmony_ci block->dev_state = dev_state; 25918c2ecf20Sopenharmony_ci block->dev_bytenr = block_ctx->dev_bytenr; 25928c2ecf20Sopenharmony_ci block->logical_bytenr = block_ctx->start; 25938c2ecf20Sopenharmony_ci block->is_metadata = is_metadata; 25948c2ecf20Sopenharmony_ci block->is_iodone = is_iodone; 25958c2ecf20Sopenharmony_ci block->never_written = never_written; 25968c2ecf20Sopenharmony_ci block->mirror_num = mirror_num; 25978c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 25988c2ecf20Sopenharmony_ci pr_info("New %s%c-block @%llu (%s/%llu/%d)\n", 25998c2ecf20Sopenharmony_ci additional_string, 26008c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, block), 26018c2ecf20Sopenharmony_ci block->logical_bytenr, dev_state->name, 26028c2ecf20Sopenharmony_ci block->dev_bytenr, mirror_num); 26038c2ecf20Sopenharmony_ci list_add(&block->all_blocks_node, &state->all_blocks_list); 26048c2ecf20Sopenharmony_ci btrfsic_block_hashtable_add(block, &state->block_hashtable); 26058c2ecf20Sopenharmony_ci if (NULL != was_created) 26068c2ecf20Sopenharmony_ci *was_created = 1; 26078c2ecf20Sopenharmony_ci } else { 26088c2ecf20Sopenharmony_ci if (NULL != was_created) 26098c2ecf20Sopenharmony_ci *was_created = 0; 26108c2ecf20Sopenharmony_ci } 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci return block; 26138c2ecf20Sopenharmony_ci} 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_cistatic void btrfsic_cmp_log_and_dev_bytenr(struct btrfsic_state *state, 26168c2ecf20Sopenharmony_ci u64 bytenr, 26178c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state, 26188c2ecf20Sopenharmony_ci u64 dev_bytenr) 26198c2ecf20Sopenharmony_ci{ 26208c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = state->fs_info; 26218c2ecf20Sopenharmony_ci struct btrfsic_block_data_ctx block_ctx; 26228c2ecf20Sopenharmony_ci int num_copies; 26238c2ecf20Sopenharmony_ci int mirror_num; 26248c2ecf20Sopenharmony_ci int match = 0; 26258c2ecf20Sopenharmony_ci int ret; 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci num_copies = btrfs_num_copies(fs_info, bytenr, state->metablock_size); 26288c2ecf20Sopenharmony_ci 26298c2ecf20Sopenharmony_ci for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) { 26308c2ecf20Sopenharmony_ci ret = btrfsic_map_block(state, bytenr, state->metablock_size, 26318c2ecf20Sopenharmony_ci &block_ctx, mirror_num); 26328c2ecf20Sopenharmony_ci if (ret) { 26338c2ecf20Sopenharmony_ci pr_info("btrfsic: btrfsic_map_block(logical @%llu, mirror %d) failed!\n", 26348c2ecf20Sopenharmony_ci bytenr, mirror_num); 26358c2ecf20Sopenharmony_ci continue; 26368c2ecf20Sopenharmony_ci } 26378c2ecf20Sopenharmony_ci 26388c2ecf20Sopenharmony_ci if (dev_state->bdev == block_ctx.dev->bdev && 26398c2ecf20Sopenharmony_ci dev_bytenr == block_ctx.dev_bytenr) { 26408c2ecf20Sopenharmony_ci match++; 26418c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&block_ctx); 26428c2ecf20Sopenharmony_ci break; 26438c2ecf20Sopenharmony_ci } 26448c2ecf20Sopenharmony_ci btrfsic_release_block_ctx(&block_ctx); 26458c2ecf20Sopenharmony_ci } 26468c2ecf20Sopenharmony_ci 26478c2ecf20Sopenharmony_ci if (WARN_ON(!match)) { 26488c2ecf20Sopenharmony_ci pr_info("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=%s, phys_bytenr=%llu)!\n", 26498c2ecf20Sopenharmony_ci bytenr, dev_state->name, dev_bytenr); 26508c2ecf20Sopenharmony_ci for (mirror_num = 1; mirror_num <= num_copies; mirror_num++) { 26518c2ecf20Sopenharmony_ci ret = btrfsic_map_block(state, bytenr, 26528c2ecf20Sopenharmony_ci state->metablock_size, 26538c2ecf20Sopenharmony_ci &block_ctx, mirror_num); 26548c2ecf20Sopenharmony_ci if (ret) 26558c2ecf20Sopenharmony_ci continue; 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci pr_info("Read logical bytenr @%llu maps to (%s/%llu/%d)\n", 26588c2ecf20Sopenharmony_ci bytenr, block_ctx.dev->name, 26598c2ecf20Sopenharmony_ci block_ctx.dev_bytenr, mirror_num); 26608c2ecf20Sopenharmony_ci } 26618c2ecf20Sopenharmony_ci } 26628c2ecf20Sopenharmony_ci} 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_cistatic struct btrfsic_dev_state *btrfsic_dev_state_lookup(dev_t dev) 26658c2ecf20Sopenharmony_ci{ 26668c2ecf20Sopenharmony_ci return btrfsic_dev_state_hashtable_lookup(dev, 26678c2ecf20Sopenharmony_ci &btrfsic_dev_state_hashtable); 26688c2ecf20Sopenharmony_ci} 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_cistatic void __btrfsic_submit_bio(struct bio *bio) 26718c2ecf20Sopenharmony_ci{ 26728c2ecf20Sopenharmony_ci struct btrfsic_dev_state *dev_state; 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci if (!btrfsic_is_initialized) 26758c2ecf20Sopenharmony_ci return; 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci mutex_lock(&btrfsic_mutex); 26788c2ecf20Sopenharmony_ci /* since btrfsic_submit_bio() is also called before 26798c2ecf20Sopenharmony_ci * btrfsic_mount(), this might return NULL */ 26808c2ecf20Sopenharmony_ci dev_state = btrfsic_dev_state_lookup(bio_dev(bio) + bio->bi_partno); 26818c2ecf20Sopenharmony_ci if (NULL != dev_state && 26828c2ecf20Sopenharmony_ci (bio_op(bio) == REQ_OP_WRITE) && bio_has_data(bio)) { 26838c2ecf20Sopenharmony_ci unsigned int i = 0; 26848c2ecf20Sopenharmony_ci u64 dev_bytenr; 26858c2ecf20Sopenharmony_ci u64 cur_bytenr; 26868c2ecf20Sopenharmony_ci struct bio_vec bvec; 26878c2ecf20Sopenharmony_ci struct bvec_iter iter; 26888c2ecf20Sopenharmony_ci int bio_is_patched; 26898c2ecf20Sopenharmony_ci char **mapped_datav; 26908c2ecf20Sopenharmony_ci unsigned int segs = bio_segments(bio); 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci dev_bytenr = 512 * bio->bi_iter.bi_sector; 26938c2ecf20Sopenharmony_ci bio_is_patched = 0; 26948c2ecf20Sopenharmony_ci if (dev_state->state->print_mask & 26958c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) 26968c2ecf20Sopenharmony_ci pr_info("submit_bio(rw=%d,0x%x, bi_vcnt=%u, bi_sector=%llu (bytenr %llu), bi_disk=%p)\n", 26978c2ecf20Sopenharmony_ci bio_op(bio), bio->bi_opf, segs, 26988c2ecf20Sopenharmony_ci (unsigned long long)bio->bi_iter.bi_sector, 26998c2ecf20Sopenharmony_ci dev_bytenr, bio->bi_disk); 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_ci mapped_datav = kmalloc_array(segs, 27028c2ecf20Sopenharmony_ci sizeof(*mapped_datav), GFP_NOFS); 27038c2ecf20Sopenharmony_ci if (!mapped_datav) 27048c2ecf20Sopenharmony_ci goto leave; 27058c2ecf20Sopenharmony_ci cur_bytenr = dev_bytenr; 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci bio_for_each_segment(bvec, bio, iter) { 27088c2ecf20Sopenharmony_ci BUG_ON(bvec.bv_len != PAGE_SIZE); 27098c2ecf20Sopenharmony_ci mapped_datav[i] = kmap(bvec.bv_page); 27108c2ecf20Sopenharmony_ci i++; 27118c2ecf20Sopenharmony_ci 27128c2ecf20Sopenharmony_ci if (dev_state->state->print_mask & 27138c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH_VERBOSE) 27148c2ecf20Sopenharmony_ci pr_info("#%u: bytenr=%llu, len=%u, offset=%u\n", 27158c2ecf20Sopenharmony_ci i, cur_bytenr, bvec.bv_len, bvec.bv_offset); 27168c2ecf20Sopenharmony_ci cur_bytenr += bvec.bv_len; 27178c2ecf20Sopenharmony_ci } 27188c2ecf20Sopenharmony_ci btrfsic_process_written_block(dev_state, dev_bytenr, 27198c2ecf20Sopenharmony_ci mapped_datav, segs, 27208c2ecf20Sopenharmony_ci bio, &bio_is_patched, 27218c2ecf20Sopenharmony_ci bio->bi_opf); 27228c2ecf20Sopenharmony_ci bio_for_each_segment(bvec, bio, iter) 27238c2ecf20Sopenharmony_ci kunmap(bvec.bv_page); 27248c2ecf20Sopenharmony_ci kfree(mapped_datav); 27258c2ecf20Sopenharmony_ci } else if (NULL != dev_state && (bio->bi_opf & REQ_PREFLUSH)) { 27268c2ecf20Sopenharmony_ci if (dev_state->state->print_mask & 27278c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) 27288c2ecf20Sopenharmony_ci pr_info("submit_bio(rw=%d,0x%x FLUSH, disk=%p)\n", 27298c2ecf20Sopenharmony_ci bio_op(bio), bio->bi_opf, bio->bi_disk); 27308c2ecf20Sopenharmony_ci if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) { 27318c2ecf20Sopenharmony_ci if ((dev_state->state->print_mask & 27328c2ecf20Sopenharmony_ci (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH | 27338c2ecf20Sopenharmony_ci BTRFSIC_PRINT_MASK_VERBOSE))) 27348c2ecf20Sopenharmony_ci pr_info("btrfsic_submit_bio(%s) with FLUSH but dummy block already in use (ignored)!\n", 27358c2ecf20Sopenharmony_ci dev_state->name); 27368c2ecf20Sopenharmony_ci } else { 27378c2ecf20Sopenharmony_ci struct btrfsic_block *const block = 27388c2ecf20Sopenharmony_ci &dev_state->dummy_block_for_bio_bh_flush; 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci block->is_iodone = 0; 27418c2ecf20Sopenharmony_ci block->never_written = 0; 27428c2ecf20Sopenharmony_ci block->iodone_w_error = 0; 27438c2ecf20Sopenharmony_ci block->flush_gen = dev_state->last_flush_gen + 1; 27448c2ecf20Sopenharmony_ci block->submit_bio_bh_rw = bio->bi_opf; 27458c2ecf20Sopenharmony_ci block->orig_bio_private = bio->bi_private; 27468c2ecf20Sopenharmony_ci block->orig_bio_end_io = bio->bi_end_io; 27478c2ecf20Sopenharmony_ci block->next_in_same_bio = NULL; 27488c2ecf20Sopenharmony_ci bio->bi_private = block; 27498c2ecf20Sopenharmony_ci bio->bi_end_io = btrfsic_bio_end_io; 27508c2ecf20Sopenharmony_ci } 27518c2ecf20Sopenharmony_ci } 27528c2ecf20Sopenharmony_cileave: 27538c2ecf20Sopenharmony_ci mutex_unlock(&btrfsic_mutex); 27548c2ecf20Sopenharmony_ci} 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_civoid btrfsic_submit_bio(struct bio *bio) 27578c2ecf20Sopenharmony_ci{ 27588c2ecf20Sopenharmony_ci __btrfsic_submit_bio(bio); 27598c2ecf20Sopenharmony_ci submit_bio(bio); 27608c2ecf20Sopenharmony_ci} 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ciint btrfsic_submit_bio_wait(struct bio *bio) 27638c2ecf20Sopenharmony_ci{ 27648c2ecf20Sopenharmony_ci __btrfsic_submit_bio(bio); 27658c2ecf20Sopenharmony_ci return submit_bio_wait(bio); 27668c2ecf20Sopenharmony_ci} 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ciint btrfsic_mount(struct btrfs_fs_info *fs_info, 27698c2ecf20Sopenharmony_ci struct btrfs_fs_devices *fs_devices, 27708c2ecf20Sopenharmony_ci int including_extent_data, u32 print_mask) 27718c2ecf20Sopenharmony_ci{ 27728c2ecf20Sopenharmony_ci int ret; 27738c2ecf20Sopenharmony_ci struct btrfsic_state *state; 27748c2ecf20Sopenharmony_ci struct list_head *dev_head = &fs_devices->devices; 27758c2ecf20Sopenharmony_ci struct btrfs_device *device; 27768c2ecf20Sopenharmony_ci 27778c2ecf20Sopenharmony_ci if (!PAGE_ALIGNED(fs_info->nodesize)) { 27788c2ecf20Sopenharmony_ci pr_info("btrfsic: cannot handle nodesize %d not being a multiple of PAGE_SIZE %ld!\n", 27798c2ecf20Sopenharmony_ci fs_info->nodesize, PAGE_SIZE); 27808c2ecf20Sopenharmony_ci return -1; 27818c2ecf20Sopenharmony_ci } 27828c2ecf20Sopenharmony_ci if (!PAGE_ALIGNED(fs_info->sectorsize)) { 27838c2ecf20Sopenharmony_ci pr_info("btrfsic: cannot handle sectorsize %d not being a multiple of PAGE_SIZE %ld!\n", 27848c2ecf20Sopenharmony_ci fs_info->sectorsize, PAGE_SIZE); 27858c2ecf20Sopenharmony_ci return -1; 27868c2ecf20Sopenharmony_ci } 27878c2ecf20Sopenharmony_ci state = kvzalloc(sizeof(*state), GFP_KERNEL); 27888c2ecf20Sopenharmony_ci if (!state) 27898c2ecf20Sopenharmony_ci return -ENOMEM; 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci if (!btrfsic_is_initialized) { 27928c2ecf20Sopenharmony_ci mutex_init(&btrfsic_mutex); 27938c2ecf20Sopenharmony_ci btrfsic_dev_state_hashtable_init(&btrfsic_dev_state_hashtable); 27948c2ecf20Sopenharmony_ci btrfsic_is_initialized = 1; 27958c2ecf20Sopenharmony_ci } 27968c2ecf20Sopenharmony_ci mutex_lock(&btrfsic_mutex); 27978c2ecf20Sopenharmony_ci state->fs_info = fs_info; 27988c2ecf20Sopenharmony_ci state->print_mask = print_mask; 27998c2ecf20Sopenharmony_ci state->include_extent_data = including_extent_data; 28008c2ecf20Sopenharmony_ci state->csum_size = 0; 28018c2ecf20Sopenharmony_ci state->metablock_size = fs_info->nodesize; 28028c2ecf20Sopenharmony_ci state->datablock_size = fs_info->sectorsize; 28038c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&state->all_blocks_list); 28048c2ecf20Sopenharmony_ci btrfsic_block_hashtable_init(&state->block_hashtable); 28058c2ecf20Sopenharmony_ci btrfsic_block_link_hashtable_init(&state->block_link_hashtable); 28068c2ecf20Sopenharmony_ci state->max_superblock_generation = 0; 28078c2ecf20Sopenharmony_ci state->latest_superblock = NULL; 28088c2ecf20Sopenharmony_ci 28098c2ecf20Sopenharmony_ci list_for_each_entry(device, dev_head, dev_list) { 28108c2ecf20Sopenharmony_ci struct btrfsic_dev_state *ds; 28118c2ecf20Sopenharmony_ci const char *p; 28128c2ecf20Sopenharmony_ci 28138c2ecf20Sopenharmony_ci if (!device->bdev || !device->name) 28148c2ecf20Sopenharmony_ci continue; 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci ds = btrfsic_dev_state_alloc(); 28178c2ecf20Sopenharmony_ci if (NULL == ds) { 28188c2ecf20Sopenharmony_ci mutex_unlock(&btrfsic_mutex); 28198c2ecf20Sopenharmony_ci return -ENOMEM; 28208c2ecf20Sopenharmony_ci } 28218c2ecf20Sopenharmony_ci ds->bdev = device->bdev; 28228c2ecf20Sopenharmony_ci ds->state = state; 28238c2ecf20Sopenharmony_ci bdevname(ds->bdev, ds->name); 28248c2ecf20Sopenharmony_ci ds->name[BDEVNAME_SIZE - 1] = '\0'; 28258c2ecf20Sopenharmony_ci p = kbasename(ds->name); 28268c2ecf20Sopenharmony_ci strlcpy(ds->name, p, sizeof(ds->name)); 28278c2ecf20Sopenharmony_ci btrfsic_dev_state_hashtable_add(ds, 28288c2ecf20Sopenharmony_ci &btrfsic_dev_state_hashtable); 28298c2ecf20Sopenharmony_ci } 28308c2ecf20Sopenharmony_ci 28318c2ecf20Sopenharmony_ci ret = btrfsic_process_superblock(state, fs_devices); 28328c2ecf20Sopenharmony_ci if (0 != ret) { 28338c2ecf20Sopenharmony_ci mutex_unlock(&btrfsic_mutex); 28348c2ecf20Sopenharmony_ci btrfsic_unmount(fs_devices); 28358c2ecf20Sopenharmony_ci return ret; 28368c2ecf20Sopenharmony_ci } 28378c2ecf20Sopenharmony_ci 28388c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_DATABASE) 28398c2ecf20Sopenharmony_ci btrfsic_dump_database(state); 28408c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_TREE) 28418c2ecf20Sopenharmony_ci btrfsic_dump_tree(state); 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci mutex_unlock(&btrfsic_mutex); 28448c2ecf20Sopenharmony_ci return 0; 28458c2ecf20Sopenharmony_ci} 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_civoid btrfsic_unmount(struct btrfs_fs_devices *fs_devices) 28488c2ecf20Sopenharmony_ci{ 28498c2ecf20Sopenharmony_ci struct btrfsic_block *b_all, *tmp_all; 28508c2ecf20Sopenharmony_ci struct btrfsic_state *state; 28518c2ecf20Sopenharmony_ci struct list_head *dev_head = &fs_devices->devices; 28528c2ecf20Sopenharmony_ci struct btrfs_device *device; 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_ci if (!btrfsic_is_initialized) 28558c2ecf20Sopenharmony_ci return; 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_ci mutex_lock(&btrfsic_mutex); 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_ci state = NULL; 28608c2ecf20Sopenharmony_ci list_for_each_entry(device, dev_head, dev_list) { 28618c2ecf20Sopenharmony_ci struct btrfsic_dev_state *ds; 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci if (!device->bdev || !device->name) 28648c2ecf20Sopenharmony_ci continue; 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci ds = btrfsic_dev_state_hashtable_lookup( 28678c2ecf20Sopenharmony_ci device->bdev->bd_dev, 28688c2ecf20Sopenharmony_ci &btrfsic_dev_state_hashtable); 28698c2ecf20Sopenharmony_ci if (NULL != ds) { 28708c2ecf20Sopenharmony_ci state = ds->state; 28718c2ecf20Sopenharmony_ci btrfsic_dev_state_hashtable_remove(ds); 28728c2ecf20Sopenharmony_ci btrfsic_dev_state_free(ds); 28738c2ecf20Sopenharmony_ci } 28748c2ecf20Sopenharmony_ci } 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_ci if (NULL == state) { 28778c2ecf20Sopenharmony_ci pr_info("btrfsic: error, cannot find state information on umount!\n"); 28788c2ecf20Sopenharmony_ci mutex_unlock(&btrfsic_mutex); 28798c2ecf20Sopenharmony_ci return; 28808c2ecf20Sopenharmony_ci } 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci /* 28838c2ecf20Sopenharmony_ci * Don't care about keeping the lists' state up to date, 28848c2ecf20Sopenharmony_ci * just free all memory that was allocated dynamically. 28858c2ecf20Sopenharmony_ci * Free the blocks and the block_links. 28868c2ecf20Sopenharmony_ci */ 28878c2ecf20Sopenharmony_ci list_for_each_entry_safe(b_all, tmp_all, &state->all_blocks_list, 28888c2ecf20Sopenharmony_ci all_blocks_node) { 28898c2ecf20Sopenharmony_ci struct btrfsic_block_link *l, *tmp; 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci list_for_each_entry_safe(l, tmp, &b_all->ref_to_list, 28928c2ecf20Sopenharmony_ci node_ref_to) { 28938c2ecf20Sopenharmony_ci if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) 28948c2ecf20Sopenharmony_ci btrfsic_print_rem_link(state, l); 28958c2ecf20Sopenharmony_ci 28968c2ecf20Sopenharmony_ci l->ref_cnt--; 28978c2ecf20Sopenharmony_ci if (0 == l->ref_cnt) 28988c2ecf20Sopenharmony_ci btrfsic_block_link_free(l); 28998c2ecf20Sopenharmony_ci } 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci if (b_all->is_iodone || b_all->never_written) 29028c2ecf20Sopenharmony_ci btrfsic_block_free(b_all); 29038c2ecf20Sopenharmony_ci else 29048c2ecf20Sopenharmony_ci pr_info("btrfs: attempt to free %c-block @%llu (%s/%llu/%d) on umount which is not yet iodone!\n", 29058c2ecf20Sopenharmony_ci btrfsic_get_block_type(state, b_all), 29068c2ecf20Sopenharmony_ci b_all->logical_bytenr, b_all->dev_state->name, 29078c2ecf20Sopenharmony_ci b_all->dev_bytenr, b_all->mirror_num); 29088c2ecf20Sopenharmony_ci } 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci mutex_unlock(&btrfsic_mutex); 29118c2ecf20Sopenharmony_ci 29128c2ecf20Sopenharmony_ci kvfree(state); 29138c2ecf20Sopenharmony_ci} 2914