@@ -93,21 +93,24 @@ static const struct rhashtable_params bch_promote_params = {
9393static inline int should_promote (struct bch_fs * c , struct bkey_s_c k ,
9494 struct bpos pos ,
9595 struct bch_io_opts opts ,
96- unsigned flags )
96+ unsigned flags ,
97+ struct bch_io_failures * failed )
9798{
98- BUG_ON (!opts .promote_target );
99+ if (!failed ) {
100+ BUG_ON (!opts .promote_target );
99101
100- if (!(flags & BCH_READ_MAY_PROMOTE ))
101- return - BCH_ERR_nopromote_may_not ;
102+ if (!(flags & BCH_READ_MAY_PROMOTE ))
103+ return - BCH_ERR_nopromote_may_not ;
102104
103- if (bch2_bkey_has_target (c , k , opts .promote_target ))
104- return - BCH_ERR_nopromote_already_promoted ;
105+ if (bch2_bkey_has_target (c , k , opts .promote_target ))
106+ return - BCH_ERR_nopromote_already_promoted ;
105107
106- if (bkey_extent_is_unwritten (k ))
107- return - BCH_ERR_nopromote_unwritten ;
108+ if (bkey_extent_is_unwritten (k ))
109+ return - BCH_ERR_nopromote_unwritten ;
108110
109- if (bch2_target_congested (c , opts .promote_target ))
110- return - BCH_ERR_nopromote_congested ;
111+ if (bch2_target_congested (c , opts .promote_target ))
112+ return - BCH_ERR_nopromote_congested ;
113+ }
111114
112115 if (rhashtable_lookup_fast (& c -> promote_table , & pos ,
113116 bch_promote_params ))
@@ -164,7 +167,8 @@ static struct promote_op *__promote_alloc(struct btree_trans *trans,
164167 struct extent_ptr_decoded * pick ,
165168 struct bch_io_opts opts ,
166169 unsigned sectors ,
167- struct bch_read_bio * * rbio )
170+ struct bch_read_bio * * rbio ,
171+ struct bch_io_failures * failed )
168172{
169173 struct bch_fs * c = trans -> c ;
170174 struct promote_op * op = NULL ;
@@ -217,14 +221,28 @@ static struct promote_op *__promote_alloc(struct btree_trans *trans,
217221 bio = & op -> write .op .wbio .bio ;
218222 bio_init (bio , NULL , bio -> bi_inline_vecs , pages , 0 );
219223
224+ struct data_update_opts update_opts = {};
225+
226+ if (!failed ) {
227+ update_opts .target = opts .promote_target ;
228+ update_opts .extra_replicas = 1 ;
229+ update_opts .write_flags = BCH_WRITE_ALLOC_NOWAIT |BCH_WRITE_CACHED ;
230+ } else {
231+ update_opts .target = opts .foreground_target ;
232+
233+ struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c (k );
234+ unsigned i = 0 ;
235+ bkey_for_each_ptr (ptrs , ptr ) {
236+ if (bch2_dev_io_failures (failed , ptr -> dev ))
237+ update_opts .rewrite_ptrs |= BIT (i );
238+ i ++ ;
239+ }
240+ }
241+
220242 ret = bch2_data_update_init (trans , NULL , NULL , & op -> write ,
221243 writepoint_hashed ((unsigned long ) current ),
222244 opts ,
223- (struct data_update_opts ) {
224- .target = opts .promote_target ,
225- .extra_replicas = 1 ,
226- .write_flags = BCH_WRITE_ALLOC_NOWAIT |BCH_WRITE_CACHED ,
227- },
245+ update_opts ,
228246 btree_id , k );
229247 /*
230248 * possible errors: -BCH_ERR_nocow_lock_blocked,
@@ -258,10 +276,17 @@ static struct promote_op *promote_alloc(struct btree_trans *trans,
258276 unsigned flags ,
259277 struct bch_read_bio * * rbio ,
260278 bool * bounce ,
261- bool * read_full )
279+ bool * read_full ,
280+ struct bch_io_failures * failed )
262281{
263282 struct bch_fs * c = trans -> c ;
264- bool promote_full = * read_full || READ_ONCE (c -> promote_whole_extents );
283+ /*
284+ * if failed != NULL we're not actually doing a promote, we're
285+ * recovering from an io/checksum error
286+ */
287+ bool promote_full = (failed ||
288+ * read_full ||
289+ READ_ONCE (c -> promote_whole_extents ));
265290 /* data might have to be decompressed in the write path: */
266291 unsigned sectors = promote_full
267292 ? max (pick -> crc .compressed_size , pick -> crc .live_size )
@@ -272,15 +297,15 @@ static struct promote_op *promote_alloc(struct btree_trans *trans,
272297 struct promote_op * promote ;
273298 int ret ;
274299
275- ret = should_promote (c , k , pos , opts , flags );
300+ ret = should_promote (c , k , pos , opts , flags , failed );
276301 if (ret )
277302 goto nopromote ;
278303
279304 promote = __promote_alloc (trans ,
280305 k .k -> type == KEY_TYPE_reflink_v
281306 ? BTREE_ID_reflink
282307 : BTREE_ID_extents ,
283- k , pos , pick , opts , sectors , rbio );
308+ k , pos , pick , opts , sectors , rbio , failed );
284309 ret = PTR_ERR_OR_ZERO (promote );
285310 if (ret )
286311 goto nopromote ;
@@ -910,9 +935,9 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
910935 bounce = true;
911936 }
912937
913- if (orig -> opts .promote_target )
938+ if (orig -> opts .promote_target )// || failed)
914939 promote = promote_alloc (trans , iter , k , & pick , orig -> opts , flags ,
915- & rbio , & bounce , & read_full );
940+ & rbio , & bounce , & read_full , failed );
916941
917942 if (!read_full ) {
918943 EBUG_ON (crc_is_compressed (pick .crc ));
0 commit comments