]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_gc.c
Update bcachefs sources to 17a344f265 bcachefs: Improve fsck for subvols/snapshots
[bcachefs-tools-debian] / libbcachefs / btree_gc.c
index b04f4705e4793592c859b3c2053121e0c65836f6..e260689ba830cc97f2c169754366baef967a4f43 100644 (file)
@@ -80,7 +80,7 @@ static int bch2_gc_check_topology(struct bch_fs *c,
                        bch2_topology_error(c);
 
                        if (bkey_deleted(&prev->k->k)) {
-                               pr_buf(&buf1, "start of node: ");
+                               prt_printf(&buf1, "start of node: ");
                                bch2_bpos_to_text(&buf1, node_start);
                        } else {
                                bch2_bkey_val_to_text(&buf1, c, bkey_i_to_s_c(prev->k));
@@ -264,7 +264,7 @@ static int btree_repair_node_boundaries(struct bch_fs *c, struct btree *b,
        int ret = 0;
 
        if (!prev) {
-               pr_buf(&buf1, "start of node: ");
+               prt_printf(&buf1, "start of node: ");
                bch2_bpos_to_text(&buf1, b->data->min_key);
        } else {
                bch2_bkey_val_to_text(&buf1, c, bkey_i_to_s_c(&prev->key));
@@ -395,6 +395,7 @@ again:
                        bch2_btree_node_evict(c, cur_k.k);
                        ret = bch2_journal_key_delete(c, b->c.btree_id,
                                                      b->c.level, cur_k.k->k.p);
+                       cur = NULL;
                        if (ret)
                                break;
                        continue;
@@ -413,6 +414,7 @@ again:
                        bch2_btree_node_evict(c, cur_k.k);
                        ret = bch2_journal_key_delete(c, b->c.btree_id,
                                                      b->c.level, cur_k.k->k.p);
+                       cur = NULL;
                        if (ret)
                                break;
                        continue;
@@ -562,7 +564,8 @@ static int bch2_check_fix_ptrs(struct bch_fs *c, enum btree_id btree_id,
                struct bucket *g = PTR_GC_BUCKET(ca, &p.ptr);
                enum bch_data_type data_type = bch2_bkey_ptr_data_type(*k, &entry->ptr);
 
-               if (fsck_err_on(!g->gen_valid, c,
+               if (c->opts.reconstruct_alloc ||
+                   fsck_err_on(!g->gen_valid, c,
                                "bucket %u:%zu data type %s ptr gen %u missing in alloc btree\n"
                                "while marking %s",
                                p.ptr.dev, PTR_BUCKET_NR(ca, &p.ptr),
@@ -746,13 +749,15 @@ found:
                if (level)
                        bch2_btree_node_update_key_early(c, btree_id, level - 1, *k, new);
 
-               printbuf_reset(&buf);
-               bch2_bkey_val_to_text(&buf, c, *k);
-               bch_info(c, "updated %s", buf.buf);
+               if (c->opts.verbose) {
+                       printbuf_reset(&buf);
+                       bch2_bkey_val_to_text(&buf, c, *k);
+                       bch_info(c, "updated %s", buf.buf);
 
-               printbuf_reset(&buf);
-               bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(new));
-               bch_info(c, "new key %s", buf.buf);
+                       printbuf_reset(&buf);
+                       bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(new));
+                       bch_info(c, "new key %s", buf.buf);
+               }
 
                *k = bkey_i_to_s_c(new);
        }
@@ -794,7 +799,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
                        atomic64_set(&c->key_version, k->k->version.lo);
        }
 
-       ret = __bch2_trans_do(trans, NULL, NULL, 0,
+       ret = commit_do(trans, NULL, NULL, 0,
                        bch2_mark_key(trans, old, *k, flags));
 fsck_err:
 err:
@@ -849,10 +854,7 @@ static int bch2_gc_btree(struct btree_trans *trans, enum btree_id btree_id,
        struct bch_fs *c = trans->c;
        struct btree_iter iter;
        struct btree *b;
-       unsigned depth = metadata_only                  ? 1
-               : bch2_expensive_debug_checks           ? 0
-               : !btree_node_type_needs_gc(btree_id)   ? 1
-               : 0;
+       unsigned depth = metadata_only ? 1 : 0;
        int ret = 0;
 
        gc_pos_set(c, gc_pos_btree(btree_id, POS_MIN, 0));
@@ -995,10 +997,7 @@ static int bch2_gc_btree_init(struct btree_trans *trans,
 {
        struct bch_fs *c = trans->c;
        struct btree *b;
-       unsigned target_depth = metadata_only           ? 1
-               : bch2_expensive_debug_checks           ? 0
-               : !btree_node_type_needs_gc(btree_id)   ? 1
-               : 0;
+       unsigned target_depth = metadata_only ? 1 : 0;
        struct printbuf buf = PRINTBUF;
        int ret = 0;
 
@@ -1181,29 +1180,28 @@ static int bch2_gc_done(struct bch_fs *c,
 {
        struct bch_dev *ca = NULL;
        struct printbuf buf = PRINTBUF;
-       bool verify = !metadata_only && (!initial ||
-                      (c->sb.compat & (1ULL << BCH_COMPAT_alloc_info)));
+       bool verify = !metadata_only &&
+               !c->opts.reconstruct_alloc &&
+               (!initial || (c->sb.compat & (1ULL << BCH_COMPAT_alloc_info)));
        unsigned i, dev;
        int ret = 0;
 
        percpu_down_write(&c->mark_lock);
 
 #define copy_field(_f, _msg, ...)                                      \
-       if (dst->_f != src->_f) {                                       \
-               if (verify)                                             \
-                       fsck_err(c, _msg ": got %llu, should be %llu"   \
-                               , ##__VA_ARGS__, dst->_f, src->_f);     \
-               dst->_f = src->_f;                                      \
-       }
+       if (dst->_f != src->_f &&                                       \
+           (!verify ||                                                 \
+            fsck_err(c, _msg ": got %llu, should be %llu"              \
+                     , ##__VA_ARGS__, dst->_f, src->_f)))              \
+               dst->_f = src->_f
 #define copy_stripe_field(_f, _msg, ...)                               \
-       if (dst->_f != src->_f) {                                       \
-               if (verify)                                             \
-                       fsck_err(c, "stripe %zu has wrong "_msg         \
-                               ": got %u, should be %u",               \
-                               iter.pos, ##__VA_ARGS__,                \
-                               dst->_f, src->_f);                      \
-               dst->_f = src->_f;                                      \
-       }
+       if (dst->_f != src->_f &&                                       \
+           (!verify ||                                                 \
+            fsck_err(c, "stripe %zu has wrong "_msg                    \
+                     ": got %u, should be %u",                         \
+                     iter.pos, ##__VA_ARGS__,                          \
+                     dst->_f, src->_f)))                               \
+               dst->_f = src->_f
 #define copy_dev_field(_f, _msg, ...)                                  \
        copy_field(_f, "dev %u has wrong " _msg, dev, ##__VA_ARGS__)
 #define copy_fs_field(_f, _msg, ...)                                   \
@@ -1381,7 +1379,8 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
                return 0;
 
 #define copy_bucket_field(_f)                                          \
-       if (fsck_err_on(new._f != gc._f, c,                             \
+       if (c->opts.reconstruct_alloc ||                                \
+           fsck_err_on(new._f != gc._f, c,                             \
                        "bucket %llu:%llu gen %u data type %s has wrong " #_f   \
                        ": got %u, should be %u",                       \
                        iter->pos.inode, iter->pos.offset,              \
@@ -1408,6 +1407,13 @@ static int bch2_alloc_write_key(struct btree_trans *trans,
 
        a->v = new;
 
+       /*
+        * The trigger normally makes sure this is set, but we're not running
+        * triggers:
+        */
+       if (a->v.data_type == BCH_DATA_cached && !a->v.io_time[READ])
+               a->v.io_time[READ] = max_t(u64, 1, atomic64_read(&c->io_clock[READ].now));
+
        ret = bch2_trans_update(trans, iter, &a->k_i, BTREE_TRIGGER_NORUN);
 fsck_err:
        return ret;
@@ -1432,7 +1438,7 @@ static int bch2_gc_alloc_done(struct bch_fs *c, bool metadata_only)
                        if (bkey_cmp(iter.pos, POS(ca->dev_idx, ca->mi.nbuckets)) >= 0)
                                break;
 
-                       ret = __bch2_trans_do(&trans, NULL, NULL,
+                       ret = commit_do(&trans, NULL, NULL,
                                              BTREE_INSERT_LAZY_RW,
                                        bch2_alloc_write_key(&trans, &iter,
                                                             metadata_only));
@@ -1586,7 +1592,7 @@ static int bch2_gc_reflink_done(struct bch_fs *c, bool metadata_only)
                        else
                                *bkey_refcount(new) = cpu_to_le64(r->refcount);
 
-                       ret = __bch2_trans_do(&trans, NULL, NULL, 0,
+                       ret = commit_do(&trans, NULL, NULL, 0,
                                __bch2_btree_insert(&trans, BTREE_ID_reflink, new));
                        kfree(new);
 
@@ -1699,7 +1705,7 @@ inconsistent:
                        for (i = 0; i < new->v.nr_blocks; i++)
                                stripe_blockcount_set(&new->v, i, m ? m->block_sectors[i] : 0);
 
-                       ret = __bch2_trans_do(&trans, NULL, NULL, 0,
+                       ret = commit_do(&trans, NULL, NULL, 0,
                                __bch2_btree_insert(&trans, BTREE_ID_reflink, &new->k_i));
                        kfree(new);
                }
@@ -1738,18 +1744,14 @@ static void bch2_gc_stripes_reset(struct bch_fs *c, bool metadata_only)
  */
 int bch2_gc(struct bch_fs *c, bool initial, bool metadata_only)
 {
-       u64 start_time = local_clock();
        unsigned iter = 0;
        int ret;
 
        lockdep_assert_held(&c->state_lock);
-       trace_gc_start(c);
 
        down_write(&c->gc_lock);
 
-       /* flush interior btree updates: */
-       closure_wait_event(&c->btree_interior_update_wait,
-                          !bch2_btree_interior_updates_nr_pending(c));
+       bch2_btree_interior_updates_flush(c);
 
        ret   = bch2_gc_start(c, metadata_only) ?:
                bch2_gc_alloc_start(c, metadata_only) ?:
@@ -1838,9 +1840,6 @@ out:
 
        up_write(&c->gc_lock);
 
-       trace_gc_end(c);
-       bch2_time_stats_update(&c->times[BCH_TIME_btree_gc], start_time);
-
        /*
         * At startup, allocations can happen directly instead of via the
         * allocator thread - issue wakeup in case they blocked on gc_lock:
@@ -1977,6 +1976,7 @@ int bch2_gc_gens(struct bch_fs *c)
        if (!mutex_trylock(&c->gc_gens_lock))
                return 0;
 
+       trace_gc_gens_start(c);
        down_read(&c->gc_lock);
        bch2_trans_init(&trans, c, 0, 0);
 
@@ -2012,7 +2012,7 @@ int bch2_gc_gens(struct bch_fs *c)
 
        for_each_btree_key(&trans, iter, BTREE_ID_alloc, POS_MIN,
                           BTREE_ITER_PREFETCH, k, ret) {
-               ret = __bch2_trans_do(&trans, NULL, NULL,
+               ret = commit_do(&trans, NULL, NULL,
                                      BTREE_INSERT_NOFAIL,
                                bch2_alloc_write_oldest_gen(&trans, &iter));
                if (ret) {
@@ -2028,6 +2028,7 @@ int bch2_gc_gens(struct bch_fs *c)
        c->gc_count++;
 
        bch2_time_stats_update(&c->times[BCH_TIME_btree_gc], start_time);
+       trace_gc_gens_end(c);
 err:
        for_each_member_device(ca, c, i) {
                kvfree(ca->oldest_gen);