diff options
| author | Jeongjun Park <aha310510@gmail.com> | 2025-02-02 15:13:51 +0900 |
|---|---|---|
| committer | Kent Overstreet <kent.overstreet@linux.dev> | 2025-02-06 22:35:11 -0500 |
| commit | 2ef995df0ce592f665d312008dbe1ad1c4bcf87f (patch) | |
| tree | f24aa732b4218060fa97083c54967d8fe323acd9 /fs/bcachefs/journal.c | |
| parent | 6b37037d6d1b42083642340efcf80f7a30203039 (diff) | |
| download | lwn-2ef995df0ce592f665d312008dbe1ad1c4bcf87f.tar.gz lwn-2ef995df0ce592f665d312008dbe1ad1c4bcf87f.zip | |
bcachefs: fix deadlock in journal_entry_open()
In the previous commit b3d82c2f2761, code was added to prevent journal sequence
overflow. Among them, the code added to journal_entry_open() uses the
bch2_fs_fatal_err_on() function to handle errors.
However, __journal_res_get() , which calls journal_entry_open() , calls
journal_entry_open() while holding journal->lock , but bch2_fs_fatal_err_on()
internally tries to acquire journal->lock , which results in a deadlock.
So we need to add a locked helper to handle fatal errors even when the
journal->lock is held.
Fixes: b3d82c2f2761 ("bcachefs: Guard against journal seq overflow")
Signed-off-by: Jeongjun Park <aha310510@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/journal.c')
| -rw-r--r-- | fs/bcachefs/journal.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index cb2c3722f674..0a943a27ef44 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -319,6 +319,16 @@ void bch2_journal_halt(struct journal *j) spin_unlock(&j->lock); } +void bch2_journal_halt_locked(struct journal *j) +{ + lockdep_assert_held(&j->lock); + + __journal_entry_close(j, JOURNAL_ENTRY_ERROR_VAL, true); + if (!j->err_seq) + j->err_seq = journal_cur_seq(j); + journal_wake(j); +} + static bool journal_entry_want_write(struct journal *j) { bool ret = !journal_entry_is_open(j) || @@ -381,9 +391,12 @@ static int journal_entry_open(struct journal *j) if (nr_unwritten_journal_entries(j) == ARRAY_SIZE(j->buf)) return JOURNAL_ERR_max_in_flight; - if (bch2_fs_fatal_err_on(journal_cur_seq(j) >= JOURNAL_SEQ_MAX, - c, "cannot start: journal seq overflow")) + if (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"); return JOURNAL_ERR_insufficient_devices; /* -EROFS */ + } BUG_ON(!j->cur_entry_sectors); |
