Skip to content

Commit 8c3f25d

Browse files
committed
jbd2: don't give up looking for space so easily in __jbd2_log_wait_for_space
Commit 23f8b79 introducd a regression because it assumed that if there were no transactions ready to be checkpointed, that no progress could be made on making space available in the journal, and so the journal should be aborted. This assumption is false; it could be the case that simply calling jbd2_cleanup_journal_tail() will recover the necessary space, or, for small journals, the currently committing transaction could be responsible for chewing up the required space in the log, so we need to wait for the currently committing transaction to finish before trying to force a checkpoint operation. This patch fixes a bug reported by Mihai Harpau at: https://bugzilla.redhat.com/show_bug.cgi?id=469582 This patch fixes a bug reported by François Valenduc at: http://bugzilla.kernel.org/show_bug.cgi?id=11840 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: Duane Griffin <duaneg@dghda.com> Cc: Toshiyuki Okajima <toshi.okajima@jp.fujitsu.com>
1 parent e219cca commit 8c3f25d

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

fs/jbd2/checkpoint.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
116116
*/
117117
void __jbd2_log_wait_for_space(journal_t *journal)
118118
{
119-
int nblocks;
119+
int nblocks, space_left;
120120
assert_spin_locked(&journal->j_state_lock);
121121

122122
nblocks = jbd_space_needed(journal);
@@ -129,25 +129,43 @@ void __jbd2_log_wait_for_space(journal_t *journal)
129129
/*
130130
* Test again, another process may have checkpointed while we
131131
* were waiting for the checkpoint lock. If there are no
132-
* outstanding transactions there is nothing to checkpoint and
133-
* we can't make progress. Abort the journal in this case.
132+
* transactions ready to be checkpointed, try to recover
133+
* journal space by calling cleanup_journal_tail(), and if
134+
* that doesn't work, by waiting for the currently committing
135+
* transaction to complete. If there is absolutely no way
136+
* to make progress, this is either a BUG or corrupted
137+
* filesystem, so abort the journal and leave a stack
138+
* trace for forensic evidence.
134139
*/
135140
spin_lock(&journal->j_state_lock);
136141
spin_lock(&journal->j_list_lock);
137142
nblocks = jbd_space_needed(journal);
138-
if (__jbd2_log_space_left(journal) < nblocks) {
143+
space_left = __jbd2_log_space_left(journal);
144+
if (space_left < nblocks) {
139145
int chkpt = journal->j_checkpoint_transactions != NULL;
146+
tid_t tid = 0;
140147

148+
if (journal->j_committing_transaction)
149+
tid = journal->j_committing_transaction->t_tid;
141150
spin_unlock(&journal->j_list_lock);
142151
spin_unlock(&journal->j_state_lock);
143152
if (chkpt) {
144153
jbd2_log_do_checkpoint(journal);
154+
} else if (jbd2_cleanup_journal_tail(journal) == 0) {
155+
/* We were able to recover space; yay! */
156+
;
157+
} else if (tid) {
158+
jbd2_log_wait_commit(journal, tid);
145159
} else {
146-
printk(KERN_ERR "%s: no transactions\n",
147-
__func__);
160+
printk(KERN_ERR "%s: needed %d blocks and "
161+
"only had %d space available\n",
162+
__func__, nblocks, space_left);
163+
printk(KERN_ERR "%s: no way to get more "
164+
"journal space in %s\n", __func__,
165+
journal->j_devname);
166+
WARN_ON(1);
148167
jbd2_journal_abort(journal, 0);
149168
}
150-
151169
spin_lock(&journal->j_state_lock);
152170
} else {
153171
spin_unlock(&journal->j_list_lock);

0 commit comments

Comments
 (0)