summaryrefslogtreecommitdiff
path: root/c_src/cmd_debug.c
diff options
context:
space:
mode:
authorThomas Bertschinger <tahbertschinger@gmail.com>2024-04-23 21:43:25 -0600
committerThomas Bertschinger <tahbertschinger@gmail.com>2024-05-07 21:29:32 -0400
commit16f2849433aafd33eae8539536169f86df124dfd (patch)
tree6431313e883f0bf3bc9eca36106c23bd48f3fb98 /c_src/cmd_debug.c
parentfbb223308961067a44d343cbca515aa12a745bde (diff)
WIP: bcachefs: new debug command
Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Diffstat (limited to 'c_src/cmd_debug.c')
-rw-r--r--c_src/cmd_debug.c115
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;
+}