@@ -2159,6 +2159,112 @@ static int scrub_checksum_data(struct scrub_block *sblock)
21592159 return sblock -> checksum_error ;
21602160}
21612161
2162+ static struct page * scrub_stripe_get_page (struct scrub_stripe * stripe , int sector_nr )
2163+ {
2164+ struct btrfs_fs_info * fs_info = stripe -> bg -> fs_info ;
2165+ int page_index = (sector_nr << fs_info -> sectorsize_bits ) >> PAGE_SHIFT ;
2166+
2167+ return stripe -> pages [page_index ];
2168+ }
2169+
2170+ static unsigned int scrub_stripe_get_page_offset (struct scrub_stripe * stripe ,
2171+ int sector_nr )
2172+ {
2173+ struct btrfs_fs_info * fs_info = stripe -> bg -> fs_info ;
2174+
2175+ return offset_in_page (sector_nr << fs_info -> sectorsize_bits );
2176+ }
2177+
2178+ void scrub_verify_one_metadata (struct scrub_stripe * stripe , int sector_nr )
2179+ {
2180+ struct btrfs_fs_info * fs_info = stripe -> bg -> fs_info ;
2181+ const u32 sectors_per_tree = fs_info -> nodesize >> fs_info -> sectorsize_bits ;
2182+ const u64 logical = stripe -> logical + (sector_nr << fs_info -> sectorsize_bits );
2183+ const struct page * first_page = scrub_stripe_get_page (stripe , sector_nr );
2184+ const unsigned int first_off = scrub_stripe_get_page_offset (stripe , sector_nr );
2185+ SHASH_DESC_ON_STACK (shash , fs_info -> csum_shash );
2186+ u8 on_disk_csum [BTRFS_CSUM_SIZE ];
2187+ u8 calculated_csum [BTRFS_CSUM_SIZE ];
2188+ struct btrfs_header * header ;
2189+
2190+ /*
2191+ * Here we don't have a good way to attach the pages (and subpages)
2192+ * to a dummy extent buffer, thus we have to directly grab the members
2193+ * from pages.
2194+ */
2195+ header = (struct btrfs_header * )(page_address (first_page ) + first_off );
2196+ memcpy (on_disk_csum , header -> csum , fs_info -> csum_size );
2197+
2198+ if (logical != btrfs_stack_header_bytenr (header )) {
2199+ bitmap_set (& stripe -> csum_error_bitmap , sector_nr , sectors_per_tree );
2200+ bitmap_set (& stripe -> error_bitmap , sector_nr , sectors_per_tree );
2201+ btrfs_warn_rl (fs_info ,
2202+ "tree block %llu mirror %u has bad bytenr, has %llu want %llu" ,
2203+ logical , stripe -> mirror_num ,
2204+ btrfs_stack_header_bytenr (header ), logical );
2205+ return ;
2206+ }
2207+ if (memcmp (header -> fsid , fs_info -> fs_devices -> fsid , BTRFS_FSID_SIZE ) != 0 ) {
2208+ bitmap_set (& stripe -> meta_error_bitmap , sector_nr , sectors_per_tree );
2209+ bitmap_set (& stripe -> error_bitmap , sector_nr , sectors_per_tree );
2210+ btrfs_warn_rl (fs_info ,
2211+ "tree block %llu mirror %u has bad fsid, has %pU want %pU" ,
2212+ logical , stripe -> mirror_num ,
2213+ header -> fsid , fs_info -> fs_devices -> fsid );
2214+ return ;
2215+ }
2216+ if (memcmp (header -> chunk_tree_uuid , fs_info -> chunk_tree_uuid ,
2217+ BTRFS_UUID_SIZE ) != 0 ) {
2218+ bitmap_set (& stripe -> meta_error_bitmap , sector_nr , sectors_per_tree );
2219+ bitmap_set (& stripe -> error_bitmap , sector_nr , sectors_per_tree );
2220+ btrfs_warn_rl (fs_info ,
2221+ "tree block %llu mirror %u has bad chunk tree uuid, has %pU want %pU" ,
2222+ logical , stripe -> mirror_num ,
2223+ header -> chunk_tree_uuid , fs_info -> chunk_tree_uuid );
2224+ return ;
2225+ }
2226+
2227+ /* Now check tree block csum. */
2228+ shash -> tfm = fs_info -> csum_shash ;
2229+ crypto_shash_init (shash );
2230+ crypto_shash_update (shash , page_address (first_page ) + first_off +
2231+ BTRFS_CSUM_SIZE , fs_info -> sectorsize - BTRFS_CSUM_SIZE );
2232+
2233+ for (int i = sector_nr + 1 ; i < sector_nr + sectors_per_tree ; i ++ ) {
2234+ struct page * page = scrub_stripe_get_page (stripe , i );
2235+ unsigned int page_off = scrub_stripe_get_page_offset (stripe , i );
2236+
2237+ crypto_shash_update (shash , page_address (page ) + page_off ,
2238+ fs_info -> sectorsize );
2239+ }
2240+
2241+ crypto_shash_final (shash , calculated_csum );
2242+ if (memcmp (calculated_csum , on_disk_csum , fs_info -> csum_size ) != 0 ) {
2243+ bitmap_set (& stripe -> meta_error_bitmap , sector_nr , sectors_per_tree );
2244+ bitmap_set (& stripe -> error_bitmap , sector_nr , sectors_per_tree );
2245+ btrfs_warn_rl (fs_info ,
2246+ "tree block %llu mirror %u has bad csum, has " CSUM_FMT " want " CSUM_FMT ,
2247+ logical , stripe -> mirror_num ,
2248+ CSUM_FMT_VALUE (fs_info -> csum_size , on_disk_csum ),
2249+ CSUM_FMT_VALUE (fs_info -> csum_size , calculated_csum ));
2250+ return ;
2251+ }
2252+ if (stripe -> sectors [sector_nr ].generation !=
2253+ btrfs_stack_header_generation (header )) {
2254+ bitmap_set (& stripe -> meta_error_bitmap , sector_nr , sectors_per_tree );
2255+ bitmap_set (& stripe -> error_bitmap , sector_nr , sectors_per_tree );
2256+ btrfs_warn_rl (fs_info ,
2257+ "tree block %llu mirror %u has bad generation, has %llu want %llu" ,
2258+ logical , stripe -> mirror_num ,
2259+ btrfs_stack_header_generation (header ),
2260+ stripe -> sectors [sector_nr ].generation );
2261+ return ;
2262+ }
2263+ bitmap_clear (& stripe -> error_bitmap , sector_nr , sectors_per_tree );
2264+ bitmap_clear (& stripe -> csum_error_bitmap , sector_nr , sectors_per_tree );
2265+ bitmap_clear (& stripe -> meta_error_bitmap , sector_nr , sectors_per_tree );
2266+ }
2267+
21622268static int scrub_checksum_tree_block (struct scrub_block * sblock )
21632269{
21642270 struct scrub_ctx * sctx = sblock -> sctx ;
0 commit comments