summaryrefslogtreecommitdiff
path: root/c_src
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
parentfbb223308961067a44d343cbca515aa12a745bde (diff)
WIP: bcachefs: new debug command
Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
Diffstat (limited to 'c_src')
-rw-r--r--c_src/cmd_debug.c115
-rw-r--r--c_src/cmds.h11
2 files changed, 126 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;
+}
diff --git a/c_src/cmds.h b/c_src/cmds.h
index 64267dc4..cb76f677 100644
--- a/c_src/cmds.h
+++ b/c_src/cmds.h
@@ -9,6 +9,14 @@
#include "tools-util.h"
+struct bkey_update {
+ enum btree_id id;
+ const char *bkey;
+ u64 offset;
+ u64 size;
+ u64 value;
+};
+
int cmd_format(int argc, char *argv[]);
int cmd_show_super(int argc, char *argv[]);
int cmd_reset_counters(int argc, char *argv[]);
@@ -54,6 +62,9 @@ int cmd_subvolume_snapshot(int argc, char *argv[]);
int cmd_fusemount(int argc, char *argv[]);
+int cmd_dump_bkey(struct bch_fs *, enum btree_id, struct bpos);
+int cmd_update_bkey(struct bch_fs *, struct bkey_update, struct bpos);
+
void bcachefs_usage(void);
int device_cmds(int argc, char *argv[]);
int fs_cmds(int argc, char *argv[]);