aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuane Griffin <duaneg@dghda.com>2008-10-22 17:15:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 11:55:02 -0400
commitbe07c4ed4043ab8c26f222348136141335e47a2f (patch)
tree6c9dc77098a4cfe4212091aaecd2350c7b301733
parent9f818b4ac04f53458d0354950b4f229f54be4dbf (diff)
jbd: abort instead of waiting for nonexistent transactions
The __log_wait_for_space function sits in a loop checkpointing transactions until there is sufficient space free in the journal. However, if there are no transactions to be processed (e.g. because the free space calculation is wrong due to a corrupted filesystem) it will never progress. Check for space being required when no transactions are outstanding and abort the journal instead of endlessly looping. This patch fixes the bug reported by Sami Liedes at: http://bugzilla.kernel.org/show_bug.cgi?id=10976 Signed-off-by: Duane Griffin <duaneg@dghda.com> Tested-by: Sami Liedes <sliedes@cc.hut.fi> Cc: <linux-ext4@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/jbd/checkpoint.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index fe8521933243..1bd8d4acc6f2 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -127,14 +127,29 @@ void __log_wait_for_space(journal_t *journal)
127 127
128 /* 128 /*
129 * Test again, another process may have checkpointed while we 129 * Test again, another process may have checkpointed while we
130 * were waiting for the checkpoint lock 130 * were waiting for the checkpoint lock. If there are no
131 * outstanding transactions there is nothing to checkpoint and
132 * we can't make progress. Abort the journal in this case.
131 */ 133 */
132 spin_lock(&journal->j_state_lock); 134 spin_lock(&journal->j_state_lock);
135 spin_lock(&journal->j_list_lock);
133 nblocks = jbd_space_needed(journal); 136 nblocks = jbd_space_needed(journal);
134 if (__log_space_left(journal) < nblocks) { 137 if (__log_space_left(journal) < nblocks) {
138 int chkpt = journal->j_checkpoint_transactions != NULL;
139
140 spin_unlock(&journal->j_list_lock);
135 spin_unlock(&journal->j_state_lock); 141 spin_unlock(&journal->j_state_lock);
136 log_do_checkpoint(journal); 142 if (chkpt) {
143 log_do_checkpoint(journal);
144 } else {
145 printk(KERN_ERR "%s: no transactions\n",
146 __func__);
147 journal_abort(journal, 0);
148 }
149
137 spin_lock(&journal->j_state_lock); 150 spin_lock(&journal->j_state_lock);
151 } else {
152 spin_unlock(&journal->j_list_lock);
138 } 153 }
139 mutex_unlock(&journal->j_checkpoint_mutex); 154 mutex_unlock(&journal->j_checkpoint_mutex);
140 } 155 }