diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index 767cb6f809e78ace5943373611ad031d543f32ee..cbfaec5143d8e15d8c2172f426fb76380b75ff98 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -986,9 +986,8 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq, u64 last_seq = cur_seq, nr, seq; if (!list_empty(journal_entries)) - last_seq = le64_to_cpu(list_first_entry(journal_entries, - struct journal_replay, - list)->j.seq); + last_seq = le64_to_cpu(list_last_entry(journal_entries, + struct journal_replay, list)->j.last_seq); nr = cur_seq - last_seq; @@ -1017,8 +1016,10 @@ int bch2_fs_journal_start(struct journal *j, u64 cur_seq, list_for_each_entry(i, journal_entries, list) { seq = le64_to_cpu(i->j.seq); + BUG_ON(seq >= cur_seq); - BUG_ON(seq < last_seq || seq >= cur_seq); + if (seq < last_seq) + continue; journal_seq_pin(j, seq)->devs = i->devs; } diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 1724c80b323c8046cc00e69de02096106f041d48..a1bae99aeaab7739585055e53e99bc7ebfdf496f 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -40,19 +40,21 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca, list)->j.last_seq : 0; - /* Is this entry older than the range we need? */ - if (le64_to_cpu(j->seq) < le64_to_cpu(last_seq)) { - ret = JOURNAL_ENTRY_ADD_OUT_OF_RANGE; - goto out; - } + if (!c->opts.read_entire_journal) { + /* Is this entry older than the range we need? */ + if (le64_to_cpu(j->seq) < le64_to_cpu(last_seq)) { + ret = JOURNAL_ENTRY_ADD_OUT_OF_RANGE; + goto out; + } - /* Drop entries we don't need anymore */ - list_for_each_entry_safe(i, pos, jlist->head, list) { - if (le64_to_cpu(i->j.seq) >= le64_to_cpu(j->last_seq)) - break; - list_del(&i->list); - kvpfree(i, offsetof(struct journal_replay, j) + - vstruct_bytes(&i->j)); + /* Drop entries we don't need anymore */ + list_for_each_entry_safe(i, pos, jlist->head, list) { + if (le64_to_cpu(i->j.seq) >= le64_to_cpu(j->last_seq)) + break; + list_del(&i->list); + kvpfree(i, offsetof(struct journal_replay, j) + + vstruct_bytes(&i->j)); + } } list_for_each_entry_reverse(i, jlist->head, list) { diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index fe457117bf8950015af6a427f3be9bd1a4dbcb66..bc274918e18cee08c905a04c94513c4832e23f02 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -265,6 +265,11 @@ enum opt_type { OPT_BOOL(), \ NO_SB_OPT, false, \ NULL, "Don't free journal entries/keys after startup")\ + x(read_entire_journal, u8, \ + 0, \ + OPT_BOOL(), \ + NO_SB_OPT, false, \ + NULL, "Read all journal entries, not just dirty ones")\ x(noexcl, u8, \ OPT_MOUNT, \ OPT_BOOL(), \ diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 384dfb2279c17c66491587b716151769f7c6408a..26e5767aa5dee1a17eaa6546b075e158dd88946e 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -319,20 +319,30 @@ static struct journal_keys journal_keys_sort(struct list_head *journal_entries) struct journal_key *src, *dst; size_t nr_keys = 0; - list_for_each_entry(p, journal_entries, list) + if (list_empty(journal_entries)) + return keys; + + keys.journal_seq_base = + le64_to_cpu(list_last_entry(journal_entries, + struct journal_replay, list)->j.last_seq); + + list_for_each_entry(p, journal_entries, list) { + if (le64_to_cpu(p->j.seq) < keys.journal_seq_base) + continue; + for_each_jset_key(k, _n, entry, &p->j) nr_keys++; + } - keys.journal_seq_base = - le64_to_cpu(list_first_entry(journal_entries, - struct journal_replay, - list)->j.seq); keys.d = kvmalloc(sizeof(keys.d[0]) * nr_keys, GFP_KERNEL); if (!keys.d) goto err; - list_for_each_entry(p, journal_entries, list) + list_for_each_entry(p, journal_entries, list) { + if (le64_to_cpu(p->j.seq) < keys.journal_seq_base) + continue; + for_each_jset_key(k, _n, entry, &p->j) keys.d[keys.nr++] = (struct journal_key) { .btree_id = entry->btree_id, @@ -342,6 +352,7 @@ static struct journal_keys journal_keys_sort(struct list_head *journal_entries) keys.journal_seq_base, .journal_offset = k->_data - p->j._data, }; + } sort(keys.d, keys.nr, sizeof(keys.d[0]), journal_sort_key_cmp, NULL); @@ -568,6 +579,9 @@ verify_journal_entries_not_blacklisted_or_missing(struct bch_fs *c, int ret = 0; list_for_each_entry(i, journal, list) { + if (le64_to_cpu(i->j.seq) < start_seq) + continue; + fsck_err_on(seq != le64_to_cpu(i->j.seq), c, "journal entries %llu-%llu missing! (replaying %llu-%llu)", seq, le64_to_cpu(i->j.seq) - 1,