X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libbcachefs%2Fmigrate.c;h=8e5688d0a8ca6af79b9b98c11efdef88c67645e1;hb=8d8a9f3e9bdd1d84fbbe0531e81977cc9044654a;hp=ef69a19f494a1583d609a04632da248f599515e4;hpb=209695dedf49425ad9e91ba2b2239c3a040ea159;p=bcachefs-tools-debian diff --git a/libbcachefs/migrate.c b/libbcachefs/migrate.c index ef69a19..8e5688d 100644 --- a/libbcachefs/migrate.c +++ b/libbcachefs/migrate.c @@ -8,8 +8,9 @@ #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,79 +36,75 @@ 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_buf sk; - int ret = 0; + struct bch_fs *c = trans->c; + struct bkey_i *n; + int ret; - bch2_bkey_buf_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_advance(iter); + for (id = 0; id < BTREE_ID_NR; id++) { + if (!btree_type_has_ptrs(id)) continue; - } - - bch2_bkey_buf_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, BCH_TRANS_COMMIT_no_enospc, + bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags)); if (ret) break; } - bch2_trans_iter_put(&trans, iter); - ret = bch2_trans_exit(&trans) ?: ret; - bch2_bkey_buf_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; @@ -118,17 +115,20 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) if (flags & BCH_FORCE_IF_METADATA_LOST) return -EINVAL; + trans = bch2_trans_get(c); bch2_bkey_buf_init(&k); - bch2_trans_init(&trans, c, 0, 0); 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) { + 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; bch2_bkey_buf_copy(&k, c, &b->key); @@ -139,33 +139,35 @@ retry: break; } - ret = bch2_btree_node_update_key(c, iter, b, k.k); - if (ret == -EINTR) { - b = bch2_btree_iter_peek_node(iter); + ret = bch2_btree_node_update_key(trans, &iter, b, k.k, 0, false); + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) { ret = 0; - goto retry; + continue; } + if (ret) { - bch_err(c, "Error updating btree node key: %i", ret); + 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; + + bch2_trans_iter_exit(trans, &iter); if (ret) goto err; } - /* flush relevant btree updates */ - closure_wait_event(&c->btree_interior_update_wait, - !bch2_btree_interior_updates_nr_pending(c)); - + 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; }