cmd_list_journal: More filtering tweaks

New options:

-B: show blacklisted entries: previously show by default, but
    highlighted
-l: Show log-only entries, i.e. recovery, snapshot deletion messages
-o: Print entry offset for each subentry

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2025-06-13 12:39:48 -04:00
parent 26c3224b26
commit 792222046d

View File

@ -80,6 +80,9 @@ typedef struct {
} transaction_key_filter; } transaction_key_filter;
typedef struct { typedef struct {
bool blacklisted;
bool log;
bool print_offset;
bool filtering; bool filtering;
u64 btree_filter; u64 btree_filter;
transaction_msg_filter transaction; transaction_msg_filter transaction;
@ -113,18 +116,14 @@ static bool entry_matches_btree_filter(journal_filter f, struct jset_entry *entr
static bool transaction_matches_btree_filter(journal_filter f, static bool transaction_matches_btree_filter(journal_filter f,
struct jset_entry *entry, struct jset_entry *end) struct jset_entry *entry, struct jset_entry *end)
{ {
bool have_keys = false;
for (entry = vstruct_next(entry); for (entry = vstruct_next(entry);
entry != end; entry != end;
entry = vstruct_next(entry)) entry = vstruct_next(entry))
if (entry_is_print_key(entry)) { if (entry_is_print_key(entry) &&
if (entry_matches_btree_filter (f, entry)) entry_matches_btree_filter (f, entry))
return true; return true;
have_keys = true;
}
return !have_keys; return false;
} }
static bool bkey_matches_filter(transaction_key_filter f, static bool bkey_matches_filter(transaction_key_filter f,
@ -225,10 +224,14 @@ static bool should_print_transaction(journal_filter f,
{ {
BUG_ON(entry->type != BCH_JSET_ENTRY_log); BUG_ON(entry->type != BCH_JSET_ENTRY_log);
if (entry_is_log_only(entry, end)) if (!f.filtering)
return true; return true;
if (!transaction_matches_btree_filter(f, entry, end)) if (f.log && entry_is_log_only(entry, end))
return true;
if (f.btree_filter != ~0ULL &&
!transaction_matches_btree_filter(f, entry, end))
return false; return false;
if (f.transaction.f.nr && if (f.transaction.f.nr &&
@ -310,11 +313,14 @@ static void print_one_entry(struct printbuf *out,
bool highlight = entry_matches_transaction_filter(f.key, entry); bool highlight = entry_matches_transaction_filter(f.key, entry);
if (highlight) if (highlight)
fputs(RED, stdout); prt_str(out, RED);
unsigned indent = journal_entry_indent(entry); unsigned indent = journal_entry_indent(entry);
printbuf_indent_add(out, indent); printbuf_indent_add(out, indent);
if (f.print_offset)
prt_printf(out, "%4lu ", entry->_data - p->j._data);
if (!f.bkey_val && entry_is_print_key(entry)) if (!f.bkey_val && entry_is_print_key(entry))
bch2_journal_entry_keys_noval_to_text(out, entry); bch2_journal_entry_keys_noval_to_text(out, entry);
else { else {
@ -354,7 +360,8 @@ static void journal_replay_print(struct bch_fs *c,
} }
while (entry < end && while (entry < end &&
vstruct_next(entry) <= end) { vstruct_next(entry) <= end &&
entry_is_transaction_start(entry)) {
struct jset_entry *t_end = transaction_end(entry, end); struct jset_entry *t_end = transaction_end(entry, end);
if (should_print_transaction(f, entry, t_end)) { if (should_print_transaction(f, entry, t_end)) {
@ -366,9 +373,6 @@ static void journal_replay_print(struct bch_fs *c,
} }
entry = t_end; entry = t_end;
if (entry_is_non_transaction(entry))
break;
} }
while (entry < end && while (entry < end &&
@ -394,6 +398,9 @@ static void list_journal_usage(void)
"\n" "\n"
"Options:\n" "Options:\n"
" -a Read entire journal, not just dirty entries\n" " -a Read entire journal, not just dirty entries\n"
" -B, --blacklisted Include blacklisted entries\n"
" -l, --log When filtering, include log-only entries\n"
" -o, --offset Print offset of each subentry\n"
" -n, --nr-entries=nr Number of journal entries to print, starting from the most recent\n" " -n, --nr-entries=nr Number of journal entries to print, starting from the most recent\n"
" -b, --btree=(+|-)btree1,btree2 Filter keys matching or not updating btree(s)\n" " -b, --btree=(+|-)btree1,btree2 Filter keys matching or not updating btree(s)\n"
" -t, --transaction=(+|-)fn1,fn2 Filter transactions matching or not matching fn(s)\n" " -t, --transaction=(+|-)fn1,fn2 Filter transactions matching or not matching fn(s)\n"
@ -408,6 +415,9 @@ int cmd_list_journal(int argc, char *argv[])
{ {
static const struct option longopts[] = { static const struct option longopts[] = {
{ "nr-entries", required_argument, NULL, 'n' }, { "nr-entries", required_argument, NULL, 'n' },
{ "blacklisted", no_argument, NULL, 'B' },
{ "log", no_argument, NULL, 'l' },
{ "offset", no_argument, NULL, 'o' },
{ "btree", required_argument, NULL, 'b' }, { "btree", required_argument, NULL, 'b' },
{ "transaction", required_argument, NULL, 't' }, { "transaction", required_argument, NULL, 't' },
{ "key", required_argument, NULL, 'k' }, { "key", required_argument, NULL, 'k' },
@ -432,7 +442,7 @@ int cmd_list_journal(int argc, char *argv[])
opt_set(opts, retain_recovery_info ,true); opt_set(opts, retain_recovery_info ,true);
opt_set(opts, read_journal_only,true); opt_set(opts, read_journal_only,true);
while ((opt = getopt_long(argc, argv, "an:m:t:k:vh", while ((opt = getopt_long(argc, argv, "an:Blob:t:k:V:vh",
longopts, NULL)) != -1) longopts, NULL)) != -1)
switch (opt) { switch (opt) {
case 'a': case 'a':
@ -443,6 +453,15 @@ int cmd_list_journal(int argc, char *argv[])
die("error parsing nr_entries"); die("error parsing nr_entries");
opt_set(opts, read_entire_journal, true); opt_set(opts, read_entire_journal, true);
break; break;
case 'B':
f.blacklisted = true;
break;
case 'l':
f.log = true;
break;
case 'o':
f.print_offset = true;
break;
case 'b': case 'b':
ret = parse_sign(&optarg); ret = parse_sign(&optarg);
f.btree_filter = f.btree_filter =
@ -491,8 +510,16 @@ int cmd_list_journal(int argc, char *argv[])
struct genradix_iter iter; struct genradix_iter iter;
genradix_for_each(&c->journal_entries, iter, _p) { genradix_for_each(&c->journal_entries, iter, _p) {
p = *_p; p = *_p;
if (p && le64_to_cpu(p->j.seq) + nr_entries >= atomic64_read(&c->journal.seq)) if (!p)
journal_replay_print(c, f, p); continue;
if (le64_to_cpu(p->j.seq) + nr_entries < atomic64_read(&c->journal.seq))
continue;
if (!f.blacklisted &&
(p->ignore_blacklisted ||
bch2_journal_seq_is_blacklisted(c, le64_to_cpu(p->j.seq), false)))
continue;
journal_replay_print(c, f, p);
} }
bch2_fs_stop(c); bch2_fs_stop(c);