diff options
Diffstat (limited to 'libbcachefs/move.c')
-rw-r--r-- | libbcachefs/move.c | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/libbcachefs/move.c b/libbcachefs/move.c index 1d11cf0d..700f847c 100644 --- a/libbcachefs/move.c +++ b/libbcachefs/move.c @@ -261,6 +261,12 @@ static int bch2_move_extent(struct btree_trans *trans, if (!percpu_ref_tryget_live(&c->writes)) return -EROFS; + /* + * Before memory allocations & taking nocow locks in + * bch2_data_update_init(): + */ + bch2_trans_unlock(trans); + /* write path might have to decompress data: */ bkey_for_each_ptr_decode(k.k, ptrs, p, entry) sectors = max_t(unsigned, sectors, p.crc.uncompressed_size); @@ -296,7 +302,7 @@ static int bch2_move_extent(struct btree_trans *trans, ret = bch2_data_update_init(c, &io->write, ctxt->wp, io_opts, data_opts, btree_id, k); - if (ret) + if (ret && ret != -BCH_ERR_unwritten_extent_update) goto err_free_pages; io->write.ctxt = ctxt; @@ -304,6 +310,15 @@ static int bch2_move_extent(struct btree_trans *trans, atomic64_inc(&ctxt->stats->keys_moved); atomic64_add(k.k->size, &ctxt->stats->sectors_moved); + + if (ret == -BCH_ERR_unwritten_extent_update) { + bch2_update_unwritten_extent(trans, &io->write); + move_free(io); + return 0; + } + + BUG_ON(ret); + this_cpu_add(c->counters[BCH_COUNTER_io_move], k.k->size); this_cpu_add(c->counters[BCH_COUNTER_move_extent_read], k.k->size); trace_move_extent_read(k.k); @@ -499,6 +514,7 @@ static int __bch2_move_data(struct moving_context *ctxt, */ bch2_bkey_buf_reassemble(&sk, c, k); k = bkey_i_to_s_c(sk.k); + bch2_trans_unlock(&trans); ret2 = bch2_move_extent(&trans, &iter, ctxt, io_opts, btree_id, k, data_opts); @@ -573,6 +589,9 @@ static int verify_bucket_evacuated(struct btree_trans *trans, struct bpos bucket struct bch_fs *c = trans->c; struct btree_iter iter; struct bkey_s_c k; + struct printbuf buf = PRINTBUF; + struct bch_backpointer bp; + u64 bp_offset = 0; int ret; bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, @@ -586,24 +605,53 @@ again: if (a.v->gen == gen && a.v->dirty_sectors) { - struct printbuf buf = PRINTBUF; - if (a.v->data_type == BCH_DATA_btree) { bch2_trans_unlock(trans); if (bch2_btree_interior_updates_flush(c)) goto again; + goto failed_to_evacuate; } - - prt_str(&buf, "failed to evacuate bucket "); - bch2_bkey_val_to_text(&buf, c, k); - - bch_err(c, "%s", buf.buf); - printbuf_exit(&buf); } } bch2_trans_iter_exit(trans, &iter); return ret; +failed_to_evacuate: + bch2_trans_iter_exit(trans, &iter); + + prt_printf(&buf, bch2_log_msg(c, "failed to evacuate bucket ")); + bch2_bkey_val_to_text(&buf, c, k); + + while (1) { + bch2_trans_begin(trans); + + ret = bch2_get_next_backpointer(trans, bucket, gen, + &bp_offset, &bp, + BTREE_ITER_CACHED); + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) + continue; + if (ret) + break; + if (bp_offset == U64_MAX) + break; + + k = bch2_backpointer_get_key(trans, &iter, + bucket, bp_offset, bp); + ret = bkey_err(k); + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) + continue; + if (ret) + break; + if (!k.k) + continue; + prt_newline(&buf); + bch2_bkey_val_to_text(&buf, c, k); + bch2_trans_iter_exit(trans, &iter); + } + + bch2_print_string_as_lines(KERN_ERR, buf.buf); + printbuf_exit(&buf); + return 0; } int __bch2_evacuate_bucket(struct moving_context *ctxt, |