diff options
-rw-r--r-- | fs/jbd2/transaction.c | 36 |
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 | |||
279 | alloc_transaction: | 297 | alloc_transaction: |
280 | if (!journal->j_running_transaction) { | 298 | if (!journal->j_running_transaction) { |
281 | /* | 299 | /* |