@@ -427,13 +427,59 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info,
427
427
return ret ;
428
428
}
429
429
430
+ static int verify_level_key (struct btrfs_fs_info * fs_info ,
431
+ struct extent_buffer * eb , int level ,
432
+ struct btrfs_key * first_key )
433
+ {
434
+ int found_level ;
435
+ struct btrfs_key found_key ;
436
+ int ret ;
437
+
438
+ found_level = btrfs_header_level (eb );
439
+ if (found_level != level ) {
440
+ #ifdef CONFIG_BTRFS_DEBUG
441
+ WARN_ON (1 );
442
+ btrfs_err (fs_info ,
443
+ "tree level mismatch detected, bytenr=%llu level expected=%u has=%u" ,
444
+ eb -> start , level , found_level );
445
+ #endif
446
+ return - EIO ;
447
+ }
448
+
449
+ if (!first_key )
450
+ return 0 ;
451
+
452
+ if (found_level )
453
+ btrfs_node_key_to_cpu (eb , & found_key , 0 );
454
+ else
455
+ btrfs_item_key_to_cpu (eb , & found_key , 0 );
456
+ ret = btrfs_comp_cpu_keys (first_key , & found_key );
457
+
458
+ #ifdef CONFIG_BTRFS_DEBUG
459
+ if (ret ) {
460
+ WARN_ON (1 );
461
+ btrfs_err (fs_info ,
462
+ "tree first key mismatch detected, bytenr=%llu key expected=(%llu, %u, %llu) has=(%llu, %u, %llu)" ,
463
+ eb -> start , first_key -> objectid , first_key -> type ,
464
+ first_key -> offset , found_key .objectid ,
465
+ found_key .type , found_key .offset );
466
+ }
467
+ #endif
468
+ return ret ;
469
+ }
470
+
430
471
/*
431
472
* helper to read a given tree block, doing retries as required when
432
473
* the checksums don't match and we have alternate mirrors to try.
474
+ *
475
+ * @parent_transid: expected transid, skip check if 0
476
+ * @level: expected level, mandatory check
477
+ * @first_key: expected key of first slot, skip check if NULL
433
478
*/
434
479
static int btree_read_extent_buffer_pages (struct btrfs_fs_info * fs_info ,
435
480
struct extent_buffer * eb ,
436
- u64 parent_transid )
481
+ u64 parent_transid , int level ,
482
+ struct btrfs_key * first_key )
437
483
{
438
484
struct extent_io_tree * io_tree ;
439
485
int failed = 0 ;
@@ -448,19 +494,23 @@ static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info,
448
494
ret = read_extent_buffer_pages (io_tree , eb , WAIT_COMPLETE ,
449
495
mirror_num );
450
496
if (!ret ) {
451
- if (! verify_parent_transid (io_tree , eb ,
497
+ if (verify_parent_transid (io_tree , eb ,
452
498
parent_transid , 0 ))
453
- break ;
454
- else
455
499
ret = - EIO ;
500
+ else if (verify_level_key (fs_info , eb , level ,
501
+ first_key ))
502
+ ret = - EUCLEAN ;
503
+ else
504
+ break ;
456
505
}
457
506
458
507
/*
459
508
* This buffer's crc is fine, but its contents are corrupted, so
460
509
* there is no reason to read the other copies, they won't be
461
510
* any less wrong.
462
511
*/
463
- if (test_bit (EXTENT_BUFFER_CORRUPT , & eb -> bflags ))
512
+ if (test_bit (EXTENT_BUFFER_CORRUPT , & eb -> bflags ) ||
513
+ ret == - EUCLEAN )
464
514
break ;
465
515
466
516
num_copies = btrfs_num_copies (fs_info ,
@@ -1049,8 +1099,17 @@ void btrfs_wait_tree_block_writeback(struct extent_buffer *buf)
1049
1099
buf -> start , buf -> start + buf -> len - 1 );
1050
1100
}
1051
1101
1102
+ /*
1103
+ * Read tree block at logical address @bytenr and do variant basic but critical
1104
+ * verification.
1105
+ *
1106
+ * @parent_transid: expected transid of this tree block, skip check if 0
1107
+ * @level: expected level, mandatory check
1108
+ * @first_key: expected key in slot 0, skip check if NULL
1109
+ */
1052
1110
struct extent_buffer * read_tree_block (struct btrfs_fs_info * fs_info , u64 bytenr ,
1053
- u64 parent_transid )
1111
+ u64 parent_transid , int level ,
1112
+ struct btrfs_key * first_key )
1054
1113
{
1055
1114
struct extent_buffer * buf = NULL ;
1056
1115
int ret ;
@@ -1059,7 +1118,8 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
1059
1118
if (IS_ERR (buf ))
1060
1119
return buf ;
1061
1120
1062
- ret = btree_read_extent_buffer_pages (fs_info , buf , parent_transid );
1121
+ ret = btree_read_extent_buffer_pages (fs_info , buf , parent_transid ,
1122
+ level , first_key );
1063
1123
if (ret ) {
1064
1124
free_extent_buffer (buf );
1065
1125
return ERR_PTR (ret );
@@ -1388,6 +1448,7 @@ static struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
1388
1448
struct btrfs_path * path ;
1389
1449
u64 generation ;
1390
1450
int ret ;
1451
+ int level ;
1391
1452
1392
1453
path = btrfs_alloc_path ();
1393
1454
if (!path )
@@ -1410,9 +1471,10 @@ static struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
1410
1471
}
1411
1472
1412
1473
generation = btrfs_root_generation (& root -> root_item );
1474
+ level = btrfs_root_level (& root -> root_item );
1413
1475
root -> node = read_tree_block (fs_info ,
1414
1476
btrfs_root_bytenr (& root -> root_item ),
1415
- generation );
1477
+ generation , level , NULL );
1416
1478
if (IS_ERR (root -> node )) {
1417
1479
ret = PTR_ERR (root -> node );
1418
1480
goto find_fail ;
@@ -2261,6 +2323,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
2261
2323
struct btrfs_root * log_tree_root ;
2262
2324
struct btrfs_super_block * disk_super = fs_info -> super_copy ;
2263
2325
u64 bytenr = btrfs_super_log_root (disk_super );
2326
+ int level = btrfs_super_log_root_level (disk_super );
2264
2327
2265
2328
if (fs_devices -> rw_devices == 0 ) {
2266
2329
btrfs_warn (fs_info , "log replay required on RO media" );
@@ -2274,7 +2337,8 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
2274
2337
__setup_root (log_tree_root , fs_info , BTRFS_TREE_LOG_OBJECTID );
2275
2338
2276
2339
log_tree_root -> node = read_tree_block (fs_info , bytenr ,
2277
- fs_info -> generation + 1 );
2340
+ fs_info -> generation + 1 ,
2341
+ level , NULL );
2278
2342
if (IS_ERR (log_tree_root -> node )) {
2279
2343
btrfs_warn (fs_info , "failed to read log tree" );
2280
2344
ret = PTR_ERR (log_tree_root -> node );
@@ -2390,6 +2454,7 @@ int open_ctree(struct super_block *sb,
2390
2454
int num_backups_tried = 0 ;
2391
2455
int backup_index = 0 ;
2392
2456
int clear_free_space_tree = 0 ;
2457
+ int level ;
2393
2458
2394
2459
tree_root = fs_info -> tree_root = btrfs_alloc_root (fs_info , GFP_KERNEL );
2395
2460
chunk_root = fs_info -> chunk_root = btrfs_alloc_root (fs_info , GFP_KERNEL );
@@ -2725,12 +2790,13 @@ int open_ctree(struct super_block *sb,
2725
2790
}
2726
2791
2727
2792
generation = btrfs_super_chunk_root_generation (disk_super );
2793
+ level = btrfs_super_chunk_root_level (disk_super );
2728
2794
2729
2795
__setup_root (chunk_root , fs_info , BTRFS_CHUNK_TREE_OBJECTID );
2730
2796
2731
2797
chunk_root -> node = read_tree_block (fs_info ,
2732
2798
btrfs_super_chunk_root (disk_super ),
2733
- generation );
2799
+ generation , level , NULL );
2734
2800
if (IS_ERR (chunk_root -> node ) ||
2735
2801
!extent_buffer_uptodate (chunk_root -> node )) {
2736
2802
btrfs_err (fs_info , "failed to read chunk root" );
@@ -2764,10 +2830,11 @@ int open_ctree(struct super_block *sb,
2764
2830
2765
2831
retry_root_backup :
2766
2832
generation = btrfs_super_generation (disk_super );
2833
+ level = btrfs_super_root_level (disk_super );
2767
2834
2768
2835
tree_root -> node = read_tree_block (fs_info ,
2769
2836
btrfs_super_root (disk_super ),
2770
- generation );
2837
+ generation , level , NULL );
2771
2838
if (IS_ERR (tree_root -> node ) ||
2772
2839
!extent_buffer_uptodate (tree_root -> node )) {
2773
2840
btrfs_warn (fs_info , "failed to read tree root" );
@@ -3887,12 +3954,14 @@ void btrfs_btree_balance_dirty_nodelay(struct btrfs_fs_info *fs_info)
3887
3954
__btrfs_btree_balance_dirty (fs_info , 0 );
3888
3955
}
3889
3956
3890
- int btrfs_read_buffer (struct extent_buffer * buf , u64 parent_transid )
3957
+ int btrfs_read_buffer (struct extent_buffer * buf , u64 parent_transid , int level ,
3958
+ struct btrfs_key * first_key )
3891
3959
{
3892
3960
struct btrfs_root * root = BTRFS_I (buf -> pages [0 ]-> mapping -> host )-> root ;
3893
3961
struct btrfs_fs_info * fs_info = root -> fs_info ;
3894
3962
3895
- return btree_read_extent_buffer_pages (fs_info , buf , parent_transid );
3963
+ return btree_read_extent_buffer_pages (fs_info , buf , parent_transid ,
3964
+ level , first_key );
3896
3965
}
3897
3966
3898
3967
static int btrfs_check_super_valid (struct btrfs_fs_info * fs_info )
0 commit comments