@@ -488,6 +488,17 @@ static int bch2_check_fix_ptr(struct btree_trans *trans,
488488 }
489489
490490 struct bucket * g = PTR_GC_BUCKET (ca , & p .ptr );
491+ if (!g ) {
492+ if (fsck_err (c , ptr_to_invalid_device ,
493+ "pointer to invalid bucket on device %u\n"
494+ "while marking %s" ,
495+ p .ptr .dev ,
496+ (printbuf_reset (& buf ),
497+ bch2_bkey_val_to_text (& buf , c , k ), buf .buf )))
498+ * do_update = true;
499+ goto out ;
500+ }
501+
491502 enum bch_data_type data_type = bch2_bkey_ptr_data_type (k , p , entry );
492503
493504 if (fsck_err_on (!g -> gen_valid ,
@@ -577,17 +588,17 @@ static int bch2_check_fix_ptr(struct btree_trans *trans,
577588 if (p .has_ec ) {
578589 struct gc_stripe * m = genradix_ptr (& c -> gc_stripes , p .ec .idx );
579590
580- if (fsck_err_on (!m || !m -> alive , c ,
581- ptr_to_missing_stripe ,
591+ if (fsck_err_on (!m || !m -> alive ,
592+ c , ptr_to_missing_stripe ,
582593 "pointer to nonexistent stripe %llu\n"
583594 "while marking %s" ,
584595 (u64 ) p .ec .idx ,
585596 (printbuf_reset (& buf ),
586597 bch2_bkey_val_to_text (& buf , c , k ), buf .buf )))
587598 * do_update = true;
588599
589- if (fsck_err_on (m && m -> alive && !bch2_ptr_matches_stripe_m (m , p ), c ,
590- ptr_to_incorrect_stripe ,
600+ if (fsck_err_on (m && m -> alive && !bch2_ptr_matches_stripe_m (m , p ),
601+ c , ptr_to_incorrect_stripe ,
591602 "pointer does not match stripe %llu\n"
592603 "while marking %s" ,
593604 (u64 ) p .ec .idx ,
@@ -1004,6 +1015,7 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
10041015 enum btree_iter_update_trigger_flags flags )
10051016{
10061017 bool insert = !(flags & BTREE_TRIGGER_overwrite );
1018+ struct printbuf buf = PRINTBUF ;
10071019 int ret = 0 ;
10081020
10091021 struct bch_fs * c = trans -> c ;
@@ -1036,6 +1048,13 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
10361048 if (flags & BTREE_TRIGGER_gc ) {
10371049 percpu_down_read (& c -> mark_lock );
10381050 struct bucket * g = gc_bucket (ca , bucket .offset );
1051+ if (bch2_fs_inconsistent_on (!g , c , "reference to invalid bucket on device %u\n %s" ,
1052+ p .ptr .dev ,
1053+ (bch2_bkey_val_to_text (& buf , c , k ), buf .buf ))) {
1054+ ret = - EIO ;
1055+ goto err_unlock ;
1056+ }
1057+
10391058 bucket_lock (g );
10401059 struct bch_alloc_v4 old = bucket_m_to_alloc (* g ), new = old ;
10411060 ret = __mark_pointer (trans , ca , k , & p .ptr , * sectors , bp .data_type , & new );
@@ -1044,10 +1063,12 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
10441063 bch2_dev_usage_update (c , ca , & old , & new , 0 , true);
10451064 }
10461065 bucket_unlock (g );
1066+ err_unlock :
10471067 percpu_up_read (& c -> mark_lock );
10481068 }
10491069err :
10501070 bch2_dev_put (ca );
1071+ printbuf_exit (& buf );
10511072 return ret ;
10521073}
10531074
@@ -1335,10 +1356,11 @@ static int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
13351356 u64 b , enum bch_data_type data_type , unsigned sectors ,
13361357 enum btree_iter_update_trigger_flags flags )
13371358{
1338- int ret = 0 ;
1339-
13401359 percpu_down_read (& c -> mark_lock );
13411360 struct bucket * g = gc_bucket (ca , b );
1361+ if (bch2_fs_inconsistent_on (!g , c , "reference to invalid bucket on device %u when marking metadata type %s" ,
1362+ ca -> dev_idx , bch2_data_type_str (data_type )))
1363+ goto err_unlock ;
13421364
13431365 bucket_lock (g );
13441366 struct bch_alloc_v4 old = bucket_m_to_alloc (* g );
@@ -1347,29 +1369,27 @@ static int bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
13471369 g -> data_type != data_type , c ,
13481370 "different types of data in same bucket: %s, %s" ,
13491371 bch2_data_type_str (g -> data_type ),
1350- bch2_data_type_str (data_type ))) {
1351- ret = - EIO ;
1372+ bch2_data_type_str (data_type )))
13521373 goto err ;
1353- }
13541374
13551375 if (bch2_fs_inconsistent_on ((u64 ) g -> dirty_sectors + sectors > ca -> mi .bucket_size , c ,
13561376 "bucket %u:%llu gen %u data type %s sector count overflow: %u + %u > bucket size" ,
13571377 ca -> dev_idx , b , g -> gen ,
13581378 bch2_data_type_str (g -> data_type ?: data_type ),
1359- g -> dirty_sectors , sectors )) {
1360- ret = - EIO ;
1379+ g -> dirty_sectors , sectors ))
13611380 goto err ;
1362- }
13631381
13641382 g -> data_type = data_type ;
13651383 g -> dirty_sectors += sectors ;
13661384 struct bch_alloc_v4 new = bucket_m_to_alloc (* g );
1385+ bch2_dev_usage_update (c , ca , & old , & new , 0 , true);
1386+ percpu_up_read (& c -> mark_lock );
1387+ return 0 ;
13671388err :
13681389 bucket_unlock (g );
1369- if (!ret )
1370- bch2_dev_usage_update (c , ca , & old , & new , 0 , true);
1390+ err_unlock :
13711391 percpu_up_read (& c -> mark_lock );
1372- return ret ;
1392+ return - EIO ;
13731393}
13741394
13751395int bch2_trans_mark_metadata_bucket (struct btree_trans * trans ,
0 commit comments