From 188b6d0c8ef1c02462a744b176557c27220112c9 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 22 Oct 2022 13:25:25 -0400 Subject: Update bcachefs sources to cd779e0cc5 bcachefs: Skip inode unpack/pack in bch2_extent_update() --- libbcachefs/inode.c | 165 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 143 insertions(+), 22 deletions(-) (limited to 'libbcachefs/inode.c') diff --git a/libbcachefs/inode.c b/libbcachefs/inode.c index 1f2782fc..1a0d2608 100644 --- a/libbcachefs/inode.c +++ b/libbcachefs/inode.c @@ -60,11 +60,10 @@ static int inode_decode_field(const u8 *in, const u8 *end, return bytes; } -void bch2_inode_pack(struct bch_fs *c, - struct bkey_inode_buf *packed, - const struct bch_inode_unpacked *inode) +static inline void bch2_inode_pack_inlined(struct bkey_inode_buf *packed, + const struct bch_inode_unpacked *inode) { - struct bkey_i_inode_v2 *k = &packed->inode; + struct bkey_i_inode_v3 *k = &packed->inode; u8 *out = k->v.fields; u8 *end = (void *) &packed[1]; u8 *last_nonzero_field = out; @@ -72,13 +71,17 @@ void bch2_inode_pack(struct bch_fs *c, unsigned bytes; int ret; - bkey_inode_v2_init(&packed->inode.k_i); + bkey_inode_v3_init(&packed->inode.k_i); packed->inode.k.p.offset = inode->bi_inum; packed->inode.v.bi_journal_seq = cpu_to_le64(inode->bi_journal_seq); packed->inode.v.bi_hash_seed = inode->bi_hash_seed; packed->inode.v.bi_flags = cpu_to_le64(inode->bi_flags); - packed->inode.v.bi_flags = cpu_to_le64(inode->bi_flags); - packed->inode.v.bi_mode = cpu_to_le16(inode->bi_mode); + packed->inode.v.bi_sectors = cpu_to_le64(inode->bi_sectors); + packed->inode.v.bi_size = cpu_to_le64(inode->bi_size); + packed->inode.v.bi_version = cpu_to_le64(inode->bi_version); + SET_INODEv3_MODE(&packed->inode.v, inode->bi_mode); + SET_INODEv3_FIELDS_START(&packed->inode.v, INODEv3_FIELDS_START_CUR); + #define x(_name, _bits) \ nr_fields++; \ @@ -99,7 +102,7 @@ void bch2_inode_pack(struct bch_fs *c, *out++ = 0; \ } - BCH_INODE_FIELDS() + BCH_INODE_FIELDS_v3() #undef x BUG_ON(out > end); @@ -110,7 +113,7 @@ void bch2_inode_pack(struct bch_fs *c, set_bkey_val_bytes(&packed->inode.k, bytes); memset_u64s_tail(&packed->inode.v, 0, bytes); - SET_INODEv2_NR_FIELDS(&k->v, nr_fields); + SET_INODEv3_NR_FIELDS(&k->v, nr_fields); if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG)) { struct bch_inode_unpacked unpacked; @@ -120,16 +123,25 @@ void bch2_inode_pack(struct bch_fs *c, BUG_ON(ret); BUG_ON(unpacked.bi_inum != inode->bi_inum); BUG_ON(unpacked.bi_hash_seed != inode->bi_hash_seed); + BUG_ON(unpacked.bi_sectors != inode->bi_sectors); + BUG_ON(unpacked.bi_size != inode->bi_size); + BUG_ON(unpacked.bi_version != inode->bi_version); BUG_ON(unpacked.bi_mode != inode->bi_mode); #define x(_name, _bits) if (unpacked._name != inode->_name) \ panic("unpacked %llu should be %llu", \ (u64) unpacked._name, (u64) inode->_name); - BCH_INODE_FIELDS() + BCH_INODE_FIELDS_v3() #undef x } } +void bch2_inode_pack(struct bkey_inode_buf *packed, + const struct bch_inode_unpacked *inode) +{ + bch2_inode_pack_inlined(packed, inode); +} + static noinline int bch2_inode_unpack_v1(struct bkey_s_c_inode inode, struct bch_inode_unpacked *unpacked) { @@ -157,7 +169,7 @@ static noinline int bch2_inode_unpack_v1(struct bkey_s_c_inode inode, unpacked->_name = field[1]; \ in += ret; - BCH_INODE_FIELDS() + BCH_INODE_FIELDS_v2() #undef x /* XXX: signal if there were more fields than expected? */ @@ -196,15 +208,66 @@ static int bch2_inode_unpack_v2(struct bch_inode_unpacked *unpacked, return -1; \ fieldnr++; - BCH_INODE_FIELDS() + BCH_INODE_FIELDS_v2() #undef x /* XXX: signal if there were more fields than expected? */ return 0; } -int bch2_inode_unpack(struct bkey_s_c k, - struct bch_inode_unpacked *unpacked) +static int bch2_inode_unpack_v3(struct bkey_s_c k, + struct bch_inode_unpacked *unpacked) +{ + struct bkey_s_c_inode_v3 inode = bkey_s_c_to_inode_v3(k); + const u8 *in = inode.v->fields; + const u8 *end = bkey_val_end(inode); + unsigned nr_fields = INODEv3_NR_FIELDS(inode.v); + unsigned fieldnr = 0; + int ret; + u64 v[2]; + + unpacked->bi_inum = inode.k->p.offset; + unpacked->bi_journal_seq= le64_to_cpu(inode.v->bi_journal_seq); + unpacked->bi_hash_seed = inode.v->bi_hash_seed; + unpacked->bi_flags = le64_to_cpu(inode.v->bi_flags); + unpacked->bi_sectors = le64_to_cpu(inode.v->bi_sectors); + unpacked->bi_size = le64_to_cpu(inode.v->bi_size); + unpacked->bi_version = le64_to_cpu(inode.v->bi_version); + unpacked->bi_mode = INODEv3_MODE(inode.v); + +#define x(_name, _bits) \ + if (fieldnr < nr_fields) { \ + ret = bch2_varint_decode_fast(in, end, &v[0]); \ + if (ret < 0) \ + return ret; \ + in += ret; \ + \ + if (_bits > 64) { \ + ret = bch2_varint_decode_fast(in, end, &v[1]); \ + if (ret < 0) \ + return ret; \ + in += ret; \ + } else { \ + v[1] = 0; \ + } \ + } else { \ + v[0] = v[1] = 0; \ + } \ + \ + unpacked->_name = v[0]; \ + if (v[1] || v[0] != unpacked->_name) \ + return -1; \ + fieldnr++; + + BCH_INODE_FIELDS_v3() +#undef x + + /* XXX: signal if there were more fields than expected? */ + return 0; +} + +static noinline int bch2_inode_unpack_slowpath(struct bkey_s_c k, + struct bch_inode_unpacked *unpacked) { switch (k.k->type) { case KEY_TYPE_inode: { @@ -243,6 +306,14 @@ int bch2_inode_unpack(struct bkey_s_c k, } } +int bch2_inode_unpack(struct bkey_s_c k, + struct bch_inode_unpacked *unpacked) +{ + if (likely(k.k->type == KEY_TYPE_inode_v3)) + return bch2_inode_unpack_v3(k, unpacked); + return bch2_inode_unpack_slowpath(k, unpacked); +} + int bch2_inode_peek(struct btree_trans *trans, struct btree_iter *iter, struct bch_inode_unpacked *inode, @@ -288,11 +359,29 @@ int bch2_inode_write(struct btree_trans *trans, if (IS_ERR(inode_p)) return PTR_ERR(inode_p); - bch2_inode_pack(trans->c, inode_p, inode); + bch2_inode_pack_inlined(inode_p, inode); inode_p->inode.k.p.snapshot = iter->snapshot; return bch2_trans_update(trans, iter, &inode_p->inode.k_i, 0); } +struct bkey_s_c bch2_inode_to_v3(struct btree_trans *trans, struct bkey_s_c k) +{ + struct bch_inode_unpacked u; + struct bkey_inode_buf *inode_p; + int ret; + + inode_p = bch2_trans_kmalloc(trans, sizeof(*inode_p)); + if (IS_ERR(inode_p)) + return bkey_s_c_err(PTR_ERR(inode_p)); + + ret = bch2_inode_unpack(k, &u); + if (ret) + return bkey_s_c_err(ret); + + bch2_inode_pack(inode_p, &u); + return bkey_i_to_s_c(&inode_p->inode.k_i); +} + static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err) { struct bch_inode_unpacked unpacked; @@ -307,7 +396,7 @@ static int __bch2_inode_invalid(struct bkey_s_c k, struct printbuf *err) return -EINVAL; } - if (bch2_inode_unpack(k, &unpacked)){ + if (bch2_inode_unpack(k, &unpacked)) { prt_printf(err, "invalid variable length fields"); return -EINVAL; } @@ -378,15 +467,48 @@ int bch2_inode_v2_invalid(const struct bch_fs *c, struct bkey_s_c k, return __bch2_inode_invalid(k, err); } -static void __bch2_inode_unpacked_to_text(struct printbuf *out, struct bch_inode_unpacked *inode) +int bch2_inode_v3_invalid(const struct bch_fs *c, struct bkey_s_c k, + int rw, struct printbuf *err) +{ + struct bkey_s_c_inode_v3 inode = bkey_s_c_to_inode_v3(k); + + if (bkey_val_bytes(k.k) < sizeof(*inode.v)) { + prt_printf(err, "incorrect value size (%zu < %zu)", + bkey_val_bytes(k.k), sizeof(*inode.v)); + return -EINVAL; + } + + if (INODEv3_FIELDS_START(inode.v) < INODEv3_FIELDS_START_INITIAL || + INODEv3_FIELDS_START(inode.v) > bkey_val_u64s(inode.k)) { + prt_printf(err, "invalid fields_start (got %llu, min %u max %zu)", + INODEv3_FIELDS_START(inode.v), + INODEv3_FIELDS_START_INITIAL, + bkey_val_u64s(inode.k)); + return -EINVAL; + } + + if (INODEv3_STR_HASH(inode.v) >= BCH_STR_HASH_NR) { + prt_printf(err, "invalid str hash type (%llu >= %u)", + INODEv3_STR_HASH(inode.v), BCH_STR_HASH_NR); + return -EINVAL; + } + + return __bch2_inode_invalid(k, err); +} + +static void __bch2_inode_unpacked_to_text(struct printbuf *out, + struct bch_inode_unpacked *inode) { - prt_printf(out, "mode %o flags %x journal_seq %llu", + prt_printf(out, "mode %o flags %x journal_seq %llu bi_size %llu bi_sectors %llu bi_version %llu", inode->bi_mode, inode->bi_flags, - inode->bi_journal_seq); + inode->bi_journal_seq, + inode->bi_size, + inode->bi_sectors, + inode->bi_version); #define x(_name, _bits) \ prt_printf(out, " "#_name " %llu", (u64) inode->_name); - BCH_INODE_FIELDS() + BCH_INODE_FIELDS_v3() #undef x } @@ -396,8 +518,7 @@ void bch2_inode_unpacked_to_text(struct printbuf *out, struct bch_inode_unpacked __bch2_inode_unpacked_to_text(out, inode); } -void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c, - struct bkey_s_c k) +void bch2_inode_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k) { struct bch_inode_unpacked inode; -- cgit v1.2.3