@@ -1206,47 +1206,62 @@ void bch2_do_stripe_deletes(struct bch_fs *c)
1206
1206
/* stripe creation: */
1207
1207
1208
1208
static int ec_stripe_key_update (struct btree_trans * trans ,
1209
- struct bkey_i_stripe * new ,
1210
- bool create )
1209
+ struct bkey_i_stripe * old ,
1210
+ struct bkey_i_stripe * new )
1211
1211
{
1212
1212
struct bch_fs * c = trans -> c ;
1213
- struct btree_iter iter ;
1214
- struct bkey_s_c k ;
1215
- int ret ;
1213
+ bool create = !old ;
1216
1214
1217
- k = bch2_bkey_get_iter (trans , & iter , BTREE_ID_stripes ,
1218
- new -> k .p , BTREE_ITER_intent );
1219
- ret = bkey_err (k );
1215
+ struct btree_iter iter ;
1216
+ struct bkey_s_c k = bch2_bkey_get_iter (trans , & iter , BTREE_ID_stripes ,
1217
+ new -> k .p , BTREE_ITER_intent );
1218
+ int ret = bkey_err (k );
1220
1219
if (ret )
1221
1220
goto err ;
1222
1221
1223
- if (k .k -> type != (create ? KEY_TYPE_deleted : KEY_TYPE_stripe )) {
1224
- bch2_fs_inconsistent ( c , "error %s stripe: got existing key type %s" ,
1225
- create ? "creating" : "updating" ,
1226
- bch2_bkey_types [k .k -> type ]);
1222
+ if (bch2_fs_inconsistent_on ( k .k -> type != (create ? KEY_TYPE_deleted : KEY_TYPE_stripe ),
1223
+ c , "error %s stripe: got existing key type %s" ,
1224
+ create ? "creating" : "updating" ,
1225
+ bch2_bkey_types [k .k -> type ])) {
1227
1226
ret = - EINVAL ;
1228
1227
goto err ;
1229
1228
}
1230
1229
1231
1230
if (k .k -> type == KEY_TYPE_stripe ) {
1232
- const struct bch_stripe * old = bkey_s_c_to_stripe (k ).v ;
1233
- unsigned i ;
1231
+ const struct bch_stripe * v = bkey_s_c_to_stripe (k ).v ;
1234
1232
1235
- if (old -> nr_blocks != new -> v .nr_blocks ) {
1236
- bch_err (c , "error updating stripe: nr_blocks does not match" );
1237
- ret = - EINVAL ;
1238
- goto err ;
1239
- }
1233
+ BUG_ON (old -> v .nr_blocks != new -> v .nr_blocks );
1234
+ BUG_ON (old -> v .nr_blocks != v -> nr_blocks );
1235
+
1236
+ for (unsigned i = 0 ; i < new -> v .nr_blocks ; i ++ ) {
1237
+ unsigned sectors = stripe_blockcount_get (v , i );
1238
+
1239
+ if (!bch2_extent_ptr_eq (old -> v .ptrs [i ], new -> v .ptrs [i ]) && sectors ) {
1240
+ struct printbuf buf = PRINTBUF ;
1240
1241
1241
- for (i = 0 ; i < new -> v .nr_blocks ; i ++ ) {
1242
- unsigned v = stripe_blockcount_get (old , i );
1242
+ prt_printf (& buf , "stripe changed nonempty block %u" , i );
1243
+ prt_str (& buf , "\nold: " );
1244
+ bch2_bkey_val_to_text (& buf , c , k );
1245
+ prt_str (& buf , "\nnew: " );
1246
+ bch2_bkey_val_to_text (& buf , c , bkey_i_to_s_c (& new -> k_i ));
1247
+ bch2_fs_inconsistent (c , "%s" , buf .buf );
1248
+ printbuf_exit (& buf );
1249
+ ret = - EINVAL ;
1250
+ goto err ;
1251
+ }
1243
1252
1244
- BUG_ON (v &&
1245
- (old -> ptrs [i ].dev != new -> v .ptrs [i ].dev ||
1246
- old -> ptrs [i ].gen != new -> v .ptrs [i ].gen ||
1247
- old -> ptrs [i ].offset != new -> v .ptrs [i ].offset ));
1253
+ /*
1254
+ * If the stripe ptr changed underneath us, it must have
1255
+ * been dev_remove_stripes() -> * invalidate_stripe_to_dev()
1256
+ */
1257
+ if (!bch2_extent_ptr_eq (old -> v .ptrs [i ], v -> ptrs [i ])) {
1258
+ BUG_ON (v -> ptrs [i ].dev != BCH_SB_MEMBER_INVALID );
1259
+
1260
+ if (bch2_extent_ptr_eq (old -> v .ptrs [i ], new -> v .ptrs [i ]))
1261
+ new -> v .ptrs [i ].dev = BCH_SB_MEMBER_INVALID ;
1262
+ }
1248
1263
1249
- stripe_blockcount_set (& new -> v , i , v );
1264
+ stripe_blockcount_set (& new -> v , i , sectors );
1250
1265
}
1251
1266
}
1252
1267
@@ -1508,8 +1523,10 @@ static void ec_stripe_create(struct ec_stripe_new *s)
1508
1523
BCH_TRANS_COMMIT_no_check_rw |
1509
1524
BCH_TRANS_COMMIT_no_enospc ,
1510
1525
ec_stripe_key_update (trans ,
1511
- bkey_i_to_stripe (& s -> new_stripe .key ),
1512
- !s -> have_existing_stripe ));
1526
+ s -> have_existing_stripe
1527
+ ? bkey_i_to_stripe (& s -> existing_stripe .key )
1528
+ : NULL ,
1529
+ bkey_i_to_stripe (& s -> new_stripe .key )));
1513
1530
bch_err_msg (c , ret , "creating stripe key" );
1514
1531
if (ret ) {
1515
1532
goto err ;
0 commit comments