diff options
Diffstat (limited to 'fs/bcachefs/rebalance.c')
-rw-r--r-- | fs/bcachefs/rebalance.c | 187 |
1 files changed, 15 insertions, 172 deletions
diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c index a435eb00df32..d1e064be1b9f 100644 --- a/fs/bcachefs/rebalance.c +++ b/fs/bcachefs/rebalance.c @@ -25,8 +25,6 @@ #include <linux/kthread.h> #include <linux/sched/cputime.h> -#define REBALANCE_WORK_SCAN_OFFSET (U64_MAX - 1) - /* bch_extent_rebalance: */ static const struct bch_extent_rebalance *bch2_bkey_ptrs_rebalance_opts(struct bkey_ptrs_c ptrs) @@ -188,61 +186,21 @@ int bch2_bkey_set_needs_rebalance(struct bch_fs *c, struct bch_io_opts *opts, return 0; } -static int have_rebalance_scan_cookie(struct btree_trans *trans, u64 inum) -{ - /* - * If opts need to be propagated to the extent, a scan cookie should be - * present: - */ - CLASS(btree_iter, iter)(trans, BTREE_ID_rebalance_work, - SPOS(inum, REBALANCE_WORK_SCAN_OFFSET, U32_MAX), - BTREE_ITER_intent); - struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter); - int ret = bkey_err(k); - if (ret) - return ret; - - if (k.k->type == KEY_TYPE_cookie) - return 1; - - if (!inum) - return 0; - - bch2_btree_iter_set_pos(&iter, SPOS(0, REBALANCE_WORK_SCAN_OFFSET, U32_MAX)); - k = bch2_btree_iter_peek_slot(&iter); - ret = bkey_err(k); - if (ret) - return ret; - - return k.k->type == KEY_TYPE_cookie; -} - -static int bch2_get_update_rebalance_opts(struct btree_trans *trans, - struct bch_io_opts *io_opts, - struct btree_iter *iter, - struct bkey_s_c k, - bool may_update_indirect) +int bch2_get_update_rebalance_opts(struct btree_trans *trans, + struct bch_io_opts *io_opts, + struct btree_iter *iter, + struct bkey_s_c k) { - int ret = 0; - BUG_ON(iter->flags & BTREE_ITER_is_extents); BUG_ON(iter->flags & BTREE_ITER_filter_snapshots); - /* - * If it's an indirect extent, and we walked to it directly, we won't - * have the options from the inode that were directly applied: options - * from the extent take precedence - unless the io_opts option came from - * the inode and may_update_indirect is true (walked from a - * REFLINK_P_MAY_UPDATE_OPTIONS pointer). - */ const struct bch_extent_rebalance *r = k.k->type == KEY_TYPE_reflink_v ? bch2_bkey_rebalance_opts(k) : NULL; if (r) { -#define x(_name) \ - if (r->_name##_from_inode && \ - !(may_update_indirect && io_opts->_name##_from_inode)) { \ - io_opts->_name = r->_name; \ - io_opts->_name##_from_inode = true; \ +#define x(_name) \ + if (r->_name##_from_inode) { \ + io_opts->_name = r->_name; \ + io_opts->_name##_from_inode = true; \ } BCH_REBALANCE_OPTS() #undef x @@ -251,22 +209,8 @@ static int bch2_get_update_rebalance_opts(struct btree_trans *trans, if (!bch2_bkey_rebalance_needs_update(trans->c, io_opts, k)) return 0; - if (k.k->type != KEY_TYPE_reflink_v) { - ret = have_rebalance_scan_cookie(trans, k.k->p.inode); - if (ret < 0) - return ret; - - if (ret) { - CLASS(printbuf, buf)(); - - bch2_bkey_val_to_text(&buf, trans->c, k); - - fsck_err(trans, extent_io_opts_not_set, "%s", buf.buf); - } - } - struct bkey_i *n = bch2_trans_kmalloc(trans, bkey_bytes(k.k) + 8); - ret = PTR_ERR_OR_ZERO(n); + int ret = PTR_ERR_OR_ZERO(n); if (ret) return ret; @@ -274,113 +218,13 @@ static int bch2_get_update_rebalance_opts(struct btree_trans *trans, /* On successfull transaction commit, @k was invalidated: */ - ret = bch2_bkey_set_needs_rebalance(trans->c, io_opts, n) ?: + return bch2_bkey_set_needs_rebalance(trans->c, io_opts, n) ?: bch2_trans_update(trans, iter, n, BTREE_UPDATE_internal_snapshot_node) ?: bch2_trans_commit(trans, NULL, NULL, 0) ?: - bch_err_throw(trans->c, transaction_restart_commit); -fsck_err: - return ret; + bch_err_throw(trans->c, transaction_restart_nested); } -static struct bch_io_opts *bch2_extent_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; - int ret = 0; - - if (btree_iter_path(trans, extent_iter)->level) - return &io_opts->fs_io_opts; - - if (extent_k.k->type == KEY_TYPE_reflink_v) - return &io_opts->fs_io_opts; - - 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)) - return &i->io_opts; - - return &io_opts->fs_io_opts; -} - -struct bch_io_opts *bch2_extent_get_apply_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, - bool may_update_indirect) -{ - struct bch_io_opts *opts = - bch2_extent_get_io_opts(trans, io_opts, extent_pos, extent_iter, extent_k); - if (IS_ERR(opts) || btree_iter_path(trans, extent_iter)->level) - return opts; - - int ret = bch2_get_update_rebalance_opts(trans, opts, extent_iter, extent_k, - may_update_indirect); - return ret ? ERR_PTR(ret) : opts; -} - -int bch2_extent_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, - bool may_update_indirect) -{ - 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, - may_update_indirect); -} +#define REBALANCE_WORK_SCAN_OFFSET (U64_MAX - 1) static const char * const bch2_rebalance_state_strs[] = { #define x(t) #t, @@ -526,7 +370,7 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans, if (bkey_err(k)) return k; - int ret = bch2_extent_get_io_opts_one(trans, io_opts, extent_iter, k, false); + int ret = bch2_move_get_io_opts_one(trans, io_opts, extent_iter, k); if (ret) return bkey_s_c_err(ret); @@ -663,9 +507,8 @@ static int do_rebalance_scan(struct moving_context *ctxt, u64 inum, u64 cookie) BTREE_ITER_prefetch, k, ({ ctxt->stats->pos = BBPOS(iter.btree_id, iter.pos); - struct bch_io_opts *io_opts = bch2_extent_get_apply_io_opts(trans, - &snapshot_io_opts, iter.pos, &iter, k, - false); + struct bch_io_opts *io_opts = bch2_move_get_io_opts(trans, + &snapshot_io_opts, iter.pos, &iter, k); PTR_ERR_OR_ZERO(io_opts); })) ?: commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc, |