summaryrefslogtreecommitdiff
path: root/c_src/cmd_debug.c
blob: 9d5def1a8742cafbc617ee69e982de3fb89f1f3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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;
}