]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/bkey_methods.c
Update bcachefs sources to b964c6cba8 bcachefs: Change lockrestart_do() to always...
[bcachefs-tools-debian] / libbcachefs / bkey_methods.c
index 641169ef91b5c1b795bb5722ee97ffb1ed81db07..f8adbf4372764852a6838f9ed8d1aa540d2752c2 100644 (file)
@@ -84,7 +84,7 @@ static void key_type_inline_data_to_text(struct printbuf *out, struct bch_fs *c,
        .val_to_text    = key_type_inline_data_to_text, \
 }
 
-static const struct bkey_ops bch2_bkey_ops[] = {
+const struct bkey_ops bch2_bkey_ops[] = {
 #define x(name, nr) [KEY_TYPE_##name]  = bch2_bkey_ops_##name,
        BCH_BKEY_TYPES()
 #undef x
@@ -98,12 +98,51 @@ const char *bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k)
        return bch2_bkey_ops[k.k->type].key_invalid(c, k);
 }
 
+static unsigned bch2_key_types_allowed[] = {
+       [BKEY_TYPE_extents] =
+               (1U << KEY_TYPE_error)|
+               (1U << KEY_TYPE_cookie)|
+               (1U << KEY_TYPE_extent)|
+               (1U << KEY_TYPE_reservation)|
+               (1U << KEY_TYPE_reflink_p)|
+               (1U << KEY_TYPE_inline_data),
+       [BKEY_TYPE_inodes] =
+               (1U << KEY_TYPE_inode)|
+               (1U << KEY_TYPE_inode_generation),
+       [BKEY_TYPE_dirents] =
+               (1U << KEY_TYPE_hash_whiteout)|
+               (1U << KEY_TYPE_dirent),
+       [BKEY_TYPE_xattrs] =
+               (1U << KEY_TYPE_cookie)|
+               (1U << KEY_TYPE_hash_whiteout)|
+               (1U << KEY_TYPE_xattr),
+       [BKEY_TYPE_alloc] =
+               (1U << KEY_TYPE_alloc)|
+               (1U << KEY_TYPE_alloc_v2),
+       [BKEY_TYPE_quotas] =
+               (1U << KEY_TYPE_quota),
+       [BKEY_TYPE_stripes] =
+               (1U << KEY_TYPE_stripe),
+       [BKEY_TYPE_reflink] =
+               (1U << KEY_TYPE_reflink_v)|
+               (1U << KEY_TYPE_indirect_inline_data),
+       [BKEY_TYPE_btree] =
+               (1U << KEY_TYPE_btree_ptr)|
+               (1U << KEY_TYPE_btree_ptr_v2),
+};
+
 const char *__bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
                                enum btree_node_type type)
 {
+       unsigned key_types_allowed = (1U << KEY_TYPE_deleted)|
+               bch2_key_types_allowed[type] ;
+
        if (k.k->u64s < BKEY_U64s)
                return "u64s too small";
 
+       if (!(key_types_allowed & (1U << k.k->type)))
+               return "invalid key type for this btree";
+
        if (type == BKEY_TYPE_btree &&
            bkey_val_u64s(k.k) > BKEY_BTREE_PTR_VAL_U64s_MAX)
                return "value too big";
@@ -119,9 +158,16 @@ const char *__bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
                        return "nonzero size field";
        }
 
-       if (k.k->p.snapshot)
+       if (type != BKEY_TYPE_btree &&
+           !btree_type_has_snapshots(type) &&
+           k.k->p.snapshot)
                return "nonzero snapshot";
 
+       if (type != BKEY_TYPE_btree &&
+           btree_type_has_snapshots(type) &&
+           k.k->p.snapshot != U32_MAX)
+               return "invalid snapshot field";
+
        if (type != BKEY_TYPE_btree &&
            !bkey_cmp(k.k->p, POS_MAX))
                return "POS_MAX key";
@@ -138,10 +184,10 @@ const char *bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
 
 const char *bch2_bkey_in_btree_node(struct btree *b, struct bkey_s_c k)
 {
-       if (bkey_cmp(k.k->p, b->data->min_key) < 0)
+       if (bpos_cmp(k.k->p, b->data->min_key) < 0)
                return "key before start of btree node";
 
-       if (bkey_cmp(k.k->p, b->data->max_key) > 0)
+       if (bpos_cmp(k.k->p, b->data->max_key) > 0)
                return "key past end of btree node";
 
        return NULL;
@@ -165,9 +211,9 @@ void bch2_bkey_debugcheck(struct bch_fs *c, struct btree *b, struct bkey_s_c k)
 
 void bch2_bpos_to_text(struct printbuf *out, struct bpos pos)
 {
-       if (!bkey_cmp(pos, POS_MIN))
+       if (!bpos_cmp(pos, POS_MIN))
                pr_buf(out, "POS_MIN");
-       else if (!bkey_cmp(pos, POS_MAX))
+       else if (!bpos_cmp(pos, POS_MAX))
                pr_buf(out, "POS_MAX");
        else {
                if (pos.inode == U64_MAX)
@@ -223,7 +269,7 @@ void bch2_bkey_val_to_text(struct printbuf *out, struct bch_fs *c,
 {
        bch2_bkey_to_text(out, k.k);
 
-       if (k.k) {
+       if (bkey_val_bytes(k.k)) {
                pr_buf(out, ": ");
                bch2_val_to_text(out, c, k);
        }
@@ -246,24 +292,11 @@ bool bch2_bkey_normalize(struct bch_fs *c, struct bkey_s k)
                : false;
 }
 
-enum merge_result bch2_bkey_merge(struct bch_fs *c,
-                                 struct bkey_s l, struct bkey_s r)
+bool bch2_bkey_merge(struct bch_fs *c, struct bkey_s l, struct bkey_s_c r)
 {
        const struct bkey_ops *ops = &bch2_bkey_ops[l.k->type];
-       enum merge_result ret;
 
-       if (bch2_key_merging_disabled ||
-           !ops->key_merge ||
-           l.k->type != r.k->type ||
-           bversion_cmp(l.k->version, r.k->version) ||
-           bkey_cmp(l.k->p, bkey_start_pos(r.k)))
-               return BCH_MERGE_NOMERGE;
-
-       ret = ops->key_merge(c, l, r);
-
-       if (ret != BCH_MERGE_NOMERGE)
-               l.k->needs_whiteout |= r.k->needs_whiteout;
-       return ret;
+       return bch2_bkey_maybe_mergable(l.k, r.k) && ops->key_merge(c, l, r);
 }
 
 static const struct old_bkey_type {
@@ -310,14 +343,15 @@ void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
        const struct bkey_ops *ops;
        struct bkey uk;
        struct bkey_s u;
+       unsigned nr_compat = 5;
        int i;
 
        /*
         * Do these operations in reverse order in the write path:
         */
 
-       for (i = 0; i < 4; i++)
-       switch (!write ? i : 3 - i) {
+       for (i = 0; i < nr_compat; i++)
+       switch (!write ? i : nr_compat - 1 - i) {
        case 0:
                if (big_endian != CPU_BIG_ENDIAN)
                        bch2_bkey_swab_key(f, k);
@@ -351,6 +385,28 @@ void __bch2_bkey_compat(unsigned level, enum btree_id btree_id,
                }
                break;
        case 3:
+               if (version < bcachefs_metadata_version_snapshot &&
+                   (level || btree_type_has_snapshots(btree_id))) {
+                       struct bkey_i *u = packed_to_bkey(k);
+
+                       if (u) {
+                               u->k.p.snapshot = write
+                                       ? 0 : U32_MAX;
+                       } else {
+                               u64 min_packed = f->field_offset[BKEY_FIELD_SNAPSHOT];
+                               u64 max_packed = min_packed +
+                                       ~(~0ULL << f->bits_per_field[BKEY_FIELD_SNAPSHOT]);
+
+                               uk = __bch2_bkey_unpack_key(f, k);
+                               uk.p.snapshot = write
+                                       ? min_packed : min_t(u64, U32_MAX, max_packed);
+
+                               BUG_ON(!bch2_bkey_pack_key(k, &uk, f));
+                       }
+               }
+
+               break;
+       case 4:
                if (!bkey_packed(k)) {
                        u = bkey_i_to_s(packed_to_bkey(k));
                } else {