summaryrefslogtreecommitdiff
path: root/libbcachefs/migrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/migrate.c')
-rw-r--r--libbcachefs/migrate.c125
1 files changed, 38 insertions, 87 deletions
diff --git a/libbcachefs/migrate.c b/libbcachefs/migrate.c
index d7f27a3d..8d1c0ee0 100644
--- a/libbcachefs/migrate.c
+++ b/libbcachefs/migrate.c
@@ -13,31 +13,16 @@
#include "move.h"
#include "super-io.h"
-static int issue_migration_move(struct bch_dev *ca,
- struct moving_context *ctxt,
- struct bch_devs_mask *devs,
- struct bkey_s_c k)
+static bool migrate_pred(void *arg, struct bkey_s_c_extent e)
{
- struct bch_fs *c = ca->fs;
- struct disk_reservation res;
+ struct bch_dev *ca = arg;
const struct bch_extent_ptr *ptr;
- int ret;
-
- if (bch2_disk_reservation_get(c, &res, k.k->size, 0))
- return -ENOSPC;
- extent_for_each_ptr(bkey_s_c_to_extent(k), ptr)
+ extent_for_each_ptr(e, ptr)
if (ptr->dev == ca->dev_idx)
- goto found;
+ return true;
- BUG();
-found:
- /* XXX: we need to be doing something with the disk reservation */
-
- ret = bch2_data_move(c, ctxt, devs, k, ptr);
- if (ret)
- bch2_disk_reservation_put(c, &res);
- return ret;
+ return false;
}
#define MAX_DATA_OFF_ITER 10
@@ -58,10 +43,11 @@ found:
int bch2_move_data_off_device(struct bch_dev *ca)
{
- struct moving_context ctxt;
struct bch_fs *c = ca->fs;
+ struct btree_iter iter;
+ struct bkey_s_c k;
+ u64 keys_moved, sectors_moved;
unsigned pass = 0;
- u64 seen_key_count;
int ret = 0;
BUG_ON(ca->mi.state == BCH_MEMBER_STATE_RW);
@@ -69,12 +55,6 @@ int bch2_move_data_off_device(struct bch_dev *ca)
if (!(bch2_dev_has_data(c, ca) & (1 << BCH_DATA_USER)))
return 0;
- mutex_lock(&c->replicas_gc_lock);
- bch2_replicas_gc_start(c, 1 << BCH_DATA_USER);
-
- bch2_move_ctxt_init(&ctxt, NULL, SECTORS_IN_FLIGHT_PER_DEVICE);
- __set_bit(ca->dev_idx, ctxt.avoid.d);
-
/*
* In theory, only one pass should be necessary as we've
* quiesced all writes before calling this.
@@ -91,69 +71,43 @@ int bch2_move_data_off_device(struct bch_dev *ca)
* Thus this scans the tree one more time than strictly necessary,
* but that can be viewed as a verification pass.
*/
-
do {
- struct btree_iter iter;
- struct bkey_s_c k;
-
- seen_key_count = 0;
- atomic_set(&ctxt.error_count, 0);
- atomic_set(&ctxt.error_flags, 0);
-
- bch2_btree_iter_init(&iter, c, BTREE_ID_EXTENTS, POS_MIN,
- BTREE_ITER_PREFETCH);
-
- while (!bch2_move_ctxt_wait(&ctxt) &&
- (k = bch2_btree_iter_peek(&iter)).k &&
- !(ret = btree_iter_err(k))) {
- if (!bkey_extent_is_data(k.k) ||
- !bch2_extent_has_device(bkey_s_c_to_extent(k),
- ca->dev_idx))
- goto next;
-
- ret = issue_migration_move(ca, &ctxt, NULL, k);
- if (ret == -ENOMEM) {
- bch2_btree_iter_unlock(&iter);
-
- /*
- * memory allocation failure, wait for some IO
- * to finish
- */
- bch2_move_ctxt_wait_for_io(&ctxt);
- continue;
- }
- if (ret == -ENOSPC)
- break;
- BUG_ON(ret);
+ ret = bch2_move_data(c, NULL,
+ SECTORS_IN_FLIGHT_PER_DEVICE,
+ NULL,
+ writepoint_hashed((unsigned long) current),
+ 0,
+ ca->dev_idx,
+ migrate_pred, ca,
+ &keys_moved,
+ &sectors_moved);
+ if (ret) {
+ bch_err(c, "error migrating data: %i", ret);
+ return ret;
+ }
+ } while (keys_moved && pass++ < MAX_DATA_OFF_ITER);
- seen_key_count++;
- continue;
-next:
- if (bkey_extent_is_data(k.k)) {
- ret = bch2_check_mark_super(c, bkey_s_c_to_extent(k),
- BCH_DATA_USER);
- if (ret)
- break;
- }
- bch2_btree_iter_advance_pos(&iter);
- bch2_btree_iter_cond_resched(&iter);
+ if (keys_moved) {
+ bch_err(c, "unable to migrate all data in %d iterations",
+ MAX_DATA_OFF_ITER);
+ return -1;
+ }
- }
- bch2_btree_iter_unlock(&iter);
- bch2_move_ctxt_exit(&ctxt);
+ mutex_lock(&c->replicas_gc_lock);
+ bch2_replicas_gc_start(c, 1 << BCH_DATA_USER);
- if (ret)
- goto err;
- } while (seen_key_count && pass++ < MAX_DATA_OFF_ITER);
+ for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS_MIN, BTREE_ITER_PREFETCH, k) {
+ if (!bkey_extent_is_data(k.k))
+ continue;
- if (seen_key_count) {
- pr_err("Unable to migrate all data in %d iterations.",
- MAX_DATA_OFF_ITER);
- ret = -1;
- goto err;
+ ret = bch2_check_mark_super(c, bkey_s_c_to_extent(k),
+ BCH_DATA_USER);
+ if (ret) {
+ bch_err(c, "error migrating data %i from check_mark_super()", ret);
+ break;
+ }
}
-err:
bch2_replicas_gc_end(c, ret);
mutex_unlock(&c->replicas_gc_lock);
return ret;
@@ -167,14 +121,11 @@ static int bch2_move_btree_off(struct bch_fs *c, struct bch_dev *ca,
enum btree_id id)
{
struct btree_iter iter;
- struct closure cl;
struct btree *b;
int ret;
BUG_ON(ca->mi.state == BCH_MEMBER_STATE_RW);
- closure_init_stack(&cl);
-
for_each_btree_node(&iter, c, id, POS_MIN, BTREE_ITER_PREFETCH, b) {
struct bkey_s_c_extent e = bkey_i_to_s_c_extent(&b->key);