]> git.sesse.net Git - bcachefs-tools-debian/blob - cmd_list_journal.c
New upstream release
[bcachefs-tools-debian] / cmd_list_journal.c
1 #include <fcntl.h>
2 #include <string.h>
3 #include <sys/stat.h>
4 #include <sys/types.h>
5
6 #include "cmds.h"
7 #include "libbcachefs.h"
8 #include "tools-util.h"
9
10 #include "libbcachefs/bcachefs.h"
11 #include "libbcachefs/btree_iter.h"
12 #include "libbcachefs/error.h"
13 #include "libbcachefs/journal_io.h"
14 #include "libbcachefs/journal_seq_blacklist.h"
15 #include "libbcachefs/super.h"
16
17 static void list_journal_usage(void)
18 {
19         puts("bcachefs list_journal - print contents of journal\n"
20              "Usage: bcachefs list_journal [OPTION]... <devices>\n"
21              "\n"
22              "Options:\n"
23              "  -a            Read entire journal, not just dirty entries\n"
24              "  -n            Number of journal entries to print, starting from the most recent\n"
25              "  -v            Verbose mode\n"
26              "  -h            Display this help and exit\n"
27              "Report bugs to <linux-bcachefs@vger.kernel.org>");
28 }
29
30 static void star_start_of_lines(char *buf)
31 {
32         char *p = buf;
33
34         if (*p == ' ')
35                 *p = '*';
36
37         while ((p = strstr(p, "\n ")))
38                 p[1] = '*';
39 }
40
41 int cmd_list_journal(int argc, char *argv[])
42 {
43         struct bch_opts opts = bch2_opts_empty();
44         u32 nr_entries = U32_MAX;
45         int opt;
46
47         opt_set(opts, nochanges,        true);
48         opt_set(opts, norecovery,       true);
49         opt_set(opts, degraded,         true);
50         opt_set(opts, errors,           BCH_ON_ERROR_continue);
51         opt_set(opts, fix_errors,       FSCK_OPT_YES);
52         opt_set(opts, keep_journal,     true);
53         opt_set(opts, read_journal_only,true);
54
55         while ((opt = getopt(argc, argv, "an:vh")) != -1)
56                 switch (opt) {
57                 case 'a':
58                         opt_set(opts, read_entire_journal, true);
59                         break;
60                 case 'n':
61                         nr_entries = kstrtouint(optarg, 10, &nr_entries);
62                         opt_set(opts, read_entire_journal, true);
63                         break;
64                 case 'v':
65                         opt_set(opts, verbose, true);
66                         break;
67                 case 'h':
68                         list_journal_usage();
69                         exit(EXIT_SUCCESS);
70                 }
71         args_shift(optind);
72
73         if (!argc)
74                 die("Please supply device(s) to open");
75
76         struct bch_fs *c = bch2_fs_open(argv, argc, opts);
77         if (IS_ERR(c))
78                 die("error opening %s: %s", argv[0], strerror(-PTR_ERR(c)));
79
80         struct journal_replay *p, **_p;
81         struct genradix_iter iter;
82         struct jset_entry *entry;
83         struct printbuf buf = PRINTBUF;
84
85         genradix_for_each(&c->journal_entries, iter, _p) {
86                 p = *_p;
87                 if (!p)
88                         continue;
89
90                 if (le64_to_cpu(p->j.seq) + nr_entries < atomic64_read(&c->journal.seq))
91                         continue;
92
93                 bool blacklisted =
94                         bch2_journal_seq_is_blacklisted(c,
95                                         le64_to_cpu(p->j.seq), false);
96
97                 if (blacklisted)
98                         printf("blacklisted ");
99
100                 printf("journal entry       %llu\n", le64_to_cpu(p->j.seq));
101
102                 printbuf_reset(&buf);
103
104                 prt_printf(&buf,
105                        "  version         %u\n"
106                        "  last seq        %llu\n"
107                        "  flush           %u\n"
108                        "  written at      ",
109                        le32_to_cpu(p->j.version),
110                        le64_to_cpu(p->j.last_seq),
111                        !JSET_NO_FLUSH(&p->j));
112                 bch2_journal_ptrs_to_text(&buf, c, p);
113
114                 if (blacklisted)
115                         star_start_of_lines(buf.buf);
116                 printf("%s\n", buf.buf);
117
118                 vstruct_for_each(&p->j, entry) {
119                         printbuf_reset(&buf);
120
121                         /*
122                          * log entries denote the start of a new transaction
123                          * commit:
124                          */
125                         if (entry->type == BCH_JSET_ENTRY_log && !entry->level)
126                                 prt_newline(&buf);
127                         printbuf_indent_add(&buf, 4);
128                         bch2_journal_entry_to_text(&buf, c, entry);
129
130                         if (blacklisted)
131                                 star_start_of_lines(buf.buf);
132                         printf("%s\n", buf.buf);
133                 }
134         }
135
136         printbuf_exit(&buf);
137         bch2_fs_stop(c);
138         return 0;
139 }