jbd2: fix infinite loop when recovering corrupt journal blocks
[firefly-linux-kernel-4.4.55.git] / fs / jbd2 / transaction.c
index 10f524c59ea88d48bf4f85f42e6fb2eca0d7a55b..ec34e11d685484b77050a584440f9a096d0f4e37 100644 (file)
@@ -517,10 +517,10 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
                   &transaction->t_outstanding_credits);
        if (atomic_dec_and_test(&transaction->t_updates))
                wake_up(&journal->j_wait_updates);
+       tid = transaction->t_tid;
        spin_unlock(&transaction->t_handle_lock);
 
        jbd_debug(2, "restarting handle %p\n", handle);
-       tid = transaction->t_tid;
        need_to_start = !tid_geq(journal->j_commit_request, tid);
        read_unlock(&journal->j_state_lock);
        if (need_to_start)
@@ -1151,7 +1151,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
                 * once a transaction -bzzz
                 */
                jh->b_modified = 1;
-               J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+               if (handle->h_buffer_credits <= 0) {
+                       ret = -ENOSPC;
+                       goto out_unlock_bh;
+               }
                handle->h_buffer_credits--;
        }
 
@@ -1234,7 +1237,6 @@ out_unlock_bh:
        jbd2_journal_put_journal_head(jh);
 out:
        JBUFFER_TRACE(jh, "exit");
-       WARN_ON(ret);   /* All errors are bugs, so dump the stack */
        return ret;
 }
 
@@ -1440,9 +1442,12 @@ int jbd2_journal_stop(handle_t *handle)
         * to perform a synchronous write.  We do this to detect the
         * case where a single process is doing a stream of sync
         * writes.  No point in waiting for joiners in that case.
+        *
+        * Setting max_batch_time to 0 disables this completely.
         */
        pid = current->pid;
-       if (handle->h_sync && journal->j_last_sync_writer != pid) {
+       if (handle->h_sync && journal->j_last_sync_writer != pid &&
+           journal->j_max_batch_time) {
                u64 commit_time, trans_time;
 
                journal->j_last_sync_writer = pid;