#include "bcachefs.h"
#include "bkey.h"
+#include "bkey_methods.h"
#include "bset.h"
#include "util.h"
+#undef EBUG_ON
+
+#ifdef DEBUG_BKEYS
+#define EBUG_ON(cond) BUG_ON(cond)
+#else
+#define EBUG_ON(cond)
+#endif
+
const struct bkey_format bch2_bkey_format_current = BKEY_FORMAT_CURRENT;
struct bkey __bch2_bkey_unpack_key(const struct bkey_format *,
const struct bkey_format *format) {}
#endif
-int bch2_bkey_to_text(char *buf, size_t size, const struct bkey *k)
-{
- char *out = buf, *end = buf + size;
-
-#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
-
- p("u64s %u type %u %llu:%llu snap %u len %u ver %llu",
- k->u64s, k->type, k->p.inode, k->p.offset,
- k->p.snapshot, k->size, k->version.lo);
-
- BUG_ON(bkey_packed(k));
-
- switch (k->type) {
- case KEY_TYPE_DELETED:
- p(" deleted");
- break;
- case KEY_TYPE_DISCARD:
- p(" discard");
- break;
- case KEY_TYPE_ERROR:
- p(" error");
- break;
- case KEY_TYPE_COOKIE:
- p(" cookie");
- break;
- }
-#undef p
-
- return out - buf;
-}
-
struct pack_state {
const struct bkey_format *format;
unsigned bits; /* bits remaining in current word */
return out;
}
-#ifndef HAVE_BCACHE_COMPILED_UNPACK
+#ifndef HAVE_BCACHEFS_COMPILED_UNPACK
struct bpos __bkey_unpack_pos(const struct bkey_format *format,
const struct bkey_packed *in)
{
* Extents - we have to guarantee that if an extent is packed, a trimmed
* version will also pack:
*/
- if (bkey_start_offset(in) < format->field_offset[BKEY_FIELD_OFFSET])
+ if (bkey_start_offset(in) <
+ le64_to_cpu(format->field_offset[BKEY_FIELD_OFFSET]))
return false;
pack_state_finish(&state, out);
unsigned i, bits = KEY_PACKED_BITS_START;
if (f->nr_fields != BKEY_NR_FIELDS)
- return "invalid format: incorrect number of fields";
+ return "incorrect number of fields";
for (i = 0; i < f->nr_fields; i++) {
u64 field_offset = le64_to_cpu(f->field_offset[i]);
if (f->bits_per_field[i] > 64)
- return "invalid format: field too large";
+ return "field too large";
if (field_offset &&
(f->bits_per_field[i] == 64 ||
(field_offset + ((1ULL << f->bits_per_field[i]) - 1) <
field_offset)))
- return "invalid format: offset + bits overflow";
+ return "offset + bits overflow";
bits += f->bits_per_field[i];
}
if (f->key_u64s != DIV_ROUND_UP(bits, 64))
- return "invalid format: incorrect key_u64s";
+ return "incorrect key_u64s";
return NULL;
}
unsigned dst_offset, unsigned dst_size,
bool *eax_zeroed)
{
- unsigned byte = format->key_u64s * sizeof(u64);
unsigned bits = format->bits_per_field[field];
- u64 offset = format->field_offset[field];
- unsigned i, bit_offset = 0;
- unsigned shl, shr;
+ u64 offset = le64_to_cpu(format->field_offset[field]);
+ unsigned i, byte, bit_offset, align, shl, shr;
if (!bits && !offset) {
if (!*eax_zeroed) {
return out;
}
+ bit_offset = format->key_u64s * 64;
for (i = 0; i <= field; i++)
- bit_offset += format->bits_per_field[i];
+ bit_offset -= format->bits_per_field[i];
- byte -= DIV_ROUND_UP(bit_offset, 8);
- bit_offset = round_up(bit_offset, 8) - bit_offset;
+ byte = bit_offset / 8;
+ bit_offset -= byte * 8;
*eax_zeroed = false;
/* movzx eax, WORD PTR [rsi + imm8] */
I4(0x0f, 0xb7, 0x46, byte);
} else if (bit_offset + bits <= 32) {
+ align = min(4 - DIV_ROUND_UP(bit_offset + bits, 8), byte & 3);
+ byte -= align;
+ bit_offset += align * 8;
+
+ BUG_ON(bit_offset + bits > 32);
+
/* mov eax, [rsi + imm8] */
I3(0x8b, 0x46, byte);
out += 4;
}
} else if (bit_offset + bits <= 64) {
+ align = min(8 - DIV_ROUND_UP(bit_offset + bits, 8), byte & 7);
+ byte -= align;
+ bit_offset += align * 8;
+
+ BUG_ON(bit_offset + bits > 64);
+
/* mov rax, [rsi + imm8] */
I4(0x48, 0x8b, 0x46, byte);
I4(0x48, 0xc1, 0xe8, shr);
}
} else {
+ align = min(4 - DIV_ROUND_UP(bit_offset + bits, 8), byte & 3);
+ byte -= align;
+ bit_offset += align * 8;
+
+ BUG_ON(bit_offset + bits > 96);
+
/* mov rax, [rsi + byte] */
I4(0x48, 0x8b, 0x46, byte);