]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/btree_io.c
Update bcachefs sources to bdf6d7c135 fixup! bcachefs: Kill journal buf bloom filter
[bcachefs-tools-debian] / libbcachefs / btree_io.c
index 08f5f6b865c6ed17bc7fe69d504a10b3e1e0699f..7a883922bb0914b4deff3abab20c79efadb79fe0 100644 (file)
@@ -767,14 +767,23 @@ fsck_err:
        return ret;
 }
 
+static int bset_key_invalid(struct bch_fs *c, struct btree *b,
+                           struct bkey_s_c k,
+                           bool updated_range, int rw,
+                           struct printbuf *err)
+{
+       return __bch2_bkey_invalid(c, k, btree_node_type(b), READ, err) ?:
+               (!updated_range ? bch2_bkey_in_btree_node(b, k, err) : 0) ?:
+               (rw == WRITE ? bch2_bkey_val_invalid(c, k, READ, err) : 0);
+}
+
 static int validate_bset_keys(struct bch_fs *c, struct btree *b,
                         struct bset *i, unsigned *whiteout_u64s,
                         int write, bool have_retry)
 {
        unsigned version = le16_to_cpu(i->version);
        struct bkey_packed *k, *prev = NULL;
-       struct printbuf buf1 = PRINTBUF;
-       struct printbuf buf2 = PRINTBUF;
+       struct printbuf buf = PRINTBUF;
        bool updated_range = b->key.k.type == KEY_TYPE_btree_ptr_v2 &&
                BTREE_PTR_RANGE_UPDATED(&bkey_i_to_btree_ptr_v2(&b->key)->v);
        int ret = 0;
@@ -783,7 +792,6 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
             k != vstruct_last(i);) {
                struct bkey_s u;
                struct bkey tmp;
-               const char *invalid;
 
                if (btree_err_on(bkey_next(k) > vstruct_last(i),
                                 BTREE_ERR_FIXABLE, c, NULL, b, i,
@@ -809,14 +817,15 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
 
                u = __bkey_disassemble(b, k, &tmp);
 
-               invalid = __bch2_bkey_invalid(c, u.s_c, btree_node_type(b)) ?:
-                       (!updated_range ?  bch2_bkey_in_btree_node(b, u.s_c) : NULL) ?:
-                       (write ? bch2_bkey_val_invalid(c, u.s_c) : NULL);
-               if (invalid) {
-                       printbuf_reset(&buf1);
-                       bch2_bkey_val_to_text(&buf1, c, u.s_c);
-                       btree_err(BTREE_ERR_FIXABLE, c, NULL, b, i,
-                                 "invalid bkey: %s\n%s", invalid, buf1.buf);
+               printbuf_reset(&buf);
+               if (bset_key_invalid(c, b, u.s_c, updated_range, write, &buf)) {
+                       printbuf_reset(&buf);
+                       pr_buf(&buf, "invalid bkey:  ");
+                       bset_key_invalid(c, b, u.s_c, updated_range, write, &buf);
+                       pr_buf(&buf, "\n  ");
+                       bch2_bkey_val_to_text(&buf, c, u.s_c);
+
+                       btree_err(BTREE_ERR_FIXABLE, c, NULL, b, i, "%s", buf.buf);
 
                        i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);
                        memmove_u64s_down(k, bkey_next(k),
@@ -832,16 +841,15 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
                if (prev && bkey_iter_cmp(b, prev, k) > 0) {
                        struct bkey up = bkey_unpack_key(b, prev);
 
-                       printbuf_reset(&buf1);
-                       bch2_bkey_to_text(&buf1, &up);
-                       printbuf_reset(&buf2);
-                       bch2_bkey_to_text(&buf2, u.k);
+                       printbuf_reset(&buf);
+                       pr_buf(&buf, "keys out of order: ");
+                       bch2_bkey_to_text(&buf, &up);
+                       pr_buf(&buf, " > ");
+                       bch2_bkey_to_text(&buf, u.k);
 
                        bch2_dump_bset(c, b, i, 0);
 
-                       if (btree_err(BTREE_ERR_FIXABLE, c, NULL, b, i,
-                                     "keys out of order: %s > %s",
-                                     buf1.buf, buf2.buf)) {
+                       if (btree_err(BTREE_ERR_FIXABLE, c, NULL, b, i, "%s", buf.buf)) {
                                i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);
                                memmove_u64s_down(k, bkey_next(k),
                                                  (u64 *) vstruct_end(i) - (u64 *) k);
@@ -853,8 +861,7 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
                k = bkey_next(k);
        }
 fsck_err:
-       printbuf_exit(&buf2);
-       printbuf_exit(&buf1);
+       printbuf_exit(&buf);
        return ret;
 }
 
@@ -873,6 +880,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
        unsigned u64s;
        unsigned blacklisted_written, nonblacklisted_written = 0;
        unsigned ptr_written = btree_ptr_sectors_written(&b->key);
+       struct printbuf buf = PRINTBUF;
        int ret, retry_read = 0, write = READ;
 
        b->version_ondisk = U16_MAX;
@@ -930,7 +938,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
                                        "error decrypting btree node: %i", ret))
                                goto fsck_err;
 
-                       btree_err_on(btree_node_is_extents(b) &&
+                       btree_err_on(btree_node_type_is_extents(btree_node_type(b)) &&
                                     !BTREE_NODE_NEW_EXTENT_OVERWRITE(b->data),
                                     BTREE_ERR_FATAL, c, NULL, b, NULL,
                                     "btree node does not have NEW_EXTENT_OVERWRITE set");
@@ -1065,17 +1073,20 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
        for (k = i->start; k != vstruct_last(i);) {
                struct bkey tmp;
                struct bkey_s u = __bkey_disassemble(b, k, &tmp);
-               const char *invalid = bch2_bkey_val_invalid(c, u.s_c);
 
-               if (invalid ||
+               printbuf_reset(&buf);
+
+               if (bch2_bkey_val_invalid(c, u.s_c, READ, &buf) ||
                    (bch2_inject_invalid_keys &&
                     !bversion_cmp(u.k->version, MAX_VERSION))) {
-                       struct printbuf buf = PRINTBUF;
+                       printbuf_reset(&buf);
 
+                       pr_buf(&buf, "invalid bkey: ");
+                       bch2_bkey_val_invalid(c, u.s_c, READ, &buf);
+                       pr_buf(&buf, "\n  ");
                        bch2_bkey_val_to_text(&buf, c, u.s_c);
-                       btree_err(BTREE_ERR_FIXABLE, c, NULL, b, i,
-                                 "invalid bkey %s: %s", buf, invalid);
-                       printbuf_exit(&buf);
+
+                       btree_err(BTREE_ERR_FIXABLE, c, NULL, b, i, "%s", buf.buf);
 
                        btree_keys_account_key_drop(&b->nr, 0, k);
 
@@ -1112,6 +1123,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca,
                set_btree_node_need_rewrite(b);
 out:
        mempool_free(iter, &c->fill_iter);
+       printbuf_exit(&buf);
        return retry_read;
 fsck_err:
        if (ret == BTREE_RETRY_READ) {
@@ -1546,7 +1558,7 @@ int bch2_btree_root_read(struct bch_fs *c, enum btree_id id,
                closure_sync(&cl);
        } while (ret);
 
-       b = bch2_btree_node_mem_alloc(c);
+       b = bch2_btree_node_mem_alloc(c, level != 0);
        bch2_btree_cache_cannibalize_unlock(c);
 
        BUG_ON(IS_ERR(b));
@@ -1626,6 +1638,8 @@ static void __btree_node_write_done(struct bch_fs *c, struct btree *b)
 
        if (new & (1U << BTREE_NODE_write_in_flight))
                __bch2_btree_node_write(c, b, BTREE_WRITE_ALREADY_STARTED);
+       else
+               wake_up_bit(&b->flags, BTREE_NODE_write_in_flight);
 }
 
 static void btree_node_write_done(struct bch_fs *c, struct btree *b)
@@ -1717,10 +1731,17 @@ static int validate_bset_for_write(struct bch_fs *c, struct btree *b,
                                   struct bset *i, unsigned sectors)
 {
        unsigned whiteout_u64s = 0;
+       struct printbuf buf = PRINTBUF;
        int ret;
 
-       if (bch2_bkey_invalid(c, bkey_i_to_s_c(&b->key), BKEY_TYPE_btree))
-               return -1;
+       ret = bch2_bkey_invalid(c, bkey_i_to_s_c(&b->key),
+                               BKEY_TYPE_btree, WRITE, &buf);
+
+       if (ret)
+               bch2_fs_inconsistent(c, "invalid btree node key before write: %s", buf.buf);
+       printbuf_exit(&buf);
+       if (ret)
+               return ret;
 
        ret = validate_bset_keys(c, b, i, &whiteout_u64s, WRITE, false) ?:
                validate_bset(c, NULL, b, i, b->written, sectors, WRITE, false);
@@ -1889,7 +1910,7 @@ do_write:
        BUG_ON(BSET_BIG_ENDIAN(i) != CPU_BIG_ENDIAN);
        BUG_ON(i->seq != b->data->keys.seq);
 
-       i->version = c->sb.version < bcachefs_metadata_version_new_versioning
+       i->version = c->sb.version < bcachefs_metadata_version_bkey_renumber
                ? cpu_to_le16(BCH_BSET_VERSION_OLD)
                : cpu_to_le16(c->sb.version);
        SET_BSET_OFFSET(i, b->written);
@@ -2081,30 +2102,33 @@ void bch2_btree_node_write(struct bch_fs *c, struct btree *b,
        }
 }
 
-static void __bch2_btree_flush_all(struct bch_fs *c, unsigned flag)
+static bool __bch2_btree_flush_all(struct bch_fs *c, unsigned flag)
 {
        struct bucket_table *tbl;
        struct rhash_head *pos;
        struct btree *b;
        unsigned i;
+       bool ret = false;
 restart:
        rcu_read_lock();
        for_each_cached_btree(b, c, tbl, i, pos)
                if (test_bit(flag, &b->flags)) {
                        rcu_read_unlock();
                        wait_on_bit_io(&b->flags, flag, TASK_UNINTERRUPTIBLE);
+                       ret = true;
                        goto restart;
-
                }
        rcu_read_unlock();
+
+       return ret;
 }
 
-void bch2_btree_flush_all_reads(struct bch_fs *c)
+bool bch2_btree_flush_all_reads(struct bch_fs *c)
 {
-       __bch2_btree_flush_all(c, BTREE_NODE_read_in_flight);
+       return __bch2_btree_flush_all(c, BTREE_NODE_read_in_flight);
 }
 
-void bch2_btree_flush_all_writes(struct bch_fs *c)
+bool bch2_btree_flush_all_writes(struct bch_fs *c)
 {
-       __bch2_btree_flush_all(c, BTREE_NODE_write_in_flight);
+       return __bch2_btree_flush_all(c, BTREE_NODE_write_in_flight);
 }