diff options
Diffstat (limited to 'c_src/cmd_debug.c')
-rw-r--r-- | c_src/cmd_debug.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/c_src/cmd_debug.c b/c_src/cmd_debug.c new file mode 100644 index 00000000..9d5def1a --- /dev/null +++ b/c_src/cmd_debug.c @@ -0,0 +1,115 @@ +#include <stdio.h> + +#include "libbcachefs/bkey_types.h" +#include "libbcachefs/btree_update.h" +#include "libbcachefs/printbuf.h" +#include "libbcachefs/inode.h" + +#include "cmds.h" + +void write_field(void *base, u64 size, u64 offset, u64 value) +{ + u8 *field8; + u16 *field16; + u32 *field32; + u64 *field64; + + switch (size) { + case 1: + field8 = (u8 *) base + offset; + *field8 = (u8) value; + break; + case 2: + field16 = (u16 *) ((u8 *) base + offset); + *field16 = (u16) value; + break; + case 4: + field32 = (u32 *) ((u8 *) base + offset); + *field32 = (u32) value; + break; + case 8: + field64 = (u64 *) ((u8 *) base + offset); + *field64 = value; + break; + default: + fprintf(stderr, "can't handle size %llu\n", size); + } +} + +int cmd_dump_bkey(struct bch_fs *c, enum btree_id id, struct bpos pos) +{ + struct printbuf buf = PRINTBUF; + struct btree_trans *trans = bch2_trans_get(c); + struct btree_iter iter = { NULL }; + int ret = 0; + + bch2_trans_iter_init(trans, &iter, id, pos, BTREE_ITER_ALL_SNAPSHOTS); + + struct bkey_s_c k = bch2_btree_iter_peek(&iter); + if (!bpos_eq(pos, k.k->p)) { + printf("no such key\n"); + ret = 1; + goto out; + } + + bch2_bkey_val_to_text(&buf, c, k); + printf("%s\n", buf.buf); + +out: + bch2_trans_iter_exit(trans, &iter); + bch2_trans_put(trans); + + return ret; +} + +int cmd_update_bkey(struct bch_fs *c, struct bkey_update u, struct bpos pos) +{ + struct btree_trans *trans = bch2_trans_get(c); + struct btree_iter iter = { NULL }; + int ret = 0; + + set_bit(BCH_FS_no_invalid_checks, &c->flags); + + if (!strcmp(u.bkey, "bch_inode_unpacked")) { + bch2_trans_iter_init(trans, &iter, BTREE_ID_inodes, pos, + BTREE_ITER_ALL_SNAPSHOTS); + + struct bkey_s_c k = bch2_btree_iter_peek(&iter); + if (bkey_err(k)) { + // TODO: is this proper error handling? + printf("error getting key: %s\n", bch2_err_str(PTR_ERR(k.k))); + ret = 1; + goto out; + } + struct bch_inode_unpacked inode; + // TODO: check error + bch2_inode_unpack(k, &inode); + + write_field(&inode, u.size, u.offset, u.value); + + ret = bch2_inode_write(trans, &iter, &inode) ?: + bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_invalid_checks); + if (ret != 0) { + printf("ret = %s (%d)\n", bch2_err_str(ret), ret); + } + } else { + // TODO can this return an error? + struct bkey_i *k = bch2_bkey_get_mut(trans, &iter, u.id, pos, + BTREE_ITER_ALL_SNAPSHOTS); + // TODO: check bkey type to confirm it matches specified type? + bch2_trans_unlock(trans); + + write_field(&k->v, u.size, u.offset, u.value); + + ret = bch2_btree_insert(c, u.id, k, NULL, BCH_TRANS_COMMIT_no_invalid_checks); + if (ret != 0) { + printf("ret = %s (%d)\n", bch2_err_str(ret), ret); + } + } + +out: + bch2_trans_iter_exit(trans, &iter); + bch2_trans_put(trans); + + return ret; +} |