diff --git a/.bcachefs_revision b/.bcachefs_revision index b62e19f3..370b9636 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -482e1f07810803ba5509653d4a4fcd217d26d280 +b3616d33633509373c40c441e8c32ea554e2fa35 diff --git a/libbcachefs/btree/commit.c b/libbcachefs/btree/commit.c index a3a3a2da..40bd13db 100644 --- a/libbcachefs/btree/commit.c +++ b/libbcachefs/btree/commit.c @@ -68,7 +68,15 @@ static void verify_update_old_key(struct btree_trans *trans, struct btree_insert } struct bkey_s_c old = { &i->old_k, i->old_v }; - BUG_ON(!bkey_and_val_eq(k, old)); + if (unlikely(!bkey_and_val_eq(k, old))) { + CLASS(printbuf, buf)(); + prt_str(&buf, "updated cached old key doesn't match\n"); + prt_str(&buf, "cached: "); + bch2_bkey_val_to_text(&buf, c, old); + prt_str(&buf, "real: "); + bch2_bkey_val_to_text(&buf, c, k); + panic("%s\n", buf.buf); + } #endif } diff --git a/libbcachefs/data/reconcile.c b/libbcachefs/data/reconcile.c index 2a134d89..98ad3db1 100644 --- a/libbcachefs/data/reconcile.c +++ b/libbcachefs/data/reconcile.c @@ -23,7 +23,6 @@ #include "init/progress.h" #include "fs/inode.h" -#include "fs/namei.h" #include "snapshots/subvolume.h" @@ -33,56 +32,6 @@ #include #include -#define RECONCILE_WORK_IDS() \ - x(none) \ - x(hipri) \ - x(normal) \ - x(pending) - -enum reconcile_work_id { -#define x(t) RECONCILE_WORK_##t, - RECONCILE_WORK_IDS() -#undef x -}; - -#define x(n) #n, - -static const char * const reconcile_opts[] = { - BCH_REBALANCE_OPTS() - NULL -}; - -static const char * const reconcile_work_ids[] = { - RECONCILE_WORK_IDS() - NULL -}; - -static const char * const rebalance_scan_strs[] = { - RECONCILE_SCAN_TYPES() -}; - -#undef x - -static const enum btree_id reconcile_work_btree[] = { - [RECONCILE_WORK_hipri] = BTREE_ID_reconcile_hipri, - [RECONCILE_WORK_normal] = BTREE_ID_reconcile_work, - [RECONCILE_WORK_pending] = BTREE_ID_reconcile_pending, -}; - -static enum reconcile_work_id btree_to_reconcile_work_id(enum btree_id btree) -{ - switch (btree) { - case BTREE_ID_reconcile_hipri: - return RECONCILE_WORK_hipri; - case BTREE_ID_reconcile_work: - return RECONCILE_WORK_normal; - case BTREE_ID_reconcile_pending: - return RECONCILE_WORK_pending; - default: - BUG(); - } -} - /* bch_extent_reconcile: */ int bch2_extent_reconcile_validate(struct bch_fs *c, @@ -129,6 +78,13 @@ const struct bch_extent_reconcile *bch2_bkey_reconcile_opts(const struct bch_fs return bch2_bkey_ptrs_reconcile_opts(c, bch2_bkey_ptrs_c(k)); } +static const char * const reconcile_opts[] = { +#define x(n) #n, + BCH_REBALANCE_OPTS() +#undef x + NULL +}; + void bch2_extent_rebalance_v1_to_text(struct printbuf *out, struct bch_fs *c, const struct bch_extent_rebalance_v1 *r) { @@ -235,20 +191,20 @@ void bch2_extent_reconcile_to_text(struct printbuf *out, struct bch_fs *c, } } -static enum reconcile_work_id rb_work_id(const struct bch_extent_reconcile *r) -{ - if (!r || !r->need_rb) - return RECONCILE_WORK_none; - if (r->hipri) - return RECONCILE_WORK_hipri; - if (!r->pending) - return RECONCILE_WORK_normal; - return RECONCILE_WORK_pending; -} +/* + * XXX: check in bkey_validate that if r->hipri or r->pending are set, + * r->data_replicas are also set + */ static enum btree_id rb_work_btree(const struct bch_extent_reconcile *r) { - return reconcile_work_btree[rb_work_id(r)]; + if (!r || !r->need_rb) + return 0; + if (r->hipri) + return BTREE_ID_reconcile_hipri; + if (r->pending) + return BTREE_ID_reconcile_pending; + return BTREE_ID_reconcile_work; } static inline unsigned rb_accounting_counters(const struct bch_extent_reconcile *r) @@ -1052,6 +1008,13 @@ int bch2_bkey_get_io_opts(struct btree_trans *trans, return 0; } +static const char * const bch2_reconcile_state_strs[] = { +#define x(t) #t, + BCH_REBALANCE_STATES() + NULL +#undef x +}; + #define RECONCILE_SCAN_COOKIE_device 32 #define RECONCILE_SCAN_COOKIE_pending 2 #define RECONCILE_SCAN_COOKIE_metadata 1 @@ -1095,24 +1058,6 @@ static struct reconcile_scan reconcile_scan_decode(struct bch_fs *c, u64 v) return (struct reconcile_scan) { .type = RECONCILE_SCAN_fs}; } -static void reconcile_scan_to_text(struct printbuf *out, - struct bch_fs *c, struct reconcile_scan s) -{ - prt_str(out, rebalance_scan_strs[s.type]); - switch (s.type) { - case RECONCILE_SCAN_device: - prt_str(out, ": "); - bch2_prt_member_name(out, c, s.dev); - break; - case RECONCILE_SCAN_inum: - prt_str(out, ": "); - bch2_trans_do(c, bch2_inum_snapshot_to_path(trans, s.inum, 0, NULL, out)); - break; - default: - break; - } -} - int bch2_set_reconcile_needs_scan_trans(struct btree_trans *trans, struct reconcile_scan s) { CLASS(btree_iter, iter)(trans, BTREE_ID_reconcile_scan, @@ -1379,6 +1324,7 @@ static int __do_reconcile_extent(struct moving_context *ctxt, u32 restart_count = trans->restart_count; ctxt->stats = &c->reconcile.work_stats; + c->reconcile.state = BCH_REBALANCE_working; int ret = bch2_move_extent(ctxt, NULL, snapshot_io_opts, reconcile_set_data_opts, NULL, @@ -1413,13 +1359,11 @@ static int __do_reconcile_extent(struct moving_context *ctxt, static int do_reconcile_extent(struct moving_context *ctxt, struct per_snapshot_io_opts *snapshot_io_opts, - struct bpos work_pos) + struct bbpos pos) { - struct bbpos data_pos = rb_work_to_data_pos(work_pos); - struct btree_trans *trans = ctxt->trans; - CLASS(btree_iter, iter)(trans, data_pos.btree, data_pos.pos, BTREE_ITER_all_snapshots); + CLASS(btree_iter, iter)(trans, pos.btree, pos.pos, BTREE_ITER_all_snapshots); struct bkey_s_c k = bkey_try(bch2_btree_iter_peek_slot(&iter)); return __do_reconcile_extent(ctxt, snapshot_io_opts, &iter, k); @@ -1606,6 +1550,8 @@ static int do_reconcile_scan(struct moving_context *ctxt, bch2_move_stats_init(&r->scan_stats, "reconcile_scan"); ctxt->stats = &r->scan_stats; + r->state = BCH_REBALANCE_scanning; + struct reconcile_scan s = reconcile_scan_decode(c, cookie_pos.offset); if (s.type == RECONCILE_SCAN_fs) { try(do_reconcile_scan_fs(ctxt, snapshot_io_opts, false)); @@ -1668,10 +1614,10 @@ static void reconcile_wait(struct bch_fs *c) r->wait_iotime_end = now + (min_member_capacity >> 6); - if (r->running) { + if (r->state != BCH_REBALANCE_waiting) { r->wait_iotime_start = now; r->wait_wallclock_start = ktime_get_real_ns(); - r->running = false; + r->state = BCH_REBALANCE_waiting; } bch2_kthread_io_clock_wait_once(clock, r->wait_iotime_end, MAX_SCHEDULE_TIMEOUT); @@ -1707,8 +1653,7 @@ static int do_reconcile(struct moving_context *ctxt) BTREE_ID_reconcile_pending, }; unsigned i = 0; - - r->work_pos = BBPOS(scan_btrees[i], POS_MIN); + struct bpos work_pos = POS_MIN; struct bkey_i_cookie pending_cookie; bkey_init(&pending_cookie.k); @@ -1725,11 +1670,13 @@ static int do_reconcile(struct moving_context *ctxt) if (kick != r->kick) { kick = r->kick; i = 0; - r->work_pos = BBPOS(scan_btrees[i], POS_MIN); + work_pos = POS_MIN; work.nr = 0; } - struct bkey_s_c k = next_reconcile_entry(trans, &work, r->work_pos.btree, &r->work_pos.pos); + bch2_trans_begin(trans); + + struct bkey_s_c k = next_reconcile_entry(trans, &work, scan_btrees[i], &work_pos); ret = bkey_err(k); if (ret) break; @@ -1738,17 +1685,14 @@ static int do_reconcile(struct moving_context *ctxt) if (++i == ARRAY_SIZE(scan_btrees)) break; - r->work_pos = BBPOS(scan_btrees[i], POS_MIN); + work_pos = POS_MIN; - if (r->work_pos.btree == BTREE_ID_reconcile_pending && + if (scan_btrees[i] == BTREE_ID_reconcile_pending && bkey_deleted(&pending_cookie.k)) break; continue; } - r->running = true; - r->work_pos.pos = k.k->p; - if (k.k->type == KEY_TYPE_cookie && reconcile_scan_decode(c, k.k->p.offset).type == RECONCILE_SCAN_pending) bkey_reassemble(&pending_cookie.k_i, k); @@ -1763,7 +1707,8 @@ static int do_reconcile(struct moving_context *ctxt) bkey_s_c_to_backpointer(k)); else ret = lockrestart_do(trans, - do_reconcile_extent(ctxt, &snapshot_io_opts, k.k->p)); + do_reconcile_extent(ctxt, &snapshot_io_opts, + rb_work_to_data_pos(k.k->p))); if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) { ret = 0; @@ -1773,8 +1718,8 @@ static int do_reconcile(struct moving_context *ctxt) if (ret) break; - if (r->work_pos.btree == BTREE_ID_reconcile_scan) - r->work_pos.pos = bpos_successor(r->work_pos.pos); + if (scan_btrees[i] == BTREE_ID_reconcile_scan) + work_pos = bpos_successor(work_pos); } if (!ret && !bkey_deleted(&pending_cookie.k)) @@ -1843,10 +1788,13 @@ void bch2_reconcile_status_to_text(struct printbuf *out, struct bch_fs *c) } prt_newline(out); - guard(printbuf_indent_nextline)(out); - if (!r->running) { - prt_printf(out, "waiting:\n"); + prt_str(out, bch2_reconcile_state_strs[r->state]); + prt_newline(out); + guard(printbuf_indent)(out); + + switch (r->state) { + case BCH_REBALANCE_waiting: { u64 now = atomic64_read(&c->io_clock[WRITE].now); prt_printf(out, "io wait duration:\t"); @@ -1860,28 +1808,16 @@ void bch2_reconcile_status_to_text(struct printbuf *out, struct bch_fs *c) prt_printf(out, "duration waited:\t"); bch2_pr_time_units(out, ktime_get_real_ns() - r->wait_wallclock_start); prt_newline(out); - } else { - struct bbpos work_pos = r->work_pos; - barrier(); - - if (work_pos.btree == BTREE_ID_reconcile_scan && - work_pos.pos.inode == 0) { - prt_printf(out, "scanning:\n"); - reconcile_scan_to_text(out, c, - reconcile_scan_decode(c, work_pos.pos.offset)); - } else if (work_pos.btree == BTREE_ID_reconcile_scan) { - prt_printf(out, "processing metadata: %s %llu\n", - reconcile_work_ids[work_pos.pos.inode - 1], - work_pos.pos.offset); - - } else { - prt_printf(out, "processing data: %s ", - reconcile_work_ids[btree_to_reconcile_work_id(work_pos.btree)]); - - bch2_bbpos_to_text(out, rb_work_to_data_pos(work_pos.pos)); - prt_newline(out); - } + break; } + case BCH_REBALANCE_working: + bch2_move_stats_to_text(out, &r->work_stats); + break; + case BCH_REBALANCE_scanning: + bch2_move_stats_to_text(out, &r->scan_stats); + break; + } + prt_newline(out); struct task_struct *t; scoped_guard(rcu) { diff --git a/libbcachefs/data/reconcile.h b/libbcachefs/data/reconcile.h index aae18eb6..47b7240a 100644 --- a/libbcachefs/data/reconcile.h +++ b/libbcachefs/data/reconcile.h @@ -114,18 +114,13 @@ int bch2_bkey_set_needs_reconcile(struct btree_trans *, struct per_snapshot_io_opts *, struct bch_inode_opts *, struct bkey_i *, enum set_needs_reconcile_ctx, u32); -#define RECONCILE_SCAN_TYPES() \ - x(fs) \ - x(metadata) \ - x(pending) \ - x(device) \ - x(inum) - struct reconcile_scan { enum reconcile_scan_type { -#define x(t) RECONCILE_SCAN_##t, - RECONCILE_SCAN_TYPES() -#undef x + RECONCILE_SCAN_fs, + RECONCILE_SCAN_metadata, + RECONCILE_SCAN_pending, + RECONCILE_SCAN_device, + RECONCILE_SCAN_inum, } type; union { diff --git a/libbcachefs/data/reconcile_types.h b/libbcachefs/data/reconcile_types.h index 2fd11104..78d08e15 100644 --- a/libbcachefs/data/reconcile_types.h +++ b/libbcachefs/data/reconcile_types.h @@ -5,16 +5,26 @@ #include "btree/bbpos_types.h" #include "move_types.h" +#define BCH_REBALANCE_STATES() \ + x(waiting) \ + x(working) \ + x(scanning) + +enum bch_reconcile_states { +#define x(t) BCH_REBALANCE_##t, + BCH_REBALANCE_STATES() +#undef x +}; + struct bch_fs_reconcile { struct task_struct __rcu *thread; u32 kick; - bool running; + enum bch_reconcile_states state; u64 wait_iotime_start; u64 wait_iotime_end; u64 wait_wallclock_start; - struct bbpos work_pos; struct bch_move_stats work_stats; struct bbpos scan_start; diff --git a/libbcachefs/fs/namei.c b/libbcachefs/fs/namei.c index 8568f748..e7df6a05 100644 --- a/libbcachefs/fs/namei.c +++ b/libbcachefs/fs/namei.c @@ -528,27 +528,9 @@ static int __bch2_inum_to_path(struct btree_trans *trans, DARRAY(subvol_inum) inums = {}; if (!snapshot) { - if (subvol) { - ret = bch2_subvolume_get_snapshot(trans, subvol, &snapshot); - if (ret) - goto disconnected; - } else { - struct bkey_s_c k; - for_each_btree_key_max_norestart(trans, iter, - BTREE_ID_inodes, - POS(0, inum), - SPOS(0, inum, U32_MAX), - BTREE_ITER_all_snapshots, k, ret) { - if (bkey_is_inode(k.k)) { - snapshot = k.k->p.snapshot; - break; - } - } - if (ret) - return ret; - if (!snapshot) - goto disconnected; - } + ret = bch2_subvolume_get_snapshot(trans, subvol, &snapshot); + if (ret) + goto disconnected; } while (true) { diff --git a/libbcachefs/sb/members.h b/libbcachefs/sb/members.h index 96b4ce9f..7fc363ca 100644 --- a/libbcachefs/sb/members.h +++ b/libbcachefs/sb/members.h @@ -410,15 +410,4 @@ void bch2_dev_btree_bitmap_mark(struct bch_fs *, struct bkey_s_c); int bch2_sb_member_alloc(struct bch_fs *); void bch2_sb_members_clean_deleted(struct bch_fs *); -static inline void bch2_prt_member_name(struct printbuf *out, struct bch_fs *c, unsigned idx) -{ - guard(rcu)(); - guard(printbuf_atomic)(out); - struct bch_dev *ca = c ? bch2_dev_rcu_noerror(c, idx) : NULL; - if (ca) - prt_str(out, ca->name); - else - prt_printf(out, "(invalid device %u)", idx); -} - #endif /* _BCACHEFS_SB_MEMBERS_H */ diff --git a/libbcachefs/util/printbuf.h b/libbcachefs/util/printbuf.h index 2d606143..37e0b82c 100644 --- a/libbcachefs/util/printbuf.h +++ b/libbcachefs/util/printbuf.h @@ -299,12 +299,18 @@ DEFINE_GUARD(printbuf_atomic, struct printbuf *, printbuf_atomic_inc(_T), printbuf_atomic_dec(_T)); -DEFINE_GUARD(printbuf_indent, struct printbuf *, - bch2_printbuf_indent_add(_T, 2), - bch2_printbuf_indent_sub(_T, 2)); +static inline void printbuf_indent_add_2(struct printbuf *out) +{ + bch2_printbuf_indent_add(out, 2); +} -DEFINE_GUARD(printbuf_indent_nextline, struct printbuf *, - bch2_printbuf_indent_add_nextline(_T, 2), - bch2_printbuf_indent_sub(_T, 2)); +static inline void printbuf_indent_sub_2(struct printbuf *out) +{ + bch2_printbuf_indent_sub(out, 2); +} + +DEFINE_GUARD(printbuf_indent, struct printbuf *, + printbuf_indent_add_2(_T), + printbuf_indent_sub_2(_T)); #endif /* _BCACHEFS_PRINTBUF_H */