diff options
Diffstat (limited to 'fs/bcachefs/move.c')
-rw-r--r-- | fs/bcachefs/move.c | 209 |
1 files changed, 31 insertions, 178 deletions
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c index 101658cbe95a..9a440d3f7180 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c @@ -46,12 +46,12 @@ struct evacuate_bucket_arg { static bool evacuate_bucket_pred(struct bch_fs *, void *, enum btree_id, struct bkey_s_c, - struct bch_io_opts *, + struct bch_inode_opts *, struct data_update_opts *); static noinline void trace_io_move2(struct bch_fs *c, struct bkey_s_c k, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts) { CLASS(printbuf, buf)(); @@ -72,7 +72,7 @@ static noinline void trace_io_move_read2(struct bch_fs *c, struct bkey_s_c k) static noinline void trace_io_move_pred2(struct bch_fs *c, struct bkey_s_c k, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts, move_pred_fn pred, void *_arg, bool p) { @@ -327,7 +327,7 @@ int bch2_move_extent(struct moving_context *ctxt, struct move_bucket *bucket_in_flight, struct btree_iter *iter, struct bkey_s_c k, - struct bch_io_opts io_opts, + struct bch_inode_opts io_opts, struct data_update_opts data_opts) { struct btree_trans *trans = ctxt->trans; @@ -451,93 +451,6 @@ err: return ret; } -struct bch_io_opts *bch2_move_get_io_opts(struct btree_trans *trans, - struct per_snapshot_io_opts *io_opts, - struct bpos extent_pos, /* extent_iter, extent_k may be in reflink btree */ - struct btree_iter *extent_iter, - struct bkey_s_c extent_k) -{ - struct bch_fs *c = trans->c; - u32 restart_count = trans->restart_count; - struct bch_io_opts *opts_ret = &io_opts->fs_io_opts; - int ret = 0; - - if (btree_iter_path(trans, extent_iter)->level) - return opts_ret; - - if (extent_k.k->type == KEY_TYPE_reflink_v) - goto out; - - if (io_opts->cur_inum != extent_pos.inode) { - io_opts->d.nr = 0; - - ret = for_each_btree_key(trans, iter, BTREE_ID_inodes, POS(0, extent_pos.inode), - BTREE_ITER_all_snapshots, k, ({ - if (k.k->p.offset != extent_pos.inode) - break; - - if (!bkey_is_inode(k.k)) - continue; - - struct bch_inode_unpacked inode; - _ret3 = bch2_inode_unpack(k, &inode); - if (_ret3) - break; - - struct snapshot_io_opts_entry e = { .snapshot = k.k->p.snapshot }; - bch2_inode_opts_get(&e.io_opts, trans->c, &inode); - - darray_push(&io_opts->d, e); - })); - io_opts->cur_inum = extent_pos.inode; - } - - ret = ret ?: trans_was_restarted(trans, restart_count); - if (ret) - return ERR_PTR(ret); - - if (extent_k.k->p.snapshot) - darray_for_each(io_opts->d, i) - if (bch2_snapshot_is_ancestor(c, extent_k.k->p.snapshot, i->snapshot)) { - opts_ret = &i->io_opts; - break; - } -out: - ret = bch2_get_update_rebalance_opts(trans, opts_ret, extent_iter, extent_k); - if (ret) - return ERR_PTR(ret); - return opts_ret; -} - -int bch2_move_get_io_opts_one(struct btree_trans *trans, - struct bch_io_opts *io_opts, - struct btree_iter *extent_iter, - struct bkey_s_c extent_k) -{ - struct bch_fs *c = trans->c; - - *io_opts = bch2_opts_to_inode_opts(c->opts); - - /* reflink btree? */ - if (extent_k.k->p.inode) { - CLASS(btree_iter, inode_iter)(trans, BTREE_ID_inodes, - SPOS(0, extent_k.k->p.inode, extent_k.k->p.snapshot), - BTREE_ITER_cached); - struct bkey_s_c inode_k = bch2_btree_iter_peek_slot(&inode_iter); - int ret = bkey_err(inode_k); - if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) - return ret; - - if (!ret && bkey_is_inode(inode_k.k)) { - struct bch_inode_unpacked inode; - bch2_inode_unpack(inode_k, &inode); - bch2_inode_opts_get(io_opts, c, &inode); - } - } - - return bch2_get_update_rebalance_opts(trans, io_opts, extent_iter, extent_k); -} - int bch2_move_ratelimit(struct moving_context *ctxt) { struct bch_fs *c = ctxt->trans->c; @@ -582,37 +495,6 @@ int bch2_move_ratelimit(struct moving_context *ctxt) return 0; } -/* - * Move requires non extents iterators, and there's also no need for it to - * signal indirect_extent_missing_error: - */ -static struct bkey_s_c bch2_lookup_indirect_extent_for_move(struct btree_trans *trans, - struct btree_iter *iter, - struct bkey_s_c_reflink_p p) -{ - if (unlikely(REFLINK_P_ERROR(p.v))) - return bkey_s_c_null; - - struct bpos reflink_pos = POS(0, REFLINK_P_IDX(p.v)); - - bch2_trans_iter_init(trans, iter, - BTREE_ID_reflink, reflink_pos, - BTREE_ITER_not_extents); - - struct bkey_s_c k = bch2_btree_iter_peek(iter); - if (!k.k || bkey_err(k)) { - bch2_trans_iter_exit(iter); - return k; - } - - if (bkey_lt(reflink_pos, bkey_start_pos(k.k))) { - bch2_trans_iter_exit(iter); - return bkey_s_c_null; - } - - return k; -} - int bch2_move_data_btree(struct moving_context *ctxt, struct bpos start, struct bpos end, @@ -622,17 +504,11 @@ int bch2_move_data_btree(struct moving_context *ctxt, struct btree_trans *trans = ctxt->trans; struct bch_fs *c = trans->c; struct per_snapshot_io_opts snapshot_io_opts; - struct bch_io_opts *io_opts; + struct bch_inode_opts *io_opts; struct bkey_buf sk; struct btree_iter iter, reflink_iter = {}; struct bkey_s_c k; struct data_update_opts data_opts; - /* - * If we're moving a single file, also process reflinked data it points - * to (this includes propagating changed io_opts from the inode to the - * extent): - */ - bool walk_indirect = start.inode == end.inode; int ret = 0, ret2; per_snapshot_io_opts_init(&snapshot_io_opts, c); @@ -697,8 +573,6 @@ root_err: bch2_ratelimit_reset(ctxt->rate); while (!bch2_move_ratelimit(ctxt)) { - struct btree_iter *extent_iter = &iter; - bch2_trans_begin(trans); k = bch2_btree_iter_peek(&iter); @@ -717,41 +591,18 @@ root_err: if (ctxt->stats) ctxt->stats->pos = BBPOS(iter.btree_id, iter.pos); - if (walk_indirect && - k.k->type == KEY_TYPE_reflink_p && - REFLINK_P_MAY_UPDATE_OPTIONS(bkey_s_c_to_reflink_p(k).v)) { - struct bkey_s_c_reflink_p p = bkey_s_c_to_reflink_p(k); - - bch2_trans_iter_exit(&reflink_iter); - k = bch2_lookup_indirect_extent_for_move(trans, &reflink_iter, p); - ret = bkey_err(k); - if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) - continue; - if (ret) - break; - - if (!k.k) - goto next_nondata; - - /* - * XXX: reflink pointers may point to multiple indirect - * extents, so don't advance past the entire reflink - * pointer - need to fixup iter->k - */ - extent_iter = &reflink_iter; - } - if (!bkey_extent_is_direct_data(k.k)) goto next_nondata; - io_opts = bch2_move_get_io_opts(trans, &snapshot_io_opts, - iter.pos, extent_iter, k); + io_opts = bch2_extent_get_apply_io_opts(trans, &snapshot_io_opts, + iter.pos, &iter, k, + SET_NEEDS_REBALANCE_other); ret = PTR_ERR_OR_ZERO(io_opts); if (ret) continue; memset(&data_opts, 0, sizeof(data_opts)); - if (!pred(c, arg, extent_iter->btree_id, k, io_opts, &data_opts)) + if (!pred(c, arg, iter.btree_id, k, io_opts, &data_opts)) goto next; /* @@ -762,7 +613,7 @@ root_err: k = bkey_i_to_s_c(sk.k); if (!level) - ret2 = bch2_move_extent(ctxt, NULL, extent_iter, k, *io_opts, data_opts); + ret2 = bch2_move_extent(ctxt, NULL, &iter, k, *io_opts, data_opts); else if (!data_opts.scrub) ret2 = bch2_btree_node_rewrite_pos(trans, btree_id, level, k.k->p, data_opts.target, 0); @@ -824,7 +675,7 @@ static int bch2_move_data(struct bch_fs *c, unsigned min_depth_this_btree = min_depth; /* Stripe keys have pointers, but are handled separately */ - if (!btree_type_has_ptrs(id) || + if (!btree_type_has_data_ptrs(id) || id == BTREE_ID_stripes) min_depth_this_btree = max(min_depth_this_btree, 1); @@ -859,7 +710,6 @@ static int __bch2_move_data_phys(struct moving_context *ctxt, struct btree_trans *trans = ctxt->trans; struct bch_fs *c = trans->c; bool is_kthread = current->flags & PF_KTHREAD; - struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts); struct btree_iter iter = {}; struct bkey_buf sk; struct bkey_s_c k; @@ -867,7 +717,11 @@ static int __bch2_move_data_phys(struct moving_context *ctxt, u64 check_mismatch_done = bucket_start; int ret = 0; - CLASS(bch2_dev_tryget, ca)(c, dev); + struct bch_inode_opts io_opts; + bch2_inode_opts_get(c, &io_opts); + + /* Userspace might have supplied @dev: */ + CLASS(bch2_dev_tryget_noerror, ca)(c, dev); if (!ca) return 0; @@ -941,7 +795,8 @@ static int __bch2_move_data_phys(struct moving_context *ctxt, goto next; if (!bp.v->level) { - ret = bch2_move_get_io_opts_one(trans, &io_opts, &iter, k); + ret = bch2_extent_get_apply_io_opts_one(trans, &io_opts, &iter, k, + SET_NEEDS_REBALANCE_other); if (ret) { bch2_trans_iter_exit(&iter); continue; @@ -1038,7 +893,7 @@ int bch2_move_data_phys(struct bch_fs *c, static bool evacuate_bucket_pred(struct bch_fs *c, void *_arg, enum btree_id btree, struct bkey_s_c k, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts) { struct evacuate_bucket_arg *arg = _arg; @@ -1079,7 +934,7 @@ int bch2_evacuate_bucket(struct moving_context *ctxt, } typedef bool (*move_btree_pred)(struct bch_fs *, void *, - struct btree *, struct bch_io_opts *, + struct btree *, struct bch_inode_opts *, struct data_update_opts *); static int bch2_move_btree(struct bch_fs *c, @@ -1089,7 +944,6 @@ static int bch2_move_btree(struct bch_fs *c, struct bch_move_stats *stats) { bool kthread = (current->flags & PF_KTHREAD) != 0; - struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts); struct moving_context ctxt; struct btree_trans *trans; struct btree_iter iter; @@ -1098,6 +952,9 @@ static int bch2_move_btree(struct bch_fs *c, struct data_update_opts data_opts; int ret = 0; + struct bch_inode_opts io_opts; + bch2_inode_opts_get(c, &io_opts); + bch2_moving_ctxt_init(&ctxt, c, NULL, stats, writepoint_ptr(&c->btree_write_point), true); @@ -1158,7 +1015,7 @@ next: static bool rereplicate_pred(struct bch_fs *c, void *arg, enum btree_id btree, struct bkey_s_c k, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts) { unsigned nr_good = bch2_bkey_durability(c, k); @@ -1189,7 +1046,7 @@ static bool rereplicate_pred(struct bch_fs *c, void *arg, static bool migrate_pred(struct bch_fs *c, void *arg, enum btree_id btree, struct bkey_s_c k, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts) { struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); @@ -1226,7 +1083,7 @@ static bool bformat_needs_redo(struct bkey_format *f) static bool rewrite_old_nodes_pred(struct bch_fs *c, void *arg, struct btree *b, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts) { if (b->version_ondisk != c->sb.version || @@ -1263,7 +1120,7 @@ int bch2_scan_old_btree_nodes(struct bch_fs *c, struct bch_move_stats *stats) static bool drop_extra_replicas_pred(struct bch_fs *c, void *arg, enum btree_id btree, struct bkey_s_c k, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts) { unsigned durability = bch2_bkey_durability(c, k); @@ -1301,7 +1158,7 @@ static bool drop_extra_replicas_pred(struct bch_fs *c, void *arg, static bool scrub_pred(struct bch_fs *c, void *_arg, enum btree_id btree, struct bkey_s_c k, - struct bch_io_opts *io_opts, + struct bch_inode_opts *io_opts, struct data_update_opts *data_opts) { struct bch_ioctl_data *arg = _arg; @@ -1404,7 +1261,7 @@ void bch2_move_stats_to_text(struct printbuf *out, struct bch_move_stats *stats) prt_str(out, " pos="); bch2_bbpos_to_text(out, stats->pos); prt_newline(out); - printbuf_indent_add(out, 2); + guard(printbuf_indent)(out); prt_printf(out, "keys moved:\t%llu\n", atomic64_read(&stats->keys_moved)); prt_printf(out, "keys raced:\t%llu\n", atomic64_read(&stats->keys_raced)); @@ -1419,8 +1276,6 @@ void bch2_move_stats_to_text(struct printbuf *out, struct bch_move_stats *stats) prt_printf(out, "bytes raced:\t"); prt_human_readable_u64(out, atomic64_read(&stats->sectors_raced) << 9); prt_newline(out); - - printbuf_indent_sub(out, 2); } static void bch2_moving_ctxt_to_text(struct printbuf *out, struct bch_fs *c, struct moving_context *ctxt) @@ -1429,7 +1284,7 @@ static void bch2_moving_ctxt_to_text(struct printbuf *out, struct bch_fs *c, str printbuf_tabstop_push(out, 32); bch2_move_stats_to_text(out, ctxt->stats); - printbuf_indent_add(out, 2); + guard(printbuf_indent)(out); prt_printf(out, "reads: ios %u/%u sectors %u/%u\n", atomic_read(&ctxt->read_ios), @@ -1443,15 +1298,13 @@ static void bch2_moving_ctxt_to_text(struct printbuf *out, struct bch_fs *c, str atomic_read(&ctxt->write_sectors), c->opts.move_bytes_in_flight >> 9); - printbuf_indent_add(out, 2); + guard(printbuf_indent)(out); scoped_guard(mutex, &ctxt->lock) { struct moving_io *io; list_for_each_entry(io, &ctxt->ios, io_list) bch2_data_update_inflight_to_text(out, &io->write); } - - printbuf_indent_sub(out, 4); } void bch2_fs_moving_ctxts_to_text(struct printbuf *out, struct bch_fs *c) |