.. | .. |
---|
106 | 106 | * for a checkpoint to free up some space in the log. |
---|
107 | 107 | */ |
---|
108 | 108 | void __jbd2_log_wait_for_space(journal_t *journal) |
---|
| 109 | +__acquires(&journal->j_state_lock) |
---|
| 110 | +__releases(&journal->j_state_lock) |
---|
109 | 111 | { |
---|
110 | 112 | int nblocks, space_left; |
---|
111 | 113 | /* assert_spin_locked(&journal->j_state_lock); */ |
---|
112 | 114 | |
---|
113 | | - nblocks = jbd2_space_needed(journal); |
---|
| 115 | + nblocks = journal->j_max_transaction_buffers; |
---|
114 | 116 | while (jbd2_log_space_left(journal) < nblocks) { |
---|
115 | 117 | write_unlock(&journal->j_state_lock); |
---|
116 | | - mutex_lock(&journal->j_checkpoint_mutex); |
---|
| 118 | + mutex_lock_io(&journal->j_checkpoint_mutex); |
---|
117 | 119 | |
---|
118 | 120 | /* |
---|
119 | 121 | * Test again, another process may have checkpointed while we |
---|
.. | .. |
---|
132 | 134 | return; |
---|
133 | 135 | } |
---|
134 | 136 | spin_lock(&journal->j_list_lock); |
---|
135 | | - nblocks = jbd2_space_needed(journal); |
---|
136 | 137 | space_left = jbd2_log_space_left(journal); |
---|
137 | 138 | if (space_left < nblocks) { |
---|
138 | 139 | int chkpt = journal->j_checkpoint_transactions != NULL; |
---|
.. | .. |
---|
276 | 277 | "JBD2: %s: Waiting for Godot: block %llu\n", |
---|
277 | 278 | journal->j_devname, (unsigned long long) bh->b_blocknr); |
---|
278 | 279 | |
---|
| 280 | + if (batch_count) |
---|
| 281 | + __flush_batch(journal, &batch_count); |
---|
279 | 282 | jbd2_log_start_commit(journal, tid); |
---|
| 283 | + /* |
---|
| 284 | + * jbd2_journal_commit_transaction() may want |
---|
| 285 | + * to take the checkpoint_mutex if JBD2_FLUSHED |
---|
| 286 | + * is set, jbd2_update_log_tail() called by |
---|
| 287 | + * jbd2_journal_commit_transaction() may also take |
---|
| 288 | + * checkpoint_mutex. So we need to temporarily |
---|
| 289 | + * drop it. |
---|
| 290 | + */ |
---|
| 291 | + mutex_unlock(&journal->j_checkpoint_mutex); |
---|
280 | 292 | jbd2_log_wait_commit(journal, tid); |
---|
281 | | - goto retry; |
---|
| 293 | + mutex_lock_io(&journal->j_checkpoint_mutex); |
---|
| 294 | + spin_lock(&journal->j_list_lock); |
---|
| 295 | + goto restart; |
---|
282 | 296 | } |
---|
283 | 297 | if (!buffer_dirty(bh)) { |
---|
284 | 298 | if (unlikely(buffer_write_io_error(bh)) && !result) |
---|
.. | .. |
---|
402 | 416 | * jbd2_cleanup_journal_tail() doesn't get called all that often. |
---|
403 | 417 | */ |
---|
404 | 418 | if (journal->j_flags & JBD2_BARRIER) |
---|
405 | | - blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); |
---|
| 419 | + blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS); |
---|
406 | 420 | |
---|
407 | 421 | return __jbd2_update_log_tail(journal, first_tid, blocknr); |
---|
408 | 422 | } |
---|