7 #include "libbcachefs.h"
9 #include "tools-util.h"
11 #include "libbcachefs/bcachefs.h"
12 #include "libbcachefs/btree_iter.h"
13 #include "libbcachefs/error.h"
14 #include "libbcachefs/journal_io.h"
15 #include "libbcachefs/journal_seq_blacklist.h"
16 #include "libbcachefs/super.h"
18 static void list_journal_usage(void)
20 puts("bcachefs list_journal - print contents of journal\n"
21 "Usage: bcachefs list_journal [OPTION]... <devices>\n"
24 " -a Read entire journal, not just dirty entries\n"
25 " -n Number of journal entries to print, starting from the most recent\n"
27 " -h Display this help and exit\n"
28 "Report bugs to <linux-bcachefs@vger.kernel.org>");
31 static void star_start_of_lines(char *buf)
38 while ((p = strstr(p, "\n ")))
42 int cmd_list_journal(int argc, char *argv[])
44 struct bch_opts opts = bch2_opts_empty();
45 u32 nr_entries = U32_MAX;
48 opt_set(opts, nochanges, true);
49 opt_set(opts, norecovery, true);
50 opt_set(opts, degraded, true);
51 opt_set(opts, errors, BCH_ON_ERROR_continue);
52 opt_set(opts, fix_errors, FSCK_OPT_YES);
53 opt_set(opts, keep_journal, true);
54 opt_set(opts, read_journal_only,true);
56 while ((opt = getopt(argc, argv, "an:vh")) != -1)
59 opt_set(opts, read_entire_journal, true);
62 nr_entries = kstrtouint(optarg, 10, &nr_entries);
63 opt_set(opts, read_entire_journal, true);
66 opt_set(opts, verbose, true);
75 die("Please supply device(s) to open");
77 struct bch_fs *c = bch2_fs_open(argv, argc, opts);
79 die("error opening %s: %s", argv[0], strerror(-PTR_ERR(c)));
81 struct journal_replay *p, **_p;
82 struct genradix_iter iter;
83 struct jset_entry *entry;
84 struct printbuf buf = PRINTBUF;
86 genradix_for_each(&c->journal_entries, iter, _p) {
91 if (le64_to_cpu(p->j.seq) + nr_entries < atomic64_read(&c->journal.seq))
95 bch2_journal_seq_is_blacklisted(c,
96 le64_to_cpu(p->j.seq), false);
99 printf("blacklisted ");
101 printf("journal entry %llu\n", le64_to_cpu(p->j.seq));
103 printbuf_reset(&buf);
110 le32_to_cpu(p->j.version),
111 le64_to_cpu(p->j.last_seq),
112 !JSET_NO_FLUSH(&p->j));
113 bch2_journal_ptrs_to_text(&buf, c, p);
116 star_start_of_lines(buf.buf);
117 printf("%s\n", buf.buf);
119 vstruct_for_each(&p->j, entry) {
120 printbuf_reset(&buf);
123 * log entries denote the start of a new transaction
126 if (entry->type == BCH_JSET_ENTRY_log && !entry->level)
128 printbuf_indent_add(&buf, 4);
129 bch2_journal_entry_to_text(&buf, c, entry);
132 star_start_of_lines(buf.buf);
133 printf("%s\n", buf.buf);
142 static void kill_btree_node_usage(void)
144 puts("bcachefs kill_btree_node - make btree nodes unreadable\n"
145 "Usage: bcachefs kill_btree_node [OPTION]... <devices>\n"
148 " -b (extents|inodes|dirents|xattrs) Btree to delete from\n"
149 " -l level Levle to delete from (0 == leaves)\n"
150 " -i index Index of btree node to kill\n"
151 " -h Display this help and exit\n"
152 "Report bugs to <linux-bcachefs@vger.kernel.org>");
155 int cmd_kill_btree_node(int argc, char *argv[])
157 struct bch_opts opts = bch2_opts_empty();
158 enum btree_id btree_id = 0;
163 opt_set(opts, read_only, true);
165 while ((opt = getopt(argc, argv, "b:l:i:h")) != -1)
168 btree_id = read_string_list_or_die(optarg,
169 bch2_btree_ids, "btree id");
172 if (kstrtouint(optarg, 10, &level) || level >= BTREE_MAX_DEPTH)
173 die("invalid level");
176 if (kstrtoull(optarg, 10, &node_index))
177 die("invalid index %s", optarg);
180 kill_btree_node_usage();
186 die("Please supply device(s)");
188 struct bch_fs *c = bch2_fs_open(argv, argc, opts);
190 die("error opening %s: %s", argv[0], strerror(-PTR_ERR(c)));
192 struct btree_trans trans;
193 struct btree_iter iter;
198 ret = posix_memalign(&zeroes, c->opts.block_size, c->opts.block_size);
200 die("error %s from posix_memalign", strerror(ret));
202 bch2_trans_init(&trans, c, 0, 0);
204 __for_each_btree_node(&trans, iter, btree_id, POS_MIN, 0, level, 0, b, ret) {
205 if (b->c.level != level)
209 struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key));
210 const struct bch_extent_ptr *ptr;
212 struct printbuf buf = PRINTBUF;
214 bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
215 bch_info(c, "killing btree node %s", buf.buf);
218 bkey_for_each_ptr(ptrs, ptr) {
219 struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
221 ret = pwrite(ca->disk_sb.bdev->bd_fd, zeroes,
222 c->opts.block_size, ptr->offset << 9);
223 if (ret != c->opts.block_size) {
224 bch_err(c, "pwrite error: expected %u got %i %s",
225 c->opts.block_size, ret, strerror(errno));
236 bch_err(c, "error %i walking btree nodes", ret);
238 bch_err(c, "node at specified index not found");
241 bch2_trans_iter_exit(&trans, &iter);
242 bch2_trans_exit(&trans);