Commit 521f9584 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Ensure we don't use a blacklisted journal seq



Different versions differ on the size of the blacklist range; it is
theoretically possible that we could end up with blacklisted journal
sequence numbers newer than the newest seq we find in the journal, and
pick a new start seq that's blacklisted.

Explicitly check for this in bch2_fs_journal_start().

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 9b133c0d
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -415,7 +415,7 @@ static int journal_entry_open(struct journal *j)
	if (atomic64_read(&j->seq) - j->seq_write_started == JOURNAL_STATE_BUF_NR)
		return -BCH_ERR_journal_max_open;

	if (journal_cur_seq(j) >= JOURNAL_SEQ_MAX) {
	if (unlikely(journal_cur_seq(j) >= JOURNAL_SEQ_MAX)) {
		bch_err(c, "cannot start: journal seq overflow");
		if (bch2_fs_emergency_read_only_locked(c))
			bch_err(c, "fatal error - emergency read only");
@@ -459,6 +459,14 @@ static int journal_entry_open(struct journal *j)
	atomic64_inc(&j->seq);
	journal_pin_list_init(fifo_push_ref(&j->pin), 1);

	if (unlikely(bch2_journal_seq_is_blacklisted(c, journal_cur_seq(j), false))) {
		bch_err(c, "attempting to open blacklisted journal seq %llu",
			journal_cur_seq(j));
		if (bch2_fs_emergency_read_only_locked(c))
			bch_err(c, "fatal error - emergency read only");
		return -BCH_ERR_journal_shutdown;
	}

	BUG_ON(j->pin.back - 1 != atomic64_read(&j->seq));

	BUG_ON(j->buf + (journal_cur_seq(j) & JOURNAL_BUF_MASK) != buf);
@@ -1415,6 +1423,13 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq)
	bool had_entries = false;
	u64 last_seq = cur_seq, nr, seq;

	/*
	 *
	 * XXX pick most recent non blacklisted sequence number
	 */

	cur_seq = max(cur_seq, bch2_journal_last_blacklisted_seq(c));

	if (cur_seq >= JOURNAL_SEQ_MAX) {
		bch_err(c, "cannot start: journal seq overflow");
		return -EINVAL;
+10 −0
Original line number Diff line number Diff line
@@ -130,6 +130,16 @@ bool bch2_journal_seq_is_blacklisted(struct bch_fs *c, u64 seq,
	return true;
}

u64 bch2_journal_last_blacklisted_seq(struct bch_fs *c)
{
	struct journal_seq_blacklist_table *t = c->journal_seq_blacklist_table;

	if (!t || !t->nr)
		return 0;

	return t->entries[eytzinger0_last(t->nr)].end - 1;
}

int bch2_blacklist_table_initialize(struct bch_fs *c)
{
	struct bch_sb_field_journal_seq_blacklist *bl =
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ blacklist_nr_entries(struct bch_sb_field_journal_seq_blacklist *bl)
}

bool bch2_journal_seq_is_blacklisted(struct bch_fs *, u64, bool);
u64 bch2_journal_last_blacklisted_seq(struct bch_fs *);
int bch2_journal_seq_blacklist_add(struct bch_fs *c, u64, u64);
int bch2_blacklist_table_initialize(struct bch_fs *);