X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Fmigrate.c;h=e3a51f6d6c9b25dcae89934eace9e68b038531de;hb=9799b119c34d7be1ee96d143209cfe5fc543d92a;hp=1ef62a189e3319a5425dbc10b59e1de4dd2af2dd;hpb=304691592738dc272f4150107b54a53ab43fc8be;p=bcachefs-tools-debian diff --git a/libbcachefs/migrate.c b/libbcachefs/migrate.c index 1ef62a1..e3a51f6 100644 --- a/libbcachefs/migrate.c +++ b/libbcachefs/migrate.c @@ -4,12 +4,13 @@ */ #include "bcachefs.h" -#include "bkey_on_stack.h" +#include "bkey_buf.h" #include "btree_update.h" #include "btree_update_interior.h" #include "buckets.h" +#include "errcode.h" #include "extents.h" -#include "io.h" +#include "io_write.h" #include "journal.h" #include "keylist.h" #include "migrate.h" @@ -35,80 +36,78 @@ static int drop_dev_ptrs(struct bch_fs *c, struct bkey_s k, return 0; } -static int __bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags, - enum btree_id btree_id) +static int bch2_dev_usrdata_drop_key(struct btree_trans *trans, + struct btree_iter *iter, + struct bkey_s_c k, + unsigned dev_idx, + int flags) { - struct btree_trans trans; - struct btree_iter *iter; - struct bkey_s_c k; - struct bkey_on_stack sk; - int ret = 0; + struct bch_fs *c = trans->c; + struct bkey_i *n; + int ret; - bkey_on_stack_init(&sk); - bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); + if (!bch2_bkey_has_device_c(k, dev_idx)) + return 0; + + n = bch2_bkey_make_mut(trans, iter, &k, BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE); + ret = PTR_ERR_OR_ZERO(n); + if (ret) + return ret; + + ret = drop_dev_ptrs(c, bkey_i_to_s(n), dev_idx, flags, false); + if (ret) + return ret; + + /* + * If the new extent no longer has any pointers, bch2_extent_normalize() + * will do the appropriate thing with it (turning it into a + * KEY_TYPE_error key, or just a discard if it was a cached extent) + */ + bch2_extent_normalize(c, bkey_i_to_s(n)); + + /* + * Since we're not inserting through an extent iterator + * (BTREE_ITER_ALL_SNAPSHOTS iterators aren't extent iterators), + * we aren't using the extent overwrite path to delete, we're + * just using the normal key deletion path: + */ + if (bkey_deleted(&n->k)) + n->k.size = 0; + return 0; +} - iter = bch2_trans_get_iter(&trans, btree_id, POS_MIN, - BTREE_ITER_PREFETCH); +static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags) +{ + struct btree_trans *trans = bch2_trans_get(c); + struct btree_iter iter; + struct bkey_s_c k; + enum btree_id id; + int ret = 0; - while ((k = bch2_btree_iter_peek(iter)).k && - !(ret = bkey_err(k))) { - if (!bch2_bkey_has_device(k, dev_idx)) { - bch2_btree_iter_next(iter); + for (id = 0; id < BTREE_ID_NR; id++) { + if (!btree_type_has_ptrs(id)) continue; - } - - bkey_on_stack_reassemble(&sk, c, k); - ret = drop_dev_ptrs(c, bkey_i_to_s(sk.k), - dev_idx, flags, false); - if (ret) - break; - - /* - * If the new extent no longer has any pointers, bch2_extent_normalize() - * will do the appropriate thing with it (turning it into a - * KEY_TYPE_error key, or just a discard if it was a cached extent) - */ - bch2_extent_normalize(c, bkey_i_to_s(sk.k)); - - bch2_btree_iter_set_pos(iter, bkey_start_pos(&sk.k->k)); - - bch2_trans_update(&trans, iter, sk.k, 0); - - ret = bch2_trans_commit(&trans, NULL, NULL, - BTREE_INSERT_NOFAIL); - - /* - * don't want to leave ret == -EINTR, since if we raced and - * something else overwrote the key we could spuriously return - * -EINTR below: - */ - if (ret == -EINTR) - ret = 0; + ret = for_each_btree_key_commit(trans, iter, id, POS_MIN, + BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, + NULL, NULL, BTREE_INSERT_NOFAIL, + bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags)); if (ret) break; } - ret = bch2_trans_exit(&trans) ?: ret; - bkey_on_stack_exit(&sk, c); - - BUG_ON(ret == -EINTR); + bch2_trans_put(trans); return ret; } -static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags) -{ - return __bch2_dev_usrdata_drop(c, dev_idx, flags, BTREE_ID_EXTENTS) ?: - __bch2_dev_usrdata_drop(c, dev_idx, flags, BTREE_ID_REFLINK); -} - static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) { - struct btree_trans trans; - struct btree_iter *iter; + struct btree_trans *trans; + struct btree_iter iter; struct closure cl; struct btree *b; + struct bkey_buf k; unsigned id; int ret; @@ -116,58 +115,59 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) if (flags & BCH_FORCE_IF_METADATA_LOST) return -EINVAL; - bch2_trans_init(&trans, c, 0, 0); + trans = bch2_trans_get(c); + bch2_bkey_buf_init(&k); closure_init_stack(&cl); for (id = 0; id < BTREE_ID_NR; id++) { - for_each_btree_node(&trans, iter, id, POS_MIN, - BTREE_ITER_PREFETCH, b) { - __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX) tmp; - struct bkey_i_btree_ptr *new_key; + bch2_trans_node_iter_init(trans, &iter, id, POS_MIN, 0, 0, + BTREE_ITER_PREFETCH); retry: - if (!bch2_bkey_has_device(bkey_i_to_s_c(&b->key), - dev_idx)) - continue; + ret = 0; + while (bch2_trans_begin(trans), + (b = bch2_btree_iter_peek_node(&iter)) && + !(ret = PTR_ERR_OR_ZERO(b))) { + if (!bch2_bkey_has_device_c(bkey_i_to_s_c(&b->key), dev_idx)) + goto next; - bkey_copy(&tmp.k, &b->key); - new_key = bkey_i_to_btree_ptr(&tmp.k); + bch2_bkey_buf_copy(&k, c, &b->key); - ret = drop_dev_ptrs(c, bkey_i_to_s(&new_key->k_i), + ret = drop_dev_ptrs(c, bkey_i_to_s(k.k), dev_idx, flags, true); if (ret) { bch_err(c, "Cannot drop device without losing data"); - goto err; + break; } - ret = bch2_btree_node_update_key(c, iter, b, new_key); - if (ret == -EINTR) { - b = bch2_btree_iter_peek_node(iter); - goto retry; + ret = bch2_btree_node_update_key(trans, &iter, b, k.k, 0, false); + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) { + ret = 0; + continue; } + if (ret) { - bch_err(c, "Error updating btree node key: %i", ret); - goto err; + bch_err_msg(c, ret, "updating btree node key"); + break; } +next: + bch2_btree_iter_next_node(&iter); } - bch2_trans_iter_free(&trans, iter); - } + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) + goto retry; - /* flush relevant btree updates */ - while (1) { - closure_wait_event(&c->btree_interior_update_wait, - !bch2_btree_interior_updates_nr_pending(c) || - c->btree_roots_dirty); - if (c->btree_roots_dirty) - bch2_journal_meta(&c->journal); - if (!bch2_btree_interior_updates_nr_pending(c)) - break; + bch2_trans_iter_exit(trans, &iter); + + if (ret) + goto err; } + bch2_btree_interior_updates_flush(c); ret = 0; err: - ret = bch2_trans_exit(&trans) ?: ret; + bch2_bkey_buf_exit(&k, c); + bch2_trans_put(trans); - BUG_ON(ret == -EINTR); + BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart)); return ret; }