summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c_src/cmd_kill_btree_node.c29
-rw-r--r--c_src/cmd_list_journal.c74
2 files changed, 65 insertions, 38 deletions
diff --git a/c_src/cmd_kill_btree_node.c b/c_src/cmd_kill_btree_node.c
index 81dbdd4b..523b5b15 100644
--- a/c_src/cmd_kill_btree_node.c
+++ b/c_src/cmd_kill_btree_node.c
@@ -20,9 +20,8 @@ static void kill_btree_node_usage(void)
"Usage: bcachefs kill_btree_node [OPTION]... <devices>\n"
"\n"
"Options:\n"
- " -b (extents|inodes|dirents|xattrs) Btree to delete from\n"
- " -l level Levle to delete from (0 == leaves)\n"
- " -i index Index of btree node to kill\n"
+ " -n btree:level:idx Node to kill\n"
+ " -d dev Device index (default: kill all replicas)\n"
" -h Display this help and exit\n"
"Report bugs to <linux-bcachefs@vger.kernel.org>");
}
@@ -37,11 +36,11 @@ int cmd_kill_btree_node(int argc, char *argv[])
{
struct bch_opts opts = bch2_opts_empty();
DARRAY(struct kill_node) kill_nodes = {};
- int opt;
+ int opt, dev_idx = -1;
opt_set(opts, read_only, true);
- while ((opt = getopt(argc, argv, "n:h")) != -1)
+ while ((opt = getopt(argc, argv, "n:d:h")) != -1)
switch (opt) {
case 'n': {
char *p = optarg;
@@ -65,6 +64,10 @@ int cmd_kill_btree_node(int argc, char *argv[])
darray_push(&kill_nodes, n);
break;
}
+ case 'd':
+ if (kstrtoint(optarg, 10, &dev_idx))
+ die("invalid device index %s", optarg);
+ break;
case 'h':
kill_btree_node_usage();
exit(EXIT_SUCCESS);
@@ -96,20 +99,24 @@ int cmd_kill_btree_node(int argc, char *argv[])
int ret2 = 0;
if (!i->idx) {
- struct printbuf buf = PRINTBUF;
- bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
- bch_info(c, "killing btree node %s l=%u %s",
- bch2_btree_id_str(i->btree), i->level, buf.buf);
- printbuf_exit(&buf);
-
ret2 = 1;
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
bkey_for_each_ptr(ptrs, ptr) {
+ if (dev_idx >= 0 && ptr->dev != dev_idx)
+ continue;
+
struct bch_dev *ca = bch2_dev_tryget(c, ptr->dev);
if (!ca)
continue;
+ struct printbuf buf = PRINTBUF;
+ bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
+ bch_info(c, "killing btree node on dev %i %s l=%u\n %s",
+ ptr->dev,
+ bch2_btree_id_str(i->btree), i->level, buf.buf);
+ printbuf_exit(&buf);
+
int ret3 = pwrite(ca->disk_sb.bdev->bd_fd, zeroes,
c->opts.block_size, ptr->offset << 9);
bch2_dev_put(ca);
diff --git a/c_src/cmd_list_journal.c b/c_src/cmd_list_journal.c
index ca212c26..5f91337d 100644
--- a/c_src/cmd_list_journal.c
+++ b/c_src/cmd_list_journal.c
@@ -428,7 +428,8 @@ static void list_journal_usage(void)
"Usage: bcachefs list_journal [OPTION]... <devices>\n"
"\n"
"Options:\n"
- " -a Read entire journal, not just dirty entries\n"
+ " -a, --all Read entire journal, not just contiguous entries\n"
+ " -d, --dirty-only Only read dirty entries\n"
" -B, --blacklisted Include blacklisted entries\n"
" -F, --flush-only Only print flush entries/commits\n"
" -D, --datetime Print datetime entries only\n"
@@ -448,6 +449,8 @@ static void list_journal_usage(void)
int cmd_list_journal(int argc, char *argv[])
{
static const struct option longopts[] = {
+ { "all", no_argument, NULL, 'a' },
+ { "dirty-only", no_argument, NULL, 'd' },
{ "nr-entries", required_argument, NULL, 'n' },
{ "blacklisted", no_argument, NULL, 'B' },
{ "flush-only", no_argument, NULL, 'F' },
@@ -464,8 +467,9 @@ int cmd_list_journal(int argc, char *argv[])
{ NULL }
};
struct bch_opts opts = bch2_opts_empty();
- u32 nr_entries = U32_MAX;
+ u32 nr_entries = 0;
journal_filter f = { .btree_filter = ~0ULL, .bkey_val = true };
+ bool contiguous_only = true;
char *t;
int opt, ret;
@@ -478,12 +482,16 @@ int cmd_list_journal(int argc, char *argv[])
opt_set(opts, fix_errors, FSCK_FIX_yes);
opt_set(opts, retain_recovery_info ,true);
opt_set(opts, read_journal_only,true);
+ opt_set(opts, read_entire_journal, true);
- while ((opt = getopt_long(argc, argv, "an:BFDlLob:t:k:V:vh",
+ while ((opt = getopt_long(argc, argv, "adn:BFMDlLob:t:k:V:vh",
longopts, NULL)) != -1)
switch (opt) {
case 'a':
- opt_set(opts, read_entire_journal, true);
+ contiguous_only = false;
+ break;
+ case 'd':
+ opt_set(opts, read_entire_journal, false);
break;
case 'n':
if (kstrtouint(optarg, 10, &nr_entries))
@@ -555,37 +563,49 @@ int cmd_list_journal(int argc, char *argv[])
struct journal_replay *p, **_p;
struct genradix_iter iter;
- u64 seq = 0;
+ u64 min_seq_to_print = 0;
- genradix_for_each(&c->journal_entries, iter, _p) {
- p = *_p;
- if (!p)
- continue;
- if (le64_to_cpu(p->j.seq) + nr_entries < atomic64_read(&c->journal.seq))
- continue;
+ if (contiguous_only) {
+ u64 seq = 0;
+ genradix_for_each(&c->journal_entries, iter, _p) {
+ p = *_p;
+ if (!p)
+ continue;
- while (seq < le64_to_cpu(p->j.seq)) {
- while (seq < le64_to_cpu(p->j.seq) &&
- bch2_journal_seq_is_blacklisted(c, seq, false))
- seq++;
+ if (!seq)
+ seq = le64_to_cpu(p->j.seq);
- if (seq == le64_to_cpu(p->j.seq))
- break;
+ struct u64_range missing;
+ while ((missing = bch2_journal_entry_missing_range(c, seq, le64_to_cpu(p->j.seq))).start)
+ seq = min_seq_to_print = missing.end;
- u64 missing_start = seq;
+ seq = le64_to_cpu(p->j.seq) + 1;
+ }
+ }
- while (seq < le64_to_cpu(p->j.seq) &&
- !bch2_journal_seq_is_blacklisted(c, seq, false))
- seq++;
+ if (nr_entries)
+ min_seq_to_print = max_t(s64, min_seq_to_print,
+ atomic64_read(&c->journal.seq) - nr_entries);
- u64 missing_end = seq - 1;
+ u64 seq = 0;
+ genradix_for_each(&c->journal_entries, iter, _p) {
+ p = *_p;
+ if (!p)
+ continue;
- if (missing_start == missing_end)
- break;
+ if (le64_to_cpu(p->j.seq) < min_seq_to_print)
+ continue;
+
+ if (!seq)
+ seq = le64_to_cpu(p->j.seq);
- printf("missing %llu at %llu-%llu\n",
- missing_end - missing_start,
- missing_start, missing_end);
+ struct u64_range missing;
+ while ((missing = bch2_journal_entry_missing_range(c, seq, le64_to_cpu(p->j.seq))).start) {
+ printf("missing %llu entries at %llu-%llu%s\n",
+ missing.end - missing.start,
+ missing.start, missing.end - 1,
+ missing.end < c->journal.last_seq_ondisk ? " (not dirty)" : "");
+ seq = missing.end;
}
seq = le64_to_cpu(p->j.seq) + 1;