diff --git a/.bcachefs_revision b/.bcachefs_revision index 4295df5d..417e5faa 100644 --- a/.bcachefs_revision +++ b/.bcachefs_revision @@ -1 +1 @@ -ceaf9ded6efd90d5bd53c6c77d9469c5ef9bbda5 +32ed7123aeacc7486df3d04c1540b18a7105936a diff --git a/libbcachefs/bcachefs.h b/libbcachefs/bcachefs.h index 3ccca855..36732905 100644 --- a/libbcachefs/bcachefs.h +++ b/libbcachefs/bcachefs.h @@ -686,6 +686,7 @@ struct btree_debug { unsigned id; }; +#define BCH_LINK_MAX U32_MAX #define BCH_TRANSACTIONS_NR 128 struct btree_transaction_stats { diff --git a/libbcachefs/btree_gc.c b/libbcachefs/btree_gc.c index 63dc0836..638c2a92 100644 --- a/libbcachefs/btree_gc.c +++ b/libbcachefs/btree_gc.c @@ -204,7 +204,7 @@ static int btree_check_node_boundaries(struct btree_trans *trans, struct btree * if (bpos_eq(expected_start, cur->data->min_key)) return 0; - prt_printf(&buf, " at "); + prt_printf(&buf, " at "); bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level); prt_printf(&buf, ":\nparent: "); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); @@ -229,8 +229,8 @@ static int btree_check_node_boundaries(struct btree_trans *trans, struct btree * *pulled_from_scan = cur->data->min_key; ret = bch_err_throw(c, topology_repair_did_fill_from_scan); } else { - if (mustfix_fsck_err(trans, btree_node_topology_bad_min_key, - "btree node with incorrect min_key%s", buf.buf)) + if (mustfix_fsck_err(trans, btree_node_topology_gap_between_nodes, + "gap between btree nodes%s", buf.buf)) ret = set_node_min(c, cur, expected_start); } } else { /* overlap */ diff --git a/libbcachefs/btree_io.c b/libbcachefs/btree_io.c index 52d21259..3808c41d 100644 --- a/libbcachefs/btree_io.c +++ b/libbcachefs/btree_io.c @@ -1318,6 +1318,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca, set_btree_bset_end(b, b->set); set_btree_node_need_rewrite(b); set_btree_node_need_rewrite_error(b); + ret = 0; continue; } if (ret) diff --git a/libbcachefs/disk_accounting.c b/libbcachefs/disk_accounting.c index a99f821c..22b2dbe8 100644 --- a/libbcachefs/disk_accounting.c +++ b/libbcachefs/disk_accounting.c @@ -814,6 +814,8 @@ int bch2_accounting_read(struct bch_fs *c) struct journal_keys *keys = &c->journal_keys; struct journal_key *jk = keys->data; + move_gap(keys, keys->nr); + while (jk < &darray_top(*keys) && __journal_key_cmp(c, BTREE_ID_accounting, 0, POS_MIN, jk) > 0) jk++; @@ -829,9 +831,6 @@ int bch2_accounting_read(struct bch_fs *c) iter.flags &= ~BTREE_ITER_with_journal; int ret = for_each_btree_key_continue(trans, iter, BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k, ({ - struct bkey u; - struct bkey_s_c k = bch2_btree_path_peek_slot_exact(btree_iter_path(trans, &iter), &u); - if (k.k->type != KEY_TYPE_accounting) continue; @@ -860,7 +859,7 @@ int bch2_accounting_read(struct bch_fs *c) struct disk_accounting_pos next_acc; memset(&next_acc, 0, sizeof(next_acc)); next_acc.type = acc_k.type + 1; - struct bpos next = disk_accounting_pos_to_bpos(&next_acc); + struct bpos next = bpos_predecessor(disk_accounting_pos_to_bpos(&next_acc)); if (jk < end) next = bpos_min(next, journal_key_k(c, jk)->k.p); diff --git a/libbcachefs/errcode.h b/libbcachefs/errcode.h index db2dc5b0..2712a975 100644 --- a/libbcachefs/errcode.h +++ b/libbcachefs/errcode.h @@ -228,6 +228,7 @@ x(BCH_ERR_topology_repair, topology_repair_drop_this_node) \ x(BCH_ERR_topology_repair, topology_repair_drop_prev_node) \ x(BCH_ERR_topology_repair, topology_repair_did_fill_from_scan) \ + x(EMLINK, too_many_links) \ x(EOPNOTSUPP, may_not_use_incompat_feature) \ x(EOPNOTSUPP, no_casefolding_without_utf8) \ x(EOPNOTSUPP, casefolding_disabled) \ diff --git a/libbcachefs/inode.c b/libbcachefs/inode.c index 543627fb..fda4ca78 100644 --- a/libbcachefs/inode.c +++ b/libbcachefs/inode.c @@ -1184,8 +1184,8 @@ int bch2_inode_nlink_inc(struct bch_inode_unpacked *bi) if (bi->bi_flags & BCH_INODE_unlinked) bi->bi_flags &= ~BCH_INODE_unlinked; else { - if (bi->bi_nlink == U32_MAX) - return -EINVAL; + if (bi->bi_nlink == BCH_LINK_MAX - nlink_bias(bi->bi_mode)) + return -BCH_ERR_too_many_links; bi->bi_nlink++; } diff --git a/libbcachefs/journal_reclaim.c b/libbcachefs/journal_reclaim.c index ae747c87..f7b0fdd9 100644 --- a/libbcachefs/journal_reclaim.c +++ b/libbcachefs/journal_reclaim.c @@ -766,6 +766,9 @@ static int bch2_journal_reclaim_thread(void *arg) set_freezable(); + kthread_wait_freezable(test_bit(BCH_FS_rw, &c->flags) || + kthread_should_stop()); + j->last_flushed = jiffies; while (!ret && !kthread_should_stop()) { @@ -826,8 +829,10 @@ int bch2_journal_reclaim_start(struct journal *j) struct task_struct *p; int ret; - if (j->reclaim_thread) + if (j->reclaim_thread) { + wake_up_process(j->reclaim_thread); return 0; + } p = kthread_create(bch2_journal_reclaim_thread, j, "bch-reclaim/%s", c->name); diff --git a/libbcachefs/sb-errors_format.h b/libbcachefs/sb-errors_format.h index 77e3fc92..fbdb7b7d 100644 --- a/libbcachefs/sb-errors_format.h +++ b/libbcachefs/sb-errors_format.h @@ -74,6 +74,7 @@ enum bch_fsck_flags { x(btree_root_bad_min_key, 60, 0) \ x(btree_root_bad_max_key, 61, 0) \ x(btree_node_read_error, 62, FSCK_AUTOFIX) \ + x(btree_node_topology_gap_between_nodes, 328, FSCK_AUTOFIX) \ x(btree_node_topology_bad_min_key, 63, FSCK_AUTOFIX) \ x(btree_node_topology_bad_max_key, 64, FSCK_AUTOFIX) \ x(btree_node_topology_bad_root_min_key, 323, FSCK_AUTOFIX) \ @@ -339,7 +340,7 @@ 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, 328, 0) + x(MAX, 329, 0) enum bch_sb_error_id { #define x(t, n, ...) BCH_FSCK_ERR_##t = n, diff --git a/libbcachefs/super.c b/libbcachefs/super.c index 5cd308a6..3038b5e6 100644 --- a/libbcachefs/super.c +++ b/libbcachefs/super.c @@ -564,15 +564,17 @@ static int __bch2_fs_read_write(struct bch_fs *c, bool early) * successfully marked the filesystem dirty */ - ret = bch2_journal_reclaim_start(&c->journal); - if (ret) - goto err; - set_bit(BCH_FS_rw, &c->flags); set_bit(BCH_FS_was_rw, &c->flags); enumerated_ref_start(&c->writes); + ret = bch2_journal_reclaim_start(&c->journal); + if (ret) { + bch_err_msg(c, ret, "error starting journal reclaim thread"); + goto err; + } + ret = bch2_copygc_start(c); if (ret) { bch_err_msg(c, ret, "error starting copygc thread"); @@ -852,7 +854,8 @@ int bch2_fs_init_rw(struct bch_fs *c) bch2_fs_btree_write_buffer_init(c) ?: bch2_fs_fs_io_buffered_init(c) ?: bch2_fs_io_write_init(c) ?: - bch2_fs_journal_init(&c->journal); + bch2_fs_journal_init(&c->journal) ?: + bch2_journal_reclaim_start(&c->journal); if (ret) return ret;