move.c 27.1 KB
Newer Older
Kent Overstreet's avatar
Kent Overstreet committed
1 2 3
// SPDX-License-Identifier: GPL-2.0

#include "bcachefs.h"
4
#include "alloc_foreground.h"
5
#include "bkey_buf.h"
Kent Overstreet's avatar
Kent Overstreet committed
6 7
#include "btree_gc.h"
#include "btree_update.h"
8
#include "btree_update_interior.h"
Kent Overstreet's avatar
Kent Overstreet committed
9
#include "buckets.h"
10
#include "disk_groups.h"
11
#include "ec.h"
Kent Overstreet's avatar
Kent Overstreet committed
12 13 14 15 16 17
#include "inode.h"
#include "io.h"
#include "journal_reclaim.h"
#include "keylist.h"
#include "move.h"
#include "replicas.h"
18
#include "subvolume.h"
Kent Overstreet's avatar
Kent Overstreet committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include "super-io.h"
#include "trace.h"

#include <linux/ioprio.h>
#include <linux/kthread.h>

#define SECTORS_IN_FLIGHT_PER_DEVICE	2048

struct moving_io {
	struct list_head	list;
	struct closure		cl;
	bool			read_completed;

	unsigned		read_sectors;
	unsigned		write_sectors;

	struct bch_read_bio	rbio;

	struct migrate_write	write;
	/* Must be last since it is variable size */
	struct bio_vec		bi_inline_vecs[0];
};

struct moving_context {
	/* Closure for waiting on all reads and writes to complete */
	struct closure		cl;

	struct bch_move_stats	*stats;

	struct list_head	reads;

	/* in flight sectors: */
	atomic_t		read_sectors;
	atomic_t		write_sectors;

	wait_queue_head_t	wait;
};

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
static int insert_snapshot_whiteouts(struct btree_trans *trans,
				     enum btree_id id,
				     struct bpos old_pos,
				     struct bpos new_pos)
{
	struct bch_fs *c = trans->c;
	struct btree_iter iter, update_iter;
	struct bkey_s_c k;
	struct snapshots_seen s;
	int ret;

	if (!btree_type_has_snapshots(id))
		return 0;

	snapshots_seen_init(&s);

	if (!bkey_cmp(old_pos, new_pos))
		return 0;

	if (!snapshot_t(c, old_pos.snapshot)->children[0])
		return 0;

	bch2_trans_iter_init(trans, &iter, id, old_pos,
			     BTREE_ITER_NOT_EXTENTS|
			     BTREE_ITER_ALL_SNAPSHOTS);
	while (1) {
next:
		k = bch2_btree_iter_prev(&iter);
		ret = bkey_err(k);
		if (ret)
			break;

		if (bkey_cmp(old_pos, k.k->p))
			break;

		if (bch2_snapshot_is_ancestor(c, k.k->p.snapshot, old_pos.snapshot)) {
			struct bkey_i *update;
Kent Overstreet's avatar
Kent Overstreet committed
94
			u32 *i;
95

Kent Overstreet's avatar
Kent Overstreet committed
96 97
			darray_for_each(s.ids, i)
				if (bch2_snapshot_is_ancestor(c, k.k->p.snapshot, *i))
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
					goto next;

			update = bch2_trans_kmalloc(trans, sizeof(struct bkey_i));

			ret = PTR_ERR_OR_ZERO(update);
			if (ret)
				break;

			bkey_init(&update->k);
			update->k.p = new_pos;
			update->k.p.snapshot = k.k->p.snapshot;

			bch2_trans_iter_init(trans, &update_iter, id, update->k.p,
					     BTREE_ITER_NOT_EXTENTS|
					     BTREE_ITER_ALL_SNAPSHOTS|
					     BTREE_ITER_INTENT);
			ret   = bch2_btree_iter_traverse(&update_iter) ?:
				bch2_trans_update(trans, &update_iter, update,
					  BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
			bch2_trans_iter_exit(trans, &update_iter);
			if (ret)
				break;

			ret = snapshots_seen_add(c, &s, k.k->p.snapshot);
			if (ret)
				break;
		}
	}
	bch2_trans_iter_exit(trans, &iter);
Kent Overstreet's avatar
Kent Overstreet committed
127
	darray_exit(&s.ids);
128 129 130 131

	return ret;
}

132
int bch2_migrate_index_update(struct bch_write_op *op)
Kent Overstreet's avatar
Kent Overstreet committed
133 134
{
	struct bch_fs *c = op->c;
135
	struct btree_trans trans;
Kent Overstreet's avatar
Kent Overstreet committed
136
	struct btree_iter iter;
Kent Overstreet's avatar
Kent Overstreet committed
137 138
	struct migrate_write *m =
		container_of(op, struct migrate_write, op);
139
	struct open_bucket *ec_ob = ec_open_bucket(c, &op->open_buckets);
Kent Overstreet's avatar
Kent Overstreet committed
140
	struct keylist *keys = &op->insert_keys;
141
	struct bkey_buf _new, _insert;
Kent Overstreet's avatar
Kent Overstreet committed
142 143
	int ret = 0;

144 145 146 147
	bch2_bkey_buf_init(&_new);
	bch2_bkey_buf_init(&_insert);
	bch2_bkey_buf_realloc(&_insert, c, U8_MAX);

148
	bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);
149

Kent Overstreet's avatar
Kent Overstreet committed
150 151 152
	bch2_trans_iter_init(&trans, &iter, m->btree_id,
			     bkey_start_pos(&bch2_keylist_front(keys)->k),
			     BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
Kent Overstreet's avatar
Kent Overstreet committed
153 154

	while (1) {
155
		struct bkey_s_c k;
Kent Overstreet's avatar
Kent Overstreet committed
156
		struct bkey_i *insert;
157
		struct bkey_i_extent *new;
158 159
		const union bch_extent_entry *entry;
		struct extent_ptr_decoded p;
160
		struct bpos next_pos;
Kent Overstreet's avatar
Kent Overstreet committed
161
		bool did_work = false;
162 163
		bool extending = false, should_check_enospc;
		s64 i_sectors_delta = 0, disk_sectors_delta = 0;
Kent Overstreet's avatar
Kent Overstreet committed
164

165
		bch2_trans_begin(&trans);
166

Kent Overstreet's avatar
Kent Overstreet committed
167
		k = bch2_btree_iter_peek_slot(&iter);
168
		ret = bkey_err(k);
169 170
		if (ret)
			goto err;
171 172

		new = bkey_i_to_extent(bch2_keylist_front(keys));
Kent Overstreet's avatar
Kent Overstreet committed
173 174

		if (bversion_cmp(k.k->version, new->k.version) ||
175
		    !bch2_bkey_matches_ptr(c, k, m->ptr, m->offset))
Kent Overstreet's avatar
Kent Overstreet committed
176 177
			goto nomatch;

178 179
		bkey_reassemble(_insert.k, k);
		insert = _insert.k;
Kent Overstreet's avatar
Kent Overstreet committed
180

181 182
		bch2_bkey_buf_copy(&_new, c, bch2_keylist_front(keys));
		new = bkey_i_to_extent(_new.k);
Kent Overstreet's avatar
Kent Overstreet committed
183
		bch2_cut_front(iter.pos, &new->k_i);
Kent Overstreet's avatar
Kent Overstreet committed
184

Kent Overstreet's avatar
Kent Overstreet committed
185
		bch2_cut_front(iter.pos,	insert);
186 187
		bch2_cut_back(new->k.p,		insert);
		bch2_cut_back(insert->k.p,	&new->k_i);
Kent Overstreet's avatar
Kent Overstreet committed
188

189 190 191 192 193 194 195 196 197 198 199
		if (m->data_cmd == DATA_REWRITE) {
			struct bch_extent_ptr *new_ptr, *old_ptr = (void *)
				bch2_bkey_has_device(bkey_i_to_s_c(insert),
						     m->data_opts.rewrite_dev);
			if (!old_ptr)
				goto nomatch;

			if (old_ptr->cached)
				extent_for_each_ptr(extent_i_to_s(new), new_ptr)
					new_ptr->cached = true;

200
			__bch2_bkey_drop_ptr(bkey_i_to_s(insert), old_ptr);
201
		}
Kent Overstreet's avatar
Kent Overstreet committed
202

203
		extent_for_each_ptr_decode(extent_i_to_s(new), p, entry) {
Kent Overstreet's avatar
Kent Overstreet committed
204
			if (bch2_bkey_has_device(bkey_i_to_s_c(insert), p.ptr.dev)) {
Kent Overstreet's avatar
Kent Overstreet committed
205 206 207 208 209 210 211 212
				/*
				 * raced with another move op? extent already
				 * has a pointer to the device we just wrote
				 * data to
				 */
				continue;
			}

Kent Overstreet's avatar
Kent Overstreet committed
213
			bch2_extent_ptr_decoded_append(insert, &p);
Kent Overstreet's avatar
Kent Overstreet committed
214 215 216 217 218 219
			did_work = true;
		}

		if (!did_work)
			goto nomatch;

Kent Overstreet's avatar
Kent Overstreet committed
220
		bch2_bkey_narrow_crcs(insert,
Kent Overstreet's avatar
Kent Overstreet committed
221
				(struct bch_extent_crc_unpacked) { 0 });
Kent Overstreet's avatar
Kent Overstreet committed
222 223 224 225
		bch2_extent_normalize(c, bkey_i_to_s(insert));
		bch2_bkey_mark_replicas_cached(c, bkey_i_to_s(insert),
					       op->opts.background_target,
					       op->opts.data_replicas);
Kent Overstreet's avatar
Kent Overstreet committed
226

Kent Overstreet's avatar
Kent Overstreet committed
227
		ret = bch2_sum_sector_overwrites(&trans, &iter, insert,
228 229 230 231 232 233
						 &extending,
						 &should_check_enospc,
						 &i_sectors_delta,
						 &disk_sectors_delta);
		if (ret)
			goto err;
234

235
		if (disk_sectors_delta > (s64) op->res.sectors) {
Kent Overstreet's avatar
Kent Overstreet committed
236
			ret = bch2_disk_reservation_add(c, &op->res,
237 238 239
						disk_sectors_delta - op->res.sectors,
						!should_check_enospc
						? BCH_DISK_RESERVATION_NOFAIL : 0);
Kent Overstreet's avatar
Kent Overstreet committed
240 241 242 243
			if (ret)
				goto out;
		}

244 245
		next_pos = insert->k.p;

246 247 248 249
		ret   = insert_snapshot_whiteouts(&trans, m->btree_id,
						  k.k->p, insert->k.p) ?:
			bch2_trans_update(&trans, &iter, insert,
				BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?:
250
			bch2_trans_commit(&trans, &op->res,
251
				op_journal_seq(op),
Kent Overstreet's avatar
Kent Overstreet committed
252
				BTREE_INSERT_NOFAIL|
253
				m->data_opts.btree_insert_flags);
254
		if (!ret) {
Kent Overstreet's avatar
Kent Overstreet committed
255
			bch2_btree_iter_set_pos(&iter, next_pos);
Kent Overstreet's avatar
Kent Overstreet committed
256
			atomic_long_inc(&c->extent_migrate_done);
257 258
			if (ec_ob)
				bch2_ob_add_backpointer(c, ec_ob, &insert->k);
259 260
		}
err:
Kent Overstreet's avatar
Kent Overstreet committed
261 262 263 264 265
		if (ret == -EINTR)
			ret = 0;
		if (ret)
			break;
next:
Kent Overstreet's avatar
Kent Overstreet committed
266
		while (bkey_cmp(iter.pos, bch2_keylist_front(keys)->k.p) >= 0) {
Kent Overstreet's avatar
Kent Overstreet committed
267 268 269 270 271 272
			bch2_keylist_pop_front(keys);
			if (bch2_keylist_empty(keys))
				goto out;
		}
		continue;
nomatch:
273
		if (m->ctxt) {
Kent Overstreet's avatar
Kent Overstreet committed
274
			BUG_ON(k.k->p.offset <= iter.pos.offset);
275
			atomic64_inc(&m->ctxt->stats->keys_raced);
Kent Overstreet's avatar
Kent Overstreet committed
276
			atomic64_add(k.k->p.offset - iter.pos.offset,
Kent Overstreet's avatar
Kent Overstreet committed
277
				     &m->ctxt->stats->sectors_raced);
278
		}
Kent Overstreet's avatar
Kent Overstreet committed
279 280
		atomic_long_inc(&c->extent_migrate_raced);
		trace_move_race(&new->k);
Kent Overstreet's avatar
Kent Overstreet committed
281
		bch2_btree_iter_advance(&iter);
Kent Overstreet's avatar
Kent Overstreet committed
282 283 284
		goto next;
	}
out:
Kent Overstreet's avatar
Kent Overstreet committed
285
	bch2_trans_iter_exit(&trans, &iter);
286
	bch2_trans_exit(&trans);
287 288
	bch2_bkey_buf_exit(&_insert, c);
	bch2_bkey_buf_exit(&_new, c);
289
	BUG_ON(ret == -EINTR);
Kent Overstreet's avatar
Kent Overstreet committed
290 291 292 293 294 295 296 297 298
	return ret;
}

void bch2_migrate_read_done(struct migrate_write *m, struct bch_read_bio *rbio)
{
	/* write bio must own pages: */
	BUG_ON(!m->op.wbio.bio.bi_vcnt);

	m->ptr		= rbio->pick.ptr;
299
	m->offset	= rbio->data_pos.offset - rbio->pick.crc.offset;
Kent Overstreet's avatar
Kent Overstreet committed
300
	m->op.devs_have	= rbio->devs_have;
301
	m->op.pos	= rbio->data_pos;
Kent Overstreet's avatar
Kent Overstreet committed
302 303 304 305 306 307 308 309 310 311 312 313 314
	m->op.version	= rbio->version;
	m->op.crc	= rbio->pick.crc;
	m->op.wbio.bio.bi_iter.bi_size = m->op.crc.compressed_size << 9;

	if (m->data_cmd == DATA_REWRITE)
		bch2_dev_list_drop_dev(&m->op.devs_have, m->data_opts.rewrite_dev);
}

int bch2_migrate_write_init(struct bch_fs *c, struct migrate_write *m,
			    struct write_point_specifier wp,
			    struct bch_io_opts io_opts,
			    enum data_cmd data_cmd,
			    struct data_opts data_opts,
Kent Overstreet's avatar
Kent Overstreet committed
315
			    enum btree_id btree_id,
Kent Overstreet's avatar
Kent Overstreet committed
316 317
			    struct bkey_s_c k)
{
318 319
	struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
	const union bch_extent_entry *entry;
320
	struct bch_extent_crc_unpacked crc;
321
	struct extent_ptr_decoded p;
Kent Overstreet's avatar
Kent Overstreet committed
322 323
	int ret;

Kent Overstreet's avatar
Kent Overstreet committed
324
	m->btree_id	= btree_id;
Kent Overstreet's avatar
Kent Overstreet committed
325 326 327 328 329
	m->data_cmd	= data_cmd;
	m->data_opts	= data_opts;
	m->nr_ptrs_reserved = 0;

	bch2_write_op_init(&m->op, c, io_opts);
330 331 332 333 334 335 336 337

	if (!bch2_bkey_is_incompressible(k))
		m->op.compression_type =
			bch2_compression_opt_to_type[io_opts.background_compression ?:
						     io_opts.compression];
	else
		m->op.incompressible = true;

Kent Overstreet's avatar
Kent Overstreet committed
338 339 340
	m->op.target	= data_opts.target,
	m->op.write_point = wp;

341 342 343 344 345 346 347 348 349 350 351 352
	/*
	 * op->csum_type is normally initialized from the fs/file's current
	 * options - but if an extent is encrypted, we require that it stays
	 * encrypted:
	 */
	bkey_for_each_crc(k.k, ptrs, crc, entry)
		if (bch2_csum_type_is_encryption(crc.csum_type)) {
			m->op.nonce	= crc.nonce + crc.offset;
			m->op.csum_type = crc.csum_type;
			break;
		}

353
	if (m->data_opts.btree_insert_flags & BTREE_INSERT_USE_RESERVE) {
354
		m->op.alloc_reserve = RESERVE_movinggc;
355 356 357 358
	} else {
		/* XXX: this should probably be passed in */
		m->op.flags |= BCH_WRITE_ONLY_SPECIFIED_DEVS;
	}
Kent Overstreet's avatar
Kent Overstreet committed
359

360
	m->op.flags |= BCH_WRITE_PAGES_STABLE|
Kent Overstreet's avatar
Kent Overstreet committed
361
		BCH_WRITE_PAGES_OWNED|
362
		BCH_WRITE_DATA_ENCODED|
363 364
		BCH_WRITE_FROM_INTERNAL|
		BCH_WRITE_MOVE;
Kent Overstreet's avatar
Kent Overstreet committed
365

366 367
	m->op.nr_replicas	= data_opts.nr_replicas;
	m->op.nr_replicas_required = data_opts.nr_replicas;
Kent Overstreet's avatar
Kent Overstreet committed
368 369 370

	switch (data_cmd) {
	case DATA_ADD_REPLICAS: {
371 372 373 374 375 376
		/*
		 * DATA_ADD_REPLICAS is used for moving data to a different
		 * device in the background, and due to compression the new copy
		 * might take up more space than the old copy:
		 */
#if 0
Kent Overstreet's avatar
Kent Overstreet committed
377
		int nr = (int) io_opts.data_replicas -
378
			bch2_bkey_nr_ptrs_allocated(k);
379 380
#endif
		int nr = (int) io_opts.data_replicas;
Kent Overstreet's avatar
Kent Overstreet committed
381 382 383 384 385 386 387 388 389 390 391

		if (nr > 0) {
			m->op.nr_replicas = m->nr_ptrs_reserved = nr;

			ret = bch2_disk_reservation_get(c, &m->op.res,
					k.k->size, m->op.nr_replicas, 0);
			if (ret)
				return ret;
		}
		break;
	}
392 393 394
	case DATA_REWRITE: {
		unsigned compressed_sectors = 0;

Kent Overstreet's avatar
Kent Overstreet committed
395
		bkey_for_each_ptr_decode(k.k, ptrs, p, entry)
396 397 398 399 400 401 402 403
			if (p.ptr.dev == data_opts.rewrite_dev) {
				if (p.ptr.cached)
					m->op.flags |= BCH_WRITE_CACHED;

				if (!p.ptr.cached &&
				    crc_is_compressed(p.crc))
					compressed_sectors += p.crc.compressed_size;
			}
404 405 406

		if (compressed_sectors) {
			ret = bch2_disk_reservation_add(c, &m->op.res,
407
					k.k->size * m->op.nr_replicas,
408 409 410 411
					BCH_DISK_RESERVATION_NOFAIL);
			if (ret)
				return ret;
		}
Kent Overstreet's avatar
Kent Overstreet committed
412
		break;
413
	}
Kent Overstreet's avatar
Kent Overstreet committed
414 415 416 417 418 419 420 421 422 423 424
	case DATA_PROMOTE:
		m->op.flags	|= BCH_WRITE_ALLOC_NOWAIT;
		m->op.flags	|= BCH_WRITE_CACHED;
		break;
	default:
		BUG();
	}

	return 0;
}

425
static void move_free(struct moving_io *io)
Kent Overstreet's avatar
Kent Overstreet committed
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
{
	struct moving_context *ctxt = io->write.ctxt;
	struct bvec_iter_all iter;
	struct bio_vec *bv;

	bch2_disk_reservation_put(io->write.op.c, &io->write.op.res);

	bio_for_each_segment_all(bv, &io->write.op.wbio.bio, iter)
		if (bv->bv_page)
			__free_page(bv->bv_page);

	wake_up(&ctxt->wait);

	kfree(io);
}

442
static void move_write_done(struct bch_write_op *op)
Kent Overstreet's avatar
Kent Overstreet committed
443
{
444 445
	struct moving_io *io = container_of(op, struct moving_io, write.op);
	struct moving_context *ctxt = io->write.ctxt;
Kent Overstreet's avatar
Kent Overstreet committed
446 447

	atomic_sub(io->write_sectors, &io->write.ctxt->write_sectors);
448 449
	move_free(io);
	closure_put(&ctxt->cl);
Kent Overstreet's avatar
Kent Overstreet committed
450 451
}

452
static void move_write(struct moving_io *io)
Kent Overstreet's avatar
Kent Overstreet committed
453 454
{
	if (unlikely(io->rbio.bio.bi_status || io->rbio.hole)) {
455
		move_free(io);
Kent Overstreet's avatar
Kent Overstreet committed
456 457 458
		return;
	}

459
	closure_get(&io->write.ctxt->cl);
Kent Overstreet's avatar
Kent Overstreet committed
460
	atomic_add(io->write_sectors, &io->write.ctxt->write_sectors);
461 462 463

	bch2_migrate_read_done(&io->write, &io->rbio);
	closure_call(&io->write.op.cl, bch2_write, NULL, NULL);
Kent Overstreet's avatar
Kent Overstreet committed
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
}

static inline struct moving_io *next_pending_write(struct moving_context *ctxt)
{
	struct moving_io *io =
		list_first_entry_or_null(&ctxt->reads, struct moving_io, list);

	return io && io->read_completed ? io : NULL;
}

static void move_read_endio(struct bio *bio)
{
	struct moving_io *io = container_of(bio, struct moving_io, rbio.bio);
	struct moving_context *ctxt = io->write.ctxt;

	atomic_sub(io->read_sectors, &ctxt->read_sectors);
	io->read_completed = true;

482
	wake_up(&ctxt->wait);
Kent Overstreet's avatar
Kent Overstreet committed
483 484 485
	closure_put(&ctxt->cl);
}

486
static void do_pending_writes(struct moving_context *ctxt, struct btree_trans *trans)
Kent Overstreet's avatar
Kent Overstreet committed
487 488 489
{
	struct moving_io *io;

490 491 492
	if (trans)
		bch2_trans_unlock(trans);

Kent Overstreet's avatar
Kent Overstreet committed
493 494
	while ((io = next_pending_write(ctxt))) {
		list_del(&io->list);
495
		move_write(io);
Kent Overstreet's avatar
Kent Overstreet committed
496 497 498
	}
}

499
#define move_ctxt_wait_event(_ctxt, _trans, _cond)		\
Kent Overstreet's avatar
Kent Overstreet committed
500
do {								\
501
	do_pending_writes(_ctxt, _trans);			\
Kent Overstreet's avatar
Kent Overstreet committed
502 503 504 505 506 507 508
								\
	if (_cond)						\
		break;						\
	__wait_event((_ctxt)->wait,				\
		     next_pending_write(_ctxt) || (_cond));	\
} while (1)

509 510
static void bch2_move_ctxt_wait_for_io(struct moving_context *ctxt,
				       struct btree_trans *trans)
Kent Overstreet's avatar
Kent Overstreet committed
511 512 513
{
	unsigned sectors_pending = atomic_read(&ctxt->write_sectors);

514
	move_ctxt_wait_event(ctxt, trans,
Kent Overstreet's avatar
Kent Overstreet committed
515 516 517 518
		!atomic_read(&ctxt->write_sectors) ||
		atomic_read(&ctxt->write_sectors) != sectors_pending);
}

519
static int bch2_move_extent(struct btree_trans *trans,
Kent Overstreet's avatar
Kent Overstreet committed
520 521 522
			    struct moving_context *ctxt,
			    struct write_point_specifier wp,
			    struct bch_io_opts io_opts,
Kent Overstreet's avatar
Kent Overstreet committed
523
			    enum btree_id btree_id,
524
			    struct bkey_s_c k,
Kent Overstreet's avatar
Kent Overstreet committed
525 526 527
			    enum data_cmd data_cmd,
			    struct data_opts data_opts)
{
528
	struct bch_fs *c = trans->c;
529
	struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
Kent Overstreet's avatar
Kent Overstreet committed
530
	struct moving_io *io;
531 532
	const union bch_extent_entry *entry;
	struct extent_ptr_decoded p;
533
	unsigned sectors = k.k->size, pages;
Kent Overstreet's avatar
Kent Overstreet committed
534 535 536
	int ret = -ENOMEM;

	/* write path might have to decompress data: */
537
	bkey_for_each_ptr_decode(k.k, ptrs, p, entry)
538
		sectors = max_t(unsigned, sectors, p.crc.uncompressed_size);
Kent Overstreet's avatar
Kent Overstreet committed
539 540 541 542 543 544 545 546

	pages = DIV_ROUND_UP(sectors, PAGE_SECTORS);
	io = kzalloc(sizeof(struct moving_io) +
		     sizeof(struct bio_vec) * pages, GFP_KERNEL);
	if (!io)
		goto err;

	io->write.ctxt		= ctxt;
547 548
	io->read_sectors	= k.k->size;
	io->write_sectors	= k.k->size;
Kent Overstreet's avatar
Kent Overstreet committed
549 550 551 552 553 554 555 556 557

	bio_init(&io->write.op.wbio.bio, NULL, io->bi_inline_vecs, pages, 0);
	bio_set_prio(&io->write.op.wbio.bio,
		     IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));

	if (bch2_bio_alloc_pages(&io->write.op.wbio.bio, sectors << 9,
				 GFP_KERNEL))
		goto err_free;

558 559
	io->rbio.c		= c;
	io->rbio.opts		= io_opts;
Kent Overstreet's avatar
Kent Overstreet committed
560 561 562 563 564 565
	bio_init(&io->rbio.bio, NULL, io->bi_inline_vecs, pages, 0);
	io->rbio.bio.bi_vcnt = pages;
	bio_set_prio(&io->rbio.bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
	io->rbio.bio.bi_iter.bi_size = sectors << 9;

	io->rbio.bio.bi_opf		= REQ_OP_READ;
566
	io->rbio.bio.bi_iter.bi_sector	= bkey_start_offset(k.k);
Kent Overstreet's avatar
Kent Overstreet committed
567 568 569
	io->rbio.bio.bi_end_io		= move_read_endio;

	ret = bch2_migrate_write_init(c, &io->write, wp, io_opts,
Kent Overstreet's avatar
Kent Overstreet committed
570
				      data_cmd, data_opts, btree_id, k);
Kent Overstreet's avatar
Kent Overstreet committed
571 572 573
	if (ret)
		goto err_free_pages;

574 575
	io->write.op.end_io = move_write_done;

Kent Overstreet's avatar
Kent Overstreet committed
576
	atomic64_inc(&ctxt->stats->keys_moved);
577
	atomic64_add(k.k->size, &ctxt->stats->sectors_moved);
Kent Overstreet's avatar
Kent Overstreet committed
578

579
	trace_move_extent(k.k);
Kent Overstreet's avatar
Kent Overstreet committed
580 581 582 583 584 585 586 587 588

	atomic_add(io->read_sectors, &ctxt->read_sectors);
	list_add_tail(&io->list, &ctxt->reads);

	/*
	 * dropped by move_read_endio() - guards against use after free of
	 * ctxt when doing wakeup
	 */
	closure_get(&ctxt->cl);
589 590 591
	bch2_read_extent(trans, &io->rbio,
			 bkey_start_pos(k.k),
			 btree_id, k, 0,
Kent Overstreet's avatar
Kent Overstreet committed
592 593 594 595 596 597 598 599
			 BCH_READ_NODECODE|
			 BCH_READ_LAST_FRAGMENT);
	return 0;
err_free_pages:
	bio_free_pages(&io->write.op.wbio.bio);
err_free:
	kfree(io);
err:
600
	trace_move_alloc_fail(k.k);
Kent Overstreet's avatar
Kent Overstreet committed
601 602 603
	return ret;
}

604 605 606
static int lookup_inode(struct btree_trans *trans, struct bpos pos,
			struct bch_inode_unpacked *inode)
{
Kent Overstreet's avatar
Kent Overstreet committed
607
	struct btree_iter iter;
608 609 610
	struct bkey_s_c k;
	int ret;

Kent Overstreet's avatar
Kent Overstreet committed
611 612 613
	bch2_trans_iter_init(trans, &iter, BTREE_ID_inodes, pos,
			     BTREE_ITER_ALL_SNAPSHOTS);
	k = bch2_btree_iter_peek(&iter);
614 615 616 617
	ret = bkey_err(k);
	if (ret)
		goto err;

618 619 620 621 622
	if (!k.k || bkey_cmp(k.k->p, pos)) {
		ret = -ENOENT;
		goto err;
	}

623
	ret = bkey_is_inode(k.k) ? 0 : -EIO;
624 625 626
	if (ret)
		goto err;

627
	ret = bch2_inode_unpack(k, inode);
628 629 630
	if (ret)
		goto err;
err:
Kent Overstreet's avatar
Kent Overstreet committed
631
	bch2_trans_iter_exit(trans, &iter);
632 633 634
	return ret;
}

Kent Overstreet's avatar
Kent Overstreet committed
635 636 637 638 639 640 641 642 643
static int __bch2_move_data(struct bch_fs *c,
		struct moving_context *ctxt,
		struct bch_ratelimit *rate,
		struct write_point_specifier wp,
		struct bpos start,
		struct bpos end,
		move_pred_fn pred, void *arg,
		struct bch_move_stats *stats,
		enum btree_id btree_id)
Kent Overstreet's avatar
Kent Overstreet committed
644 645 646
{
	bool kthread = (current->flags & PF_KTHREAD) != 0;
	struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
647
	struct bkey_buf sk;
648
	struct btree_trans trans;
Kent Overstreet's avatar
Kent Overstreet committed
649
	struct btree_iter iter;
Kent Overstreet's avatar
Kent Overstreet committed
650 651 652
	struct bkey_s_c k;
	struct data_opts data_opts;
	enum data_cmd data_cmd;
653
	u64 delay, cur_inum = U64_MAX;
Kent Overstreet's avatar
Kent Overstreet committed
654 655
	int ret = 0, ret2;

656
	bch2_bkey_buf_init(&sk);
657
	bch2_trans_init(&trans, c, 0, 0);
658

659
	stats->data_type = BCH_DATA_user;
Kent Overstreet's avatar
Kent Overstreet committed
660
	stats->btree_id	= btree_id;
661
	stats->pos	= start;
662

Kent Overstreet's avatar
Kent Overstreet committed
663
	bch2_trans_iter_init(&trans, &iter, btree_id, start,
664 665
			     BTREE_ITER_PREFETCH|
			     BTREE_ITER_ALL_SNAPSHOTS);
Kent Overstreet's avatar
Kent Overstreet committed
666 667 668 669

	if (rate)
		bch2_ratelimit_reset(rate);

670 671 672 673 674
	while (1) {
		do {
			delay = rate ? bch2_ratelimit_delay(rate) : 0;

			if (delay) {
675
				bch2_trans_unlock(&trans);
676 677 678 679 680 681 682 683 684 685 686 687
				set_current_state(TASK_INTERRUPTIBLE);
			}

			if (kthread && (ret = kthread_should_stop())) {
				__set_current_state(TASK_RUNNING);
				goto out;
			}

			if (delay)
				schedule_timeout(delay);

			if (unlikely(freezing(current))) {
688
				move_ctxt_wait_event(ctxt, &trans, list_empty(&ctxt->reads));
689 690 691
				try_to_freeze();
			}
		} while (delay);
692

693 694 695 696 697 698 699 700
		move_ctxt_wait_event(ctxt, &trans,
			atomic_read(&ctxt->write_sectors) <
			SECTORS_IN_FLIGHT_PER_DEVICE);

		move_ctxt_wait_event(ctxt, &trans,
			atomic_read(&ctxt->read_sectors) <
			SECTORS_IN_FLIGHT_PER_DEVICE);

701 702
		bch2_trans_begin(&trans);

Kent Overstreet's avatar
Kent Overstreet committed
703
		k = bch2_btree_iter_peek(&iter);
Kent Overstreet's avatar
Kent Overstreet committed
704 705
		if (!k.k)
			break;
706

707
		ret = bkey_err(k);
708 709
		if (ret == -EINTR)
			continue;
Kent Overstreet's avatar
Kent Overstreet committed
710 711
		if (ret)
			break;
712

Kent Overstreet's avatar
Kent Overstreet committed
713 714 715
		if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
			break;

716 717
		stats->pos = iter.pos;

718
		if (!bkey_extent_is_direct_data(k.k))
Kent Overstreet's avatar
Kent Overstreet committed
719 720
			goto next_nondata;

721
		if (btree_id == BTREE_ID_extents &&
722
		    cur_inum != k.k->p.inode) {
Kent Overstreet's avatar
Kent Overstreet committed
723 724 725
			struct bch_inode_unpacked inode;

			io_opts = bch2_opts_to_inode_opts(c->opts);
726 727 728 729 730 731 732 733

			ret = lookup_inode(&trans,
					SPOS(0, k.k->p.inode, k.k->p.snapshot),
					&inode);
			if (ret == -EINTR)
				continue;

			if (!ret)
Kent Overstreet's avatar
Kent Overstreet committed
734
				bch2_io_opts_apply(&io_opts, bch2_inode_opts_get(&inode));
735

Kent Overstreet's avatar
Kent Overstreet committed
736 737 738
			cur_inum = k.k->p.inode;
		}

739
		switch ((data_cmd = pred(c, arg, k, &io_opts, &data_opts))) {
Kent Overstreet's avatar
Kent Overstreet committed
740 741 742 743 744 745 746 747 748 749 750 751
		case DATA_SKIP:
			goto next;
		case DATA_SCRUB:
			BUG();
		case DATA_ADD_REPLICAS:
		case DATA_REWRITE:
		case DATA_PROMOTE:
			break;
		default:
			BUG();
		}

752 753 754 755
		/*
		 * The iterator gets unlocked by __bch2_read_extent - need to
		 * save a copy of @k elsewhere:
		  */
756
		bch2_bkey_buf_reassemble(&sk, c, k);
Kent Overstreet's avatar
Kent Overstreet committed
757
		k = bkey_i_to_s_c(sk.k);
Kent Overstreet's avatar
Kent Overstreet committed
758

759
		ret2 = bch2_move_extent(&trans, ctxt, wp, io_opts, btree_id, k,
Kent Overstreet's avatar
Kent Overstreet committed
760 761
					data_cmd, data_opts);
		if (ret2) {
762
			if (ret2 == -EINTR)
763 764
				continue;

Kent Overstreet's avatar
Kent Overstreet committed
765 766
			if (ret2 == -ENOMEM) {
				/* memory allocation failure, wait for some IO to finish */
767
				bch2_move_ctxt_wait_for_io(ctxt, &trans);
Kent Overstreet's avatar
Kent Overstreet committed
768 769 770 771 772 773 774 775 776 777
				continue;
			}

			/* XXX signal failure */
			goto next;
		}

		if (rate)
			bch2_ratelimit_increment(rate, k.k->size);
next:
778
		atomic64_add(k.k->size, &stats->sectors_seen);
Kent Overstreet's avatar
Kent Overstreet committed
779
next_nondata:
Kent Overstreet's avatar
Kent Overstreet committed
780
		bch2_btree_iter_advance(&iter);
Kent Overstreet's avatar
Kent Overstreet committed
781
	}
782
out:
783

Kent Overstreet's avatar
Kent Overstreet committed
784
	bch2_trans_iter_exit(&trans, &iter);
785
	bch2_trans_exit(&trans);
786
	bch2_bkey_buf_exit(&sk, c);
Kent Overstreet's avatar
Kent Overstreet committed
787 788 789 790

	return ret;
}

791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
inline void bch_move_stats_init(struct bch_move_stats *stats, char *name)
{
	memset(stats, 0, sizeof(*stats));

	scnprintf(stats->name, sizeof(stats->name),
			"%s", name);
}

static inline void progress_list_add(struct bch_fs *c,
				     struct bch_move_stats *stats)
{
	mutex_lock(&c->data_progress_lock);
	list_add(&stats->list, &c->data_progress_list);
	mutex_unlock(&c->data_progress_lock);
}

static inline void progress_list_del(struct bch_fs *c,
				     struct bch_move_stats *stats)
{
	mutex_lock(&c->data_progress_lock);
	list_del(&stats->list);
	mutex_unlock(&c->data_progress_lock);
}

Kent Overstreet's avatar
Kent Overstreet committed
815
int bch2_move_data(struct bch_fs *c,
816 817
		   enum btree_id start_btree_id, struct bpos start_pos,
		   enum btree_id end_btree_id,   struct bpos end_pos,
Kent Overstreet's avatar
Kent Overstreet committed
818 819 820 821 822 823
		   struct bch_ratelimit *rate,
		   struct write_point_specifier wp,
		   move_pred_fn pred, void *arg,
		   struct bch_move_stats *stats)
{
	struct moving_context ctxt = { .stats = stats };
824
	enum btree_id id;
Kent Overstreet's avatar
Kent Overstreet committed
825 826
	int ret;

827
	progress_list_add(c, stats);
Kent Overstreet's avatar
Kent Overstreet committed
828 829 830 831
	closure_init_stack(&ctxt.cl);
	INIT_LIST_HEAD(&ctxt.reads);
	init_waitqueue_head(&ctxt.wait);

832
	stats->data_type = BCH_DATA_user;
Kent Overstreet's avatar
Kent Overstreet committed
833

834 835 836 837 838
	for (id = start_btree_id;
	     id <= min_t(unsigned, end_btree_id, BTREE_ID_NR - 1);
	     id++) {
		stats->btree_id = id;

839 840
		if (id != BTREE_ID_extents &&
		    id != BTREE_ID_reflink)
841 842 843 844 845 846 847 848 849 850
			continue;

		ret = __bch2_move_data(c, &ctxt, rate, wp,
				       id == start_btree_id ? start_pos : POS_MIN,
				       id == end_btree_id   ? end_pos   : POS_MAX,
				       pred, arg, stats, id);
		if (ret)
			break;
	}

Kent Overstreet's avatar
Kent Overstreet committed
851

852
	move_ctxt_wait_event(&ctxt, NULL, list_empty(&ctxt.reads));
Kent Overstreet's avatar
Kent Overstreet committed
853 854 855 856 857 858 859 860
	closure_sync(&ctxt.cl);

	EBUG_ON(atomic_read(&ctxt.write_sectors));

	trace_move_data(c,
			atomic64_read(&stats->sectors_moved),
			atomic64_read(&stats->keys_moved));

861
	progress_list_del(c, stats);
Kent Overstreet's avatar
Kent Overstreet committed
862 863 864
	return ret;
}

865 866 867 868
typedef enum data_cmd (*move_btree_pred)(struct bch_fs *, void *,
					 struct btree *, struct bch_io_opts *,
					 struct data_opts *);

Kent Overstreet's avatar
Kent Overstreet committed
869
static int bch2_move_btree(struct bch_fs *c,
870 871 872
			   enum btree_id start_btree_id, struct bpos start_pos,
			   enum btree_id end_btree_id,   struct bpos end_pos,
			   move_btree_pred pred, void *arg,
Kent Overstreet's avatar
Kent Overstreet committed
873 874
			   struct bch_move_stats *stats)
{
875
	bool kthread = (current->flags & PF_KTHREAD) != 0;
Kent Overstreet's avatar
Kent Overstreet committed
876
	struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
877
	struct btree_trans trans;
Kent Overstreet's avatar
Kent Overstreet committed
878
	struct btree_iter iter;
Kent Overstreet's avatar
Kent Overstreet committed
879
	struct btree *b;
880
	enum btree_id id;
Kent Overstreet's avatar
Kent Overstreet committed
881 882 883 884
	struct data_opts data_opts;
	enum data_cmd cmd;
	int ret = 0;

885
	bch2_trans_init(&trans, c, 0, 0);
886
	progress_list_add(c, stats);
887

888
	stats->data_type = BCH_DATA_btree;
Kent Overstreet's avatar
Kent Overstreet committed
889

890 891 892
	for (id = start_btree_id;
	     id <= min_t(unsigned, end_btree_id, BTREE_ID_NR - 1);
	     id++) {
893 894
		stats->btree_id = id;

895 896
		bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0,
					  BTREE_ITER_PREFETCH);
897
retry:
898
		ret = 0;
899
		while (bch2_trans_begin(&trans),
900 901
		       (b = bch2_btree_iter_peek_node(&iter)) &&
		       !(ret = PTR_ERR_OR_ZERO(b))) {
902
			if (kthread && kthread_should_stop())
903
				break;
904 905

			if ((cmp_int(id, end_btree_id) ?:
906
			     bpos_cmp(b->key.k.p, end_pos)) > 0)
907 908
				break;

Kent Overstreet's avatar
Kent Overstreet committed
909
			stats->pos = iter.pos;
910

911
			switch ((cmd = pred(c, arg, b, &io_opts, &data_opts))) {
Kent Overstreet's avatar
Kent Overstreet committed
912 913 914 915 916 917 918 919 920 921 922
			case DATA_SKIP:
				goto next;
			case DATA_SCRUB:
				BUG();
			case DATA_ADD_REPLICAS:
			case DATA_REWRITE:
				break;
			default:
				BUG();
			}

923 924 925 926 927
			ret = bch2_btree_node_rewrite(&trans, &iter, b, 0) ?: ret;
			if (ret == -EINTR)
				continue;
			if (ret)
				break;
Kent Overstreet's avatar
Kent Overstreet committed
928
next:
929
			bch2_btree_iter_next_node(&iter);
Kent Overstreet's avatar
Kent Overstreet committed
930
		}
931 932 933
		if (ret == -EINTR)
			goto retry;

Kent Overstreet's avatar
Kent Overstreet committed
934
		bch2_trans_iter_exit(&trans, &iter);
Kent Overstreet's avatar
Kent Overstreet committed
935

936 937
		if (kthread && kthread_should_stop())
			break;
Kent Overstreet's avatar
Kent Overstreet committed
938
	}
939

940 941
	bch2_trans_exit(&trans);

942 943 944
	if (ret)
		bch_err(c, "error %i in bch2_move_btree", ret);

945 946 947 948
	/* flush relevant btree updates */
	closure_wait_event(&c->btree_interior_update_wait,
			   !bch2_btree_interior_updates_nr_pending(c));

949
	progress_list_del(c, stats);
Kent Overstreet's avatar
Kent Overstreet committed
950 951 952 953 954
	return ret;
}

#if 0
static enum data_cmd scrub_pred(struct bch_fs *c, void *arg,
955
				struct bkey_s_c k,
Kent Overstreet's avatar
Kent Overstreet committed
956 957 958 959 960 961 962 963
				struct bch_io_opts *io_opts,
				struct data_opts *data_opts)
{
	return DATA_SCRUB;
}
#endif

static enum data_cmd rereplicate_pred(struct bch_fs *c, void *arg,
964
				      struct bkey_s_c k,
Kent Overstreet's avatar
Kent Overstreet committed
965 966 967
				      struct bch_io_opts *io_opts,
				      struct data_opts *data_opts)
{
968
	unsigned nr_good = bch2_bkey_durability(c, k);
969 970 971
	unsigned replicas = bkey_is_btree_ptr(k.k)
		? c->opts.metadata_replicas
		: io_opts->data_replicas;
Kent Overstreet's avatar
Kent Overstreet committed
972 973 974 975 976

	if (!nr_good || nr_good >= replicas)
		return DATA_SKIP;

	data_opts->target		= 0;
977
	data_opts->nr_replicas		= 1;
978
	data_opts->btree_insert_flags	= 0;
Kent Overstreet's avatar
Kent Overstreet committed
979 980 981 982
	return DATA_ADD_REPLICAS;
}

static enum data_cmd migrate_pred(struct bch_fs *c, void *arg,
983
				  struct bkey_s_c k,
Kent Overstreet's avatar
Kent Overstreet committed
984 985 986 987 988
				  struct bch_io_opts *io_opts,
				  struct data_opts *data_opts)
{
	struct bch_ioctl_data *op = arg;

989
	if (!bch2_bkey_has_device(k, op->migrate.dev))
Kent Overstreet's avatar
Kent Overstreet committed
990 991 992
		return DATA_SKIP;

	data_opts->target		= 0;
993
	data_opts->nr_replicas		= 1;
Kent Overstreet's avatar
Kent Overstreet committed
994 995 996 997 998
	data_opts->btree_insert_flags	= 0;
	data_opts->rewrite_dev		= op->migrate.dev;
	return DATA_REWRITE;
}

999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
static enum data_cmd rereplicate_btree_pred(struct bch_fs *c, void *arg,
					    struct btree *b,
					    struct bch_io_opts *io_opts,
					    struct data_opts *data_opts)
{
	return rereplicate_pred(c, arg, bkey_i_to_s_c(&b->key), io_opts, data_opts);
}

static enum data_cmd migrate_btree_pred(struct bch_fs *c, void *arg,
					struct btree *b,
					struct bch_io_opts *io_opts,
					struct data_opts *data_opts)
{
	return migrate_pred(c, arg, bkey_i_to_s_c(&b->key), io_opts, data_opts);
}

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
static bool bformat_needs_redo(struct bkey_format *f)
{
	unsigned i;

	for (i = 0; i < f->nr_fields; i++) {
		unsigned unpacked_bits = bch2_bkey_format_current.bits_per_field[i];
		u64 unpacked_mask = ~((~0ULL << 1) << (unpacked_bits - 1));
		u64 field_offset = le64_to_cpu(f->field_offset[i]);

		if (f->bits_per_field[i] > unpacked_bits)
			return true;

		if ((f->bits_per_field[i] == unpacked_bits) && field_offset)
			return true;

		if (((field_offset + ((1ULL << f->bits_per_field[i]) - 1)) &
		     unpacked_mask) <
		    field_offset)
			return true;
	}

	return false;
}

1039 1040 1041 1042 1043 1044
static enum data_cmd rewrite_old_nodes_pred(struct bch_fs *c, void *arg,
					    struct btree *b,
					    struct bch_io_opts *io_opts,
					    struct data_opts *data_opts)
{
	if (b->version_ondisk != c->sb.version ||
1045 1046
	    btree_node_need_rewrite(b) ||
	    bformat_needs_redo(&b->format)) {
1047 1048 1049 1050 1051 1052 1053 1054 1055
		data_opts->target		= 0;
		data_opts->nr_replicas		= 1;
		data_opts->btree_insert_flags	= 0;
		return DATA_REWRITE;
	}

	return DATA_SKIP;
}

1056 1057 1058 1059 1060 1061
int bch2_scan_old_btree_nodes(struct bch_fs *c, struct bch_move_stats *stats)
{
	int ret;

	ret = bch2_move_btree(c,
			      0,		POS_MIN,
1062
			      BTREE_ID_NR,	SPOS_MAX,
1063 1064 1065
			      rewrite_old_nodes_pred, c, stats);
	if (!ret) {
		mutex_lock(&c->sb_lock);
1066 1067
		c->disk_sb.sb->compat[0] |= cpu_to_le64(1ULL << BCH_COMPAT_extents_above_btree_updates_done);
		c->disk_sb.sb->compat[0] |= cpu_to_le64(1ULL << BCH_COMPAT_bformat_overflow_done);
1068 1069 1070 1071 1072 1073 1074 1075
		c->disk_sb.sb->version_min = c->disk_sb.sb->version;
		bch2_write_super(c);
		mutex_unlock(&c->sb_lock);
	}

	return ret;
}

Kent Overstreet's avatar
Kent Overstreet committed
1076 1077 1078 1079 1080 1081 1082 1083
int bch2_data_job(struct bch_fs *c,
		  struct bch_move_stats *stats,
		  struct bch_ioctl_data op)
{
	int ret = 0;

	switch (op.op) {
	case BCH_DATA_OP_REREPLICATE:
1084
		bch_move_stats_init(stats, "rereplicate");
1085
		stats->data_type = BCH_DATA_journal;
Kent Overstreet's avatar
Kent Overstreet committed
1086 1087
		ret = bch2_journal_flush_device_pins(&c->journal, -1);

1088 1089 1090 1091
		ret = bch2_move_btree(c,
				      op.start_btree,	op.start_pos,
				      op.end_btree,	op.end_pos,
				      rereplicate_btree_pred, c, stats) ?: ret;
1092
		ret = bch2_replicas_gc2(c) ?: ret;
Kent Overstreet's avatar
Kent Overstreet committed
1093

1094 1095 1096 1097
		ret = bch2_move_data(c,
				     op.start_btree,	op.start_pos,
				     op.end_btree,	op.end_pos,
				     NULL, writepoint_hashed((unsigned long) current),
Kent Overstreet's avatar
Kent Overstreet committed
1098
				     rereplicate_pred, c, stats) ?: ret;
1099
		ret = bch2_replicas_gc2(c) ?: ret;
Kent Overstreet's avatar
Kent Overstreet committed
1100 1101 1102 1103 1104
		break;
	case BCH_DATA_OP_MIGRATE:
		if (op.migrate.dev >= c->sb.nr_devices)
			return -EINVAL;

1105
		bch_move_stats_init(stats, "migrate");
1106
		stats->data_type = BCH_DATA_journal;
Kent Overstreet's avatar
Kent Overstreet committed
1107 1108
		ret = bch2_journal_flush_device_pins(&c->journal, op.migrate.dev);

1109 1110 1111 1112
		ret = bch2_move_btree(c,
				      op.start_btree,	op.start_pos,
				      op.end_btree,	op.end_pos,
				      migrate_btree_pred, &op, stats) ?: ret;
1113
		ret = bch2_replicas_gc2(c) ?: ret;
Kent Overstreet's avatar
Kent Overstreet committed
1114

1115 1116 1117 1118
		ret = bch2_move_data(c,
				     op.start_btree,	op.start_pos,
				     op.end_btree,	op.end_pos,
				     NULL, writepoint_hashed((unsigned long) current),
Kent Overstreet's avatar
Kent Overstreet committed
1119
				     migrate_pred, &op, stats) ?: ret;
1120
		ret = bch2_replicas_gc2(c) ?: ret;
Kent Overstreet's avatar
Kent Overstreet committed
1121
		break;
1122
	case BCH_DATA_OP_REWRITE_OLD_NODES:
1123
		bch_move_stats_init(stats, "rewrite_old_nodes");
1124
		ret = bch2_scan_old_btree_nodes(c, stats);
1125
		break;
Kent Overstreet's avatar
Kent Overstreet committed
1126 1127 1128 1129 1130 1131
	default:
		ret = -EINVAL;
	}

	return ret;
}