bch2_get_update_rebalance_opts() now checks for consistency between bch_extent_rebalance and the io path options from the inode and filesystem; unless an option has been recently changed (and a scan to propagate new options queued), they should match.
Signed-off-by: Kent Overstreet <[email protected]> --- fs/bcachefs/rebalance.c | 65 +++++++++++++++++++++++++++++++--- fs/bcachefs/sb-errors_format.h | 3 +- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c index a2fb2f1cec70..872fff940c5a 100644 --- a/fs/bcachefs/rebalance.c +++ b/fs/bcachefs/rebalance.c @@ -25,6 +25,8 @@ #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) @@ -178,6 +180,35 @@ int bch2_bkey_set_needs_rebalance(struct bch_fs *c, struct bch_inode_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_inode_opts *io_opts, struct btree_iter *iter, @@ -185,6 +216,7 @@ static int bch2_get_update_rebalance_opts(struct btree_trans *trans, enum set_needs_rebalance_ctx ctx) { struct bch_fs *c = trans->c; + int ret = 0; BUG_ON(iter->flags & BTREE_ITER_is_extents); BUG_ON(iter->flags & BTREE_ITER_filter_snapshots); @@ -220,8 +252,33 @@ static int bch2_get_update_rebalance_opts(struct btree_trans *trans, : !old) 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)(); + + prt_printf(&buf, "extent with incorrect/missing rebalance opts:\n"); + bch2_bkey_val_to_text(&buf, c, k); + + const struct bch_extent_rebalance _old = {}; + if (!old) + old = &_old; +#define x(_name) \ + if (old->_name != new._name) \ + prt_printf(&buf, "\n" #_name " %u != %u", \ + old->_name, new._name); \ + BCH_REBALANCE_OPTS() +#undef x + + fsck_err(trans, extent_io_opts_not_set, "%s", buf.buf); + } + } + struct bkey_i *n = bch2_trans_kmalloc(trans, bkey_bytes(k.k) + 8); - int ret = PTR_ERR_OR_ZERO(n); + ret = PTR_ERR_OR_ZERO(n); if (ret) return ret; @@ -229,10 +286,12 @@ static int bch2_get_update_rebalance_opts(struct btree_trans *trans, /* On successfull transaction commit, @k was invalidated: */ - return bch2_bkey_set_needs_rebalance(c, io_opts, n, ctx, 0) ?: + ret = bch2_bkey_set_needs_rebalance(c, io_opts, n, ctx, 0) ?: bch2_trans_update(trans, iter, n, BTREE_UPDATE_internal_snapshot_node) ?: bch2_trans_commit(trans, NULL, NULL, 0) ?: bch_err_throw(c, transaction_restart_commit); +fsck_err: + return ret; } static struct bch_inode_opts *bch2_extent_get_io_opts(struct btree_trans *trans, @@ -335,8 +394,6 @@ int bch2_extent_get_io_opts_one(struct btree_trans *trans, ctx); } -#define REBALANCE_WORK_SCAN_OFFSET (U64_MAX - 1) - static const char * const bch2_rebalance_state_strs[] = { #define x(t) #t, BCH_REBALANCE_STATES() diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h index aa0ea1ec9f10..4816c4150261 100644 --- a/fs/bcachefs/sb-errors_format.h +++ b/fs/bcachefs/sb-errors_format.h @@ -337,7 +337,8 @@ enum bch_fsck_flags { x(dirent_stray_data_after_cf_name, 305, 0) \ x(rebalance_work_incorrectly_set, 309, FSCK_AUTOFIX) \ x(rebalance_work_incorrectly_unset, 310, FSCK_AUTOFIX) \ - x(MAX, 326, 0) + x(extent_io_opts_not_set, 326, FSCK_AUTOFIX) \ + x(MAX, 327, 0) enum bch_sb_error_id { #define x(t, n, ...) BCH_FSCK_ERR_##t = n, -- 2.50.1
