aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/transaction.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index a6eec9747c74..6b8338ec2464 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -204,6 +204,20 @@ static int add_transaction_credits(journal_t *journal, int blocks,
204 * attach this handle to a new transaction. 204 * attach this handle to a new transaction.
205 */ 205 */
206 atomic_sub(total, &t->t_outstanding_credits); 206 atomic_sub(total, &t->t_outstanding_credits);
207
208 /*
209 * Is the number of reserved credits in the current transaction too
210 * big to fit this handle? Wait until reserved credits are freed.
211 */
212 if (atomic_read(&journal->j_reserved_credits) + total >
213 journal->j_max_transaction_buffers) {
214 read_unlock(&journal->j_state_lock);
215 wait_event(journal->j_wait_reserved,
216 atomic_read(&journal->j_reserved_credits) + total <=
217 journal->j_max_transaction_buffers);
218 return 1;
219 }
220
207 wait_transaction_locked(journal); 221 wait_transaction_locked(journal);
208 return 1; 222 return 1;
209 } 223 }
@@ -262,20 +276,24 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
262 int rsv_blocks = 0; 276 int rsv_blocks = 0;
263 unsigned long ts = jiffies; 277 unsigned long ts = jiffies;
264 278
279 if (handle->h_rsv_handle)
280 rsv_blocks = handle->h_rsv_handle->h_buffer_credits;
281
265 /* 282 /*
266 * 1/2 of transaction can be reserved so we can practically handle 283 * Limit the number of reserved credits to 1/2 of maximum transaction
267 * only 1/2 of maximum transaction size per operation 284 * size and limit the number of total credits to not exceed maximum
285 * transaction size per operation.
268 */ 286 */
269 if (WARN_ON(blocks > journal->j_max_transaction_buffers / 2)) { 287 if ((rsv_blocks > journal->j_max_transaction_buffers / 2) ||
270 printk(KERN_ERR "JBD2: %s wants too many credits (%d > %d)\n", 288 (rsv_blocks + blocks > journal->j_max_transaction_buffers)) {
271 current->comm, blocks, 289 printk(KERN_ERR "JBD2: %s wants too many credits "
272 journal->j_max_transaction_buffers / 2); 290 "credits:%d rsv_credits:%d max:%d\n",
291 current->comm, blocks, rsv_blocks,
292 journal->j_max_transaction_buffers);
293 WARN_ON(1);
273 return -ENOSPC; 294 return -ENOSPC;
274 } 295 }
275 296
276 if (handle->h_rsv_handle)
277 rsv_blocks = handle->h_rsv_handle->h_buffer_credits;
278
279alloc_transaction: 297alloc_transaction:
280 if (!journal->j_running_transaction) { 298 if (!journal->j_running_transaction) {
281 /* 299 /*