2024-04-24 06:43:25 +03:00
|
|
|
#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 btree_trans *trans = bch2_trans_get(c);
|
|
|
|
struct btree_iter iter = { NULL };
|
2024-05-06 16:16:03 +03:00
|
|
|
struct printbuf buf = PRINTBUF;
|
2024-04-24 06:43:25 +03:00
|
|
|
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);
|
2024-05-06 16:16:03 +03:00
|
|
|
if ((ret = bkey_err(k))) {
|
|
|
|
fprintf(stderr, "bch2_btree_iter_peek() failed: %s\n", bch2_err_str(ret));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (!k.k || !bpos_eq(pos, k.k->p)) {
|
|
|
|
bch2_bpos_to_text(&buf, pos);
|
|
|
|
printf("no key at pos %s\n", buf.buf);
|
2024-04-24 06:43:25 +03:00
|
|
|
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 };
|
2024-05-06 16:16:03 +03:00
|
|
|
struct printbuf buf = PRINTBUF;
|
2024-04-24 06:43:25 +03:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
set_bit(BCH_FS_no_invalid_checks, &c->flags);
|
|
|
|
|
2024-05-06 16:16:03 +03:00
|
|
|
bch2_trans_iter_init(trans, &iter, u.id, pos, BTREE_ITER_ALL_SNAPSHOTS);
|
2024-04-24 06:43:25 +03:00
|
|
|
|
2024-05-06 16:16:03 +03:00
|
|
|
struct bkey_s_c k = bch2_btree_iter_peek(&iter);
|
|
|
|
if ((ret = bkey_err(k))) {
|
|
|
|
fprintf(stderr, "bch2_btree_iter_peek() failed: %s\n", bch2_err_str(ret));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (!k.k || !bpos_eq(pos, k.k->p)) {
|
|
|
|
bch2_bpos_to_text(&buf, pos);
|
|
|
|
printf("no key at pos %s\n", buf.buf);
|
|
|
|
ret = 1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (u.inode_bkey) {
|
|
|
|
if (k.k->type != KEY_TYPE_inode_v2 && k.k->type != KEY_TYPE_inode_v3) {
|
|
|
|
fprintf(stderr, "Wanted bch_inode_unpacked, got 'bch_%s'\n",
|
|
|
|
bch2_bkey_types[k.k->type]);
|
2024-04-24 06:43:25 +03:00
|
|
|
goto out;
|
|
|
|
}
|
2024-05-06 16:16:03 +03:00
|
|
|
} else if (u.bkey != k.k->type) {
|
|
|
|
fprintf(stderr, "Wanted type 'bch_%s', got type 'bch_%s'\n",
|
|
|
|
bch2_bkey_types[u.bkey], bch2_bkey_types[k.k->type]);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (u.inode_bkey) {
|
2024-04-24 06:43:25 +03:00
|
|
|
struct bch_inode_unpacked inode;
|
2024-05-06 16:16:03 +03:00
|
|
|
ret = bch2_inode_unpack(k, &inode);
|
|
|
|
if (ret != 0) {
|
|
|
|
fprintf(stderr, "bch2_inode_unpack() failed: %s\n", bch2_err_str(ret));
|
|
|
|
goto out;
|
|
|
|
}
|
2024-04-24 06:43:25 +03:00
|
|
|
|
|
|
|
write_field(&inode, u.size, u.offset, u.value);
|
|
|
|
|
|
|
|
ret = bch2_inode_write(trans, &iter, &inode) ?:
|
2024-05-06 16:16:03 +03:00
|
|
|
bch2_trans_commit(trans, NULL, NULL, 0);
|
2024-04-24 06:43:25 +03:00
|
|
|
if (ret != 0) {
|
2024-05-06 16:16:03 +03:00
|
|
|
fprintf(stderr, "inode update failed: %s\n", bch2_err_str(ret));
|
2024-04-24 06:43:25 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bch2_trans_unlock(trans);
|
|
|
|
|
2024-05-06 16:16:03 +03:00
|
|
|
struct bkey_i *n = bch2_bkey_make_mut_noupdate(trans, k);
|
|
|
|
if ((ret = PTR_ERR_OR_ZERO(n))) {
|
|
|
|
fprintf(stderr, "bch2_bkey_make_mut_noupdate() failed: %s\n",
|
|
|
|
bch2_err_str(ret));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_field(&n->v, u.size, u.offset, u.value);
|
2024-04-24 06:43:25 +03:00
|
|
|
|
2024-05-06 16:16:03 +03:00
|
|
|
ret = bch2_btree_insert(c, u.id, n, NULL, 0);
|
2024-04-24 06:43:25 +03:00
|
|
|
if (ret != 0) {
|
2024-05-06 16:16:03 +03:00
|
|
|
fprintf(stderr, "bch2_btree_insert() failed: %s\n", bch2_err_str(ret));
|
2024-04-24 06:43:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
bch2_trans_iter_exit(trans, &iter);
|
|
|
|
bch2_trans_put(trans);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|