diff options
-rw-r--r-- | fs/ext4/ext4_jbd2.c | 2 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 6 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 2 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 328 | ||||
-rw-r--r-- | include/linux/jbd2.h | 28 |
5 files changed, 273 insertions, 93 deletions
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 451eb4045330..bd25e782ec6b 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
@@ -62,7 +62,7 @@ handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line, | |||
62 | ext4_abort(sb, "Detected aborted journal"); | 62 | ext4_abort(sb, "Detected aborted journal"); |
63 | return ERR_PTR(-EROFS); | 63 | return ERR_PTR(-EROFS); |
64 | } | 64 | } |
65 | return jbd2__journal_start(journal, nblocks, GFP_NOFS, type, line); | 65 | return jbd2__journal_start(journal, nblocks, 0, GFP_NOFS, type, line); |
66 | } | 66 | } |
67 | 67 | ||
68 | int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) | 68 | int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index d73a0d808ec1..cfbce48adc0b 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -523,6 +523,12 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
523 | */ | 523 | */ |
524 | jbd2_journal_switch_revoke_table(journal); | 524 | jbd2_journal_switch_revoke_table(journal); |
525 | 525 | ||
526 | /* | ||
527 | * Reserved credits cannot be claimed anymore, free them | ||
528 | */ | ||
529 | atomic_sub(atomic_read(&journal->j_reserved_credits), | ||
530 | &commit_transaction->t_outstanding_credits); | ||
531 | |||
526 | trace_jbd2_commit_flushing(journal, commit_transaction); | 532 | trace_jbd2_commit_flushing(journal, commit_transaction); |
527 | stats.run.rs_flushing = jiffies; | 533 | stats.run.rs_flushing = jiffies; |
528 | stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked, | 534 | stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked, |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index f43f97ba002e..70990d682a0c 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -1030,6 +1030,7 @@ static journal_t * journal_init_common (void) | |||
1030 | init_waitqueue_head(&journal->j_wait_done_commit); | 1030 | init_waitqueue_head(&journal->j_wait_done_commit); |
1031 | init_waitqueue_head(&journal->j_wait_commit); | 1031 | init_waitqueue_head(&journal->j_wait_commit); |
1032 | init_waitqueue_head(&journal->j_wait_updates); | 1032 | init_waitqueue_head(&journal->j_wait_updates); |
1033 | init_waitqueue_head(&journal->j_wait_reserved); | ||
1033 | mutex_init(&journal->j_barrier); | 1034 | mutex_init(&journal->j_barrier); |
1034 | mutex_init(&journal->j_checkpoint_mutex); | 1035 | mutex_init(&journal->j_checkpoint_mutex); |
1035 | spin_lock_init(&journal->j_revoke_lock); | 1036 | spin_lock_init(&journal->j_revoke_lock); |
@@ -1039,6 +1040,7 @@ static journal_t * journal_init_common (void) | |||
1039 | journal->j_commit_interval = (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE); | 1040 | journal->j_commit_interval = (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE); |
1040 | journal->j_min_batch_time = 0; | 1041 | journal->j_min_batch_time = 0; |
1041 | journal->j_max_batch_time = 15000; /* 15ms */ | 1042 | journal->j_max_batch_time = 15000; /* 15ms */ |
1043 | atomic_set(&journal->j_reserved_credits, 0); | ||
1042 | 1044 | ||
1043 | /* The journal is marked for error until we succeed with recovery! */ | 1045 | /* The journal is marked for error until we succeed with recovery! */ |
1044 | journal->j_flags = JBD2_ABORT; | 1046 | journal->j_flags = JBD2_ABORT; |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index f14288b04042..f33342a2a95e 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -89,7 +89,8 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
89 | transaction->t_expires = jiffies + journal->j_commit_interval; | 89 | transaction->t_expires = jiffies + journal->j_commit_interval; |
90 | spin_lock_init(&transaction->t_handle_lock); | 90 | spin_lock_init(&transaction->t_handle_lock); |
91 | atomic_set(&transaction->t_updates, 0); | 91 | atomic_set(&transaction->t_updates, 0); |
92 | atomic_set(&transaction->t_outstanding_credits, 0); | 92 | atomic_set(&transaction->t_outstanding_credits, |
93 | atomic_read(&journal->j_reserved_credits)); | ||
93 | atomic_set(&transaction->t_handle_count, 0); | 94 | atomic_set(&transaction->t_handle_count, 0); |
94 | INIT_LIST_HEAD(&transaction->t_inode_list); | 95 | INIT_LIST_HEAD(&transaction->t_inode_list); |
95 | INIT_LIST_HEAD(&transaction->t_private_list); | 96 | INIT_LIST_HEAD(&transaction->t_private_list); |
@@ -141,6 +142,112 @@ static inline void update_t_max_wait(transaction_t *transaction, | |||
141 | } | 142 | } |
142 | 143 | ||
143 | /* | 144 | /* |
145 | * Wait until running transaction passes T_LOCKED state. Also starts the commit | ||
146 | * if needed. The function expects running transaction to exist and releases | ||
147 | * j_state_lock. | ||
148 | */ | ||
149 | static void wait_transaction_locked(journal_t *journal) | ||
150 | __releases(journal->j_state_lock) | ||
151 | { | ||
152 | DEFINE_WAIT(wait); | ||
153 | int need_to_start; | ||
154 | tid_t tid = journal->j_running_transaction->t_tid; | ||
155 | |||
156 | prepare_to_wait(&journal->j_wait_transaction_locked, &wait, | ||
157 | TASK_UNINTERRUPTIBLE); | ||
158 | need_to_start = !tid_geq(journal->j_commit_request, tid); | ||
159 | read_unlock(&journal->j_state_lock); | ||
160 | if (need_to_start) | ||
161 | jbd2_log_start_commit(journal, tid); | ||
162 | schedule(); | ||
163 | finish_wait(&journal->j_wait_transaction_locked, &wait); | ||
164 | } | ||
165 | |||
166 | static void sub_reserved_credits(journal_t *journal, int blocks) | ||
167 | { | ||
168 | atomic_sub(blocks, &journal->j_reserved_credits); | ||
169 | wake_up(&journal->j_wait_reserved); | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Wait until we can add credits for handle to the running transaction. Called | ||
174 | * with j_state_lock held for reading. Returns 0 if handle joined the running | ||
175 | * transaction. Returns 1 if we had to wait, j_state_lock is dropped, and | ||
176 | * caller must retry. | ||
177 | */ | ||
178 | static int add_transaction_credits(journal_t *journal, int blocks, | ||
179 | int rsv_blocks) | ||
180 | { | ||
181 | transaction_t *t = journal->j_running_transaction; | ||
182 | int needed; | ||
183 | int total = blocks + rsv_blocks; | ||
184 | |||
185 | /* | ||
186 | * If the current transaction is locked down for commit, wait | ||
187 | * for the lock to be released. | ||
188 | */ | ||
189 | if (t->t_state == T_LOCKED) { | ||
190 | wait_transaction_locked(journal); | ||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * If there is not enough space left in the log to write all | ||
196 | * potential buffers requested by this operation, we need to | ||
197 | * stall pending a log checkpoint to free some more log space. | ||
198 | */ | ||
199 | needed = atomic_add_return(total, &t->t_outstanding_credits); | ||
200 | if (needed > journal->j_max_transaction_buffers) { | ||
201 | /* | ||
202 | * If the current transaction is already too large, | ||
203 | * then start to commit it: we can then go back and | ||
204 | * attach this handle to a new transaction. | ||
205 | */ | ||
206 | atomic_sub(total, &t->t_outstanding_credits); | ||
207 | wait_transaction_locked(journal); | ||
208 | return 1; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * The commit code assumes that it can get enough log space | ||
213 | * without forcing a checkpoint. This is *critical* for | ||
214 | * correctness: a checkpoint of a buffer which is also | ||
215 | * associated with a committing transaction creates a deadlock, | ||
216 | * so commit simply cannot force through checkpoints. | ||
217 | * | ||
218 | * We must therefore ensure the necessary space in the journal | ||
219 | * *before* starting to dirty potentially checkpointed buffers | ||
220 | * in the new transaction. | ||
221 | */ | ||
222 | if (jbd2_log_space_left(journal) < jbd2_space_needed(journal)) { | ||
223 | atomic_sub(total, &t->t_outstanding_credits); | ||
224 | read_unlock(&journal->j_state_lock); | ||
225 | write_lock(&journal->j_state_lock); | ||
226 | if (jbd2_log_space_left(journal) < jbd2_space_needed(journal)) | ||
227 | __jbd2_log_wait_for_space(journal); | ||
228 | write_unlock(&journal->j_state_lock); | ||
229 | return 1; | ||
230 | } | ||
231 | |||
232 | /* No reservation? We are done... */ | ||
233 | if (!rsv_blocks) | ||
234 | return 0; | ||
235 | |||
236 | needed = atomic_add_return(rsv_blocks, &journal->j_reserved_credits); | ||
237 | /* We allow at most half of a transaction to be reserved */ | ||
238 | if (needed > journal->j_max_transaction_buffers / 2) { | ||
239 | sub_reserved_credits(journal, rsv_blocks); | ||
240 | atomic_sub(total, &t->t_outstanding_credits); | ||
241 | read_unlock(&journal->j_state_lock); | ||
242 | wait_event(journal->j_wait_reserved, | ||
243 | atomic_read(&journal->j_reserved_credits) + rsv_blocks | ||
244 | <= journal->j_max_transaction_buffers / 2); | ||
245 | return 1; | ||
246 | } | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | /* | ||
144 | * start_this_handle: Given a handle, deal with any locking or stalling | 251 | * start_this_handle: Given a handle, deal with any locking or stalling |
145 | * needed to make sure that there is enough journal space for the handle | 252 | * needed to make sure that there is enough journal space for the handle |
146 | * to begin. Attach the handle to a transaction and set up the | 253 | * to begin. Attach the handle to a transaction and set up the |
@@ -151,18 +258,24 @@ static int start_this_handle(journal_t *journal, handle_t *handle, | |||
151 | gfp_t gfp_mask) | 258 | gfp_t gfp_mask) |
152 | { | 259 | { |
153 | transaction_t *transaction, *new_transaction = NULL; | 260 | transaction_t *transaction, *new_transaction = NULL; |
154 | tid_t tid; | 261 | int blocks = handle->h_buffer_credits; |
155 | int needed, need_to_start; | 262 | int rsv_blocks = 0; |
156 | int nblocks = handle->h_buffer_credits; | ||
157 | unsigned long ts = jiffies; | 263 | unsigned long ts = jiffies; |
158 | 264 | ||
159 | if (nblocks > journal->j_max_transaction_buffers) { | 265 | /* |
266 | * 1/2 of transaction can be reserved so we can practically handle | ||
267 | * only 1/2 of maximum transaction size per operation | ||
268 | */ | ||
269 | if (WARN_ON(blocks > journal->j_max_transaction_buffers / 2)) { | ||
160 | printk(KERN_ERR "JBD2: %s wants too many credits (%d > %d)\n", | 270 | printk(KERN_ERR "JBD2: %s wants too many credits (%d > %d)\n", |
161 | current->comm, nblocks, | 271 | current->comm, blocks, |
162 | journal->j_max_transaction_buffers); | 272 | journal->j_max_transaction_buffers / 2); |
163 | return -ENOSPC; | 273 | return -ENOSPC; |
164 | } | 274 | } |
165 | 275 | ||
276 | if (handle->h_rsv_handle) | ||
277 | rsv_blocks = handle->h_rsv_handle->h_buffer_credits; | ||
278 | |||
166 | alloc_transaction: | 279 | alloc_transaction: |
167 | if (!journal->j_running_transaction) { | 280 | if (!journal->j_running_transaction) { |
168 | new_transaction = kmem_cache_zalloc(transaction_cache, | 281 | new_transaction = kmem_cache_zalloc(transaction_cache, |
@@ -199,8 +312,12 @@ repeat: | |||
199 | return -EROFS; | 312 | return -EROFS; |
200 | } | 313 | } |
201 | 314 | ||
202 | /* Wait on the journal's transaction barrier if necessary */ | 315 | /* |
203 | if (journal->j_barrier_count) { | 316 | * Wait on the journal's transaction barrier if necessary. Specifically |
317 | * we allow reserved handles to proceed because otherwise commit could | ||
318 | * deadlock on page writeback not being able to complete. | ||
319 | */ | ||
320 | if (!handle->h_reserved && journal->j_barrier_count) { | ||
204 | read_unlock(&journal->j_state_lock); | 321 | read_unlock(&journal->j_state_lock); |
205 | wait_event(journal->j_wait_transaction_locked, | 322 | wait_event(journal->j_wait_transaction_locked, |
206 | journal->j_barrier_count == 0); | 323 | journal->j_barrier_count == 0); |
@@ -213,7 +330,7 @@ repeat: | |||
213 | goto alloc_transaction; | 330 | goto alloc_transaction; |
214 | write_lock(&journal->j_state_lock); | 331 | write_lock(&journal->j_state_lock); |
215 | if (!journal->j_running_transaction && | 332 | if (!journal->j_running_transaction && |
216 | !journal->j_barrier_count) { | 333 | (handle->h_reserved || !journal->j_barrier_count)) { |
217 | jbd2_get_transaction(journal, new_transaction); | 334 | jbd2_get_transaction(journal, new_transaction); |
218 | new_transaction = NULL; | 335 | new_transaction = NULL; |
219 | } | 336 | } |
@@ -223,75 +340,18 @@ repeat: | |||
223 | 340 | ||
224 | transaction = journal->j_running_transaction; | 341 | transaction = journal->j_running_transaction; |
225 | 342 | ||
226 | /* | 343 | if (!handle->h_reserved) { |
227 | * If the current transaction is locked down for commit, wait for the | 344 | /* We may have dropped j_state_lock - restart in that case */ |
228 | * lock to be released. | 345 | if (add_transaction_credits(journal, blocks, rsv_blocks)) |
229 | */ | 346 | goto repeat; |
230 | if (transaction->t_state == T_LOCKED) { | 347 | } else { |
231 | DEFINE_WAIT(wait); | ||
232 | |||
233 | prepare_to_wait(&journal->j_wait_transaction_locked, | ||
234 | &wait, TASK_UNINTERRUPTIBLE); | ||
235 | read_unlock(&journal->j_state_lock); | ||
236 | schedule(); | ||
237 | finish_wait(&journal->j_wait_transaction_locked, &wait); | ||
238 | goto repeat; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * If there is not enough space left in the log to write all potential | ||
243 | * buffers requested by this operation, we need to stall pending a log | ||
244 | * checkpoint to free some more log space. | ||
245 | */ | ||
246 | needed = atomic_add_return(nblocks, | ||
247 | &transaction->t_outstanding_credits); | ||
248 | |||
249 | if (needed > journal->j_max_transaction_buffers) { | ||
250 | /* | 348 | /* |
251 | * If the current transaction is already too large, then start | 349 | * We have handle reserved so we are allowed to join T_LOCKED |
252 | * to commit it: we can then go back and attach this handle to | 350 | * transaction and we don't have to check for transaction size |
253 | * a new transaction. | 351 | * and journal space. |
254 | */ | 352 | */ |
255 | DEFINE_WAIT(wait); | 353 | sub_reserved_credits(journal, blocks); |
256 | 354 | handle->h_reserved = 0; | |
257 | jbd_debug(2, "Handle %p starting new commit...\n", handle); | ||
258 | atomic_sub(nblocks, &transaction->t_outstanding_credits); | ||
259 | prepare_to_wait(&journal->j_wait_transaction_locked, &wait, | ||
260 | TASK_UNINTERRUPTIBLE); | ||
261 | tid = transaction->t_tid; | ||
262 | need_to_start = !tid_geq(journal->j_commit_request, tid); | ||
263 | read_unlock(&journal->j_state_lock); | ||
264 | if (need_to_start) | ||
265 | jbd2_log_start_commit(journal, tid); | ||
266 | schedule(); | ||
267 | finish_wait(&journal->j_wait_transaction_locked, &wait); | ||
268 | goto repeat; | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * The commit code assumes that it can get enough log space | ||
273 | * without forcing a checkpoint. This is *critical* for | ||
274 | * correctness: a checkpoint of a buffer which is also | ||
275 | * associated with a committing transaction creates a deadlock, | ||
276 | * so commit simply cannot force through checkpoints. | ||
277 | * | ||
278 | * We must therefore ensure the necessary space in the journal | ||
279 | * *before* starting to dirty potentially checkpointed buffers | ||
280 | * in the new transaction. | ||
281 | * | ||
282 | * The worst part is, any transaction currently committing can | ||
283 | * reduce the free space arbitrarily. Be careful to account for | ||
284 | * those buffers when checkpointing. | ||
285 | */ | ||
286 | if (jbd2_log_space_left(journal) < jbd2_space_needed(journal)) { | ||
287 | jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); | ||
288 | atomic_sub(nblocks, &transaction->t_outstanding_credits); | ||
289 | read_unlock(&journal->j_state_lock); | ||
290 | write_lock(&journal->j_state_lock); | ||
291 | if (jbd2_log_space_left(journal) < jbd2_space_needed(journal)) | ||
292 | __jbd2_log_wait_for_space(journal); | ||
293 | write_unlock(&journal->j_state_lock); | ||
294 | goto repeat; | ||
295 | } | 355 | } |
296 | 356 | ||
297 | /* OK, account for the buffers that this operation expects to | 357 | /* OK, account for the buffers that this operation expects to |
@@ -299,12 +359,12 @@ repeat: | |||
299 | */ | 359 | */ |
300 | update_t_max_wait(transaction, ts); | 360 | update_t_max_wait(transaction, ts); |
301 | handle->h_transaction = transaction; | 361 | handle->h_transaction = transaction; |
302 | handle->h_requested_credits = nblocks; | 362 | handle->h_requested_credits = blocks; |
303 | handle->h_start_jiffies = jiffies; | 363 | handle->h_start_jiffies = jiffies; |
304 | atomic_inc(&transaction->t_updates); | 364 | atomic_inc(&transaction->t_updates); |
305 | atomic_inc(&transaction->t_handle_count); | 365 | atomic_inc(&transaction->t_handle_count); |
306 | jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", | 366 | jbd_debug(4, "Handle %p given %d credits (total %d, free %lu)\n", |
307 | handle, nblocks, | 367 | handle, blocks, |
308 | atomic_read(&transaction->t_outstanding_credits), | 368 | atomic_read(&transaction->t_outstanding_credits), |
309 | jbd2_log_space_left(journal)); | 369 | jbd2_log_space_left(journal)); |
310 | read_unlock(&journal->j_state_lock); | 370 | read_unlock(&journal->j_state_lock); |
@@ -338,16 +398,21 @@ static handle_t *new_handle(int nblocks) | |||
338 | * | 398 | * |
339 | * We make sure that the transaction can guarantee at least nblocks of | 399 | * We make sure that the transaction can guarantee at least nblocks of |
340 | * modified buffers in the log. We block until the log can guarantee | 400 | * modified buffers in the log. We block until the log can guarantee |
341 | * that much space. | 401 | * that much space. Additionally, if rsv_blocks > 0, we also create another |
342 | * | 402 | * handle with rsv_blocks reserved blocks in the journal. This handle is |
343 | * This function is visible to journal users (like ext3fs), so is not | 403 | * is stored in h_rsv_handle. It is not attached to any particular transaction |
344 | * called with the journal already locked. | 404 | * and thus doesn't block transaction commit. If the caller uses this reserved |
405 | * handle, it has to set h_rsv_handle to NULL as otherwise jbd2_journal_stop() | ||
406 | * on the parent handle will dispose the reserved one. Reserved handle has to | ||
407 | * be converted to a normal handle using jbd2_journal_start_reserved() before | ||
408 | * it can be used. | ||
345 | * | 409 | * |
346 | * Return a pointer to a newly allocated handle, or an ERR_PTR() value | 410 | * Return a pointer to a newly allocated handle, or an ERR_PTR() value |
347 | * on failure. | 411 | * on failure. |
348 | */ | 412 | */ |
349 | handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask, | 413 | handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int rsv_blocks, |
350 | unsigned int type, unsigned int line_no) | 414 | gfp_t gfp_mask, unsigned int type, |
415 | unsigned int line_no) | ||
351 | { | 416 | { |
352 | handle_t *handle = journal_current_handle(); | 417 | handle_t *handle = journal_current_handle(); |
353 | int err; | 418 | int err; |
@@ -364,11 +429,25 @@ handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask, | |||
364 | handle = new_handle(nblocks); | 429 | handle = new_handle(nblocks); |
365 | if (!handle) | 430 | if (!handle) |
366 | return ERR_PTR(-ENOMEM); | 431 | return ERR_PTR(-ENOMEM); |
432 | if (rsv_blocks) { | ||
433 | handle_t *rsv_handle; | ||
434 | |||
435 | rsv_handle = new_handle(rsv_blocks); | ||
436 | if (!rsv_handle) { | ||
437 | jbd2_free_handle(handle); | ||
438 | return ERR_PTR(-ENOMEM); | ||
439 | } | ||
440 | rsv_handle->h_reserved = 1; | ||
441 | rsv_handle->h_journal = journal; | ||
442 | handle->h_rsv_handle = rsv_handle; | ||
443 | } | ||
367 | 444 | ||
368 | current->journal_info = handle; | 445 | current->journal_info = handle; |
369 | 446 | ||
370 | err = start_this_handle(journal, handle, gfp_mask); | 447 | err = start_this_handle(journal, handle, gfp_mask); |
371 | if (err < 0) { | 448 | if (err < 0) { |
449 | if (handle->h_rsv_handle) | ||
450 | jbd2_free_handle(handle->h_rsv_handle); | ||
372 | jbd2_free_handle(handle); | 451 | jbd2_free_handle(handle); |
373 | current->journal_info = NULL; | 452 | current->journal_info = NULL; |
374 | return ERR_PTR(err); | 453 | return ERR_PTR(err); |
@@ -385,10 +464,68 @@ EXPORT_SYMBOL(jbd2__journal_start); | |||
385 | 464 | ||
386 | handle_t *jbd2_journal_start(journal_t *journal, int nblocks) | 465 | handle_t *jbd2_journal_start(journal_t *journal, int nblocks) |
387 | { | 466 | { |
388 | return jbd2__journal_start(journal, nblocks, GFP_NOFS, 0, 0); | 467 | return jbd2__journal_start(journal, nblocks, 0, GFP_NOFS, 0, 0); |
389 | } | 468 | } |
390 | EXPORT_SYMBOL(jbd2_journal_start); | 469 | EXPORT_SYMBOL(jbd2_journal_start); |
391 | 470 | ||
471 | void jbd2_journal_free_reserved(handle_t *handle) | ||
472 | { | ||
473 | journal_t *journal = handle->h_journal; | ||
474 | |||
475 | WARN_ON(!handle->h_reserved); | ||
476 | sub_reserved_credits(journal, handle->h_buffer_credits); | ||
477 | jbd2_free_handle(handle); | ||
478 | } | ||
479 | EXPORT_SYMBOL(jbd2_journal_free_reserved); | ||
480 | |||
481 | /** | ||
482 | * int jbd2_journal_start_reserved(handle_t *handle) - start reserved handle | ||
483 | * @handle: handle to start | ||
484 | * | ||
485 | * Start handle that has been previously reserved with jbd2_journal_reserve(). | ||
486 | * This attaches @handle to the running transaction (or creates one if there's | ||
487 | * not transaction running). Unlike jbd2_journal_start() this function cannot | ||
488 | * block on journal commit, checkpointing, or similar stuff. It can block on | ||
489 | * memory allocation or frozen journal though. | ||
490 | * | ||
491 | * Return 0 on success, non-zero on error - handle is freed in that case. | ||
492 | */ | ||
493 | int jbd2_journal_start_reserved(handle_t *handle, unsigned int type, | ||
494 | unsigned int line_no) | ||
495 | { | ||
496 | journal_t *journal = handle->h_journal; | ||
497 | int ret = -EIO; | ||
498 | |||
499 | if (WARN_ON(!handle->h_reserved)) { | ||
500 | /* Someone passed in normal handle? Just stop it. */ | ||
501 | jbd2_journal_stop(handle); | ||
502 | return ret; | ||
503 | } | ||
504 | /* | ||
505 | * Usefulness of mixing of reserved and unreserved handles is | ||
506 | * questionable. So far nobody seems to need it so just error out. | ||
507 | */ | ||
508 | if (WARN_ON(current->journal_info)) { | ||
509 | jbd2_journal_free_reserved(handle); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | handle->h_journal = NULL; | ||
514 | current->journal_info = handle; | ||
515 | /* | ||
516 | * GFP_NOFS is here because callers are likely from writeback or | ||
517 | * similarly constrained call sites | ||
518 | */ | ||
519 | ret = start_this_handle(journal, handle, GFP_NOFS); | ||
520 | if (ret < 0) { | ||
521 | current->journal_info = NULL; | ||
522 | jbd2_journal_free_reserved(handle); | ||
523 | } | ||
524 | handle->h_type = type; | ||
525 | handle->h_line_no = line_no; | ||
526 | return ret; | ||
527 | } | ||
528 | EXPORT_SYMBOL(jbd2_journal_start_reserved); | ||
392 | 529 | ||
393 | /** | 530 | /** |
394 | * int jbd2_journal_extend() - extend buffer credits. | 531 | * int jbd2_journal_extend() - extend buffer credits. |
@@ -483,7 +620,8 @@ out: | |||
483 | * to a running handle, a call to jbd2_journal_restart will commit the | 620 | * to a running handle, a call to jbd2_journal_restart will commit the |
484 | * handle's transaction so far and reattach the handle to a new | 621 | * handle's transaction so far and reattach the handle to a new |
485 | * transaction capabable of guaranteeing the requested number of | 622 | * transaction capabable of guaranteeing the requested number of |
486 | * credits. | 623 | * credits. We preserve reserved handle if there's any attached to the |
624 | * passed in handle. | ||
487 | */ | 625 | */ |
488 | int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) | 626 | int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) |
489 | { | 627 | { |
@@ -508,6 +646,10 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) | |||
508 | spin_lock(&transaction->t_handle_lock); | 646 | spin_lock(&transaction->t_handle_lock); |
509 | atomic_sub(handle->h_buffer_credits, | 647 | atomic_sub(handle->h_buffer_credits, |
510 | &transaction->t_outstanding_credits); | 648 | &transaction->t_outstanding_credits); |
649 | if (handle->h_rsv_handle) { | ||
650 | sub_reserved_credits(journal, | ||
651 | handle->h_rsv_handle->h_buffer_credits); | ||
652 | } | ||
511 | if (atomic_dec_and_test(&transaction->t_updates)) | 653 | if (atomic_dec_and_test(&transaction->t_updates)) |
512 | wake_up(&journal->j_wait_updates); | 654 | wake_up(&journal->j_wait_updates); |
513 | spin_unlock(&transaction->t_handle_lock); | 655 | spin_unlock(&transaction->t_handle_lock); |
@@ -550,6 +692,14 @@ void jbd2_journal_lock_updates(journal_t *journal) | |||
550 | write_lock(&journal->j_state_lock); | 692 | write_lock(&journal->j_state_lock); |
551 | ++journal->j_barrier_count; | 693 | ++journal->j_barrier_count; |
552 | 694 | ||
695 | /* Wait until there are no reserved handles */ | ||
696 | if (atomic_read(&journal->j_reserved_credits)) { | ||
697 | write_unlock(&journal->j_state_lock); | ||
698 | wait_event(journal->j_wait_reserved, | ||
699 | atomic_read(&journal->j_reserved_credits) == 0); | ||
700 | write_lock(&journal->j_state_lock); | ||
701 | } | ||
702 | |||
553 | /* Wait until there are no running updates */ | 703 | /* Wait until there are no running updates */ |
554 | while (1) { | 704 | while (1) { |
555 | transaction_t *transaction = journal->j_running_transaction; | 705 | transaction_t *transaction = journal->j_running_transaction; |
@@ -1505,6 +1655,8 @@ int jbd2_journal_stop(handle_t *handle) | |||
1505 | 1655 | ||
1506 | lock_map_release(&handle->h_lockdep_map); | 1656 | lock_map_release(&handle->h_lockdep_map); |
1507 | 1657 | ||
1658 | if (handle->h_rsv_handle) | ||
1659 | jbd2_journal_free_reserved(handle->h_rsv_handle); | ||
1508 | jbd2_free_handle(handle); | 1660 | jbd2_free_handle(handle); |
1509 | return err; | 1661 | return err; |
1510 | } | 1662 | } |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 8028dd581cb0..fb91c8debe6a 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -410,8 +410,15 @@ struct jbd2_revoke_table_s; | |||
410 | 410 | ||
411 | struct jbd2_journal_handle | 411 | struct jbd2_journal_handle |
412 | { | 412 | { |
413 | /* Which compound transaction is this update a part of? */ | 413 | union { |
414 | transaction_t *h_transaction; | 414 | /* Which compound transaction is this update a part of? */ |
415 | transaction_t *h_transaction; | ||
416 | /* Which journal handle belongs to - used iff h_reserved set */ | ||
417 | journal_t *h_journal; | ||
418 | }; | ||
419 | |||
420 | /* Handle reserved for finishing the logical operation */ | ||
421 | handle_t *h_rsv_handle; | ||
415 | 422 | ||
416 | /* Number of remaining buffers we are allowed to dirty: */ | 423 | /* Number of remaining buffers we are allowed to dirty: */ |
417 | int h_buffer_credits; | 424 | int h_buffer_credits; |
@@ -426,6 +433,7 @@ struct jbd2_journal_handle | |||
426 | /* Flags [no locking] */ | 433 | /* Flags [no locking] */ |
427 | unsigned int h_sync: 1; /* sync-on-close */ | 434 | unsigned int h_sync: 1; /* sync-on-close */ |
428 | unsigned int h_jdata: 1; /* force data journaling */ | 435 | unsigned int h_jdata: 1; /* force data journaling */ |
436 | unsigned int h_reserved: 1; /* handle with reserved credits */ | ||
429 | unsigned int h_aborted: 1; /* fatal error on handle */ | 437 | unsigned int h_aborted: 1; /* fatal error on handle */ |
430 | unsigned int h_type: 8; /* for handle statistics */ | 438 | unsigned int h_type: 8; /* for handle statistics */ |
431 | unsigned int h_line_no: 16; /* for handle statistics */ | 439 | unsigned int h_line_no: 16; /* for handle statistics */ |
@@ -690,6 +698,7 @@ jbd2_time_diff(unsigned long start, unsigned long end) | |||
690 | * @j_wait_done_commit: Wait queue for waiting for commit to complete | 698 | * @j_wait_done_commit: Wait queue for waiting for commit to complete |
691 | * @j_wait_commit: Wait queue to trigger commit | 699 | * @j_wait_commit: Wait queue to trigger commit |
692 | * @j_wait_updates: Wait queue to wait for updates to complete | 700 | * @j_wait_updates: Wait queue to wait for updates to complete |
701 | * @j_wait_reserved: Wait queue to wait for reserved buffer credits to drop | ||
693 | * @j_checkpoint_mutex: Mutex for locking against concurrent checkpoints | 702 | * @j_checkpoint_mutex: Mutex for locking against concurrent checkpoints |
694 | * @j_head: Journal head - identifies the first unused block in the journal | 703 | * @j_head: Journal head - identifies the first unused block in the journal |
695 | * @j_tail: Journal tail - identifies the oldest still-used block in the | 704 | * @j_tail: Journal tail - identifies the oldest still-used block in the |
@@ -703,6 +712,7 @@ jbd2_time_diff(unsigned long start, unsigned long end) | |||
703 | * journal | 712 | * journal |
704 | * @j_fs_dev: Device which holds the client fs. For internal journal this will | 713 | * @j_fs_dev: Device which holds the client fs. For internal journal this will |
705 | * be equal to j_dev | 714 | * be equal to j_dev |
715 | * @j_reserved_credits: Number of buffers reserved from the running transaction | ||
706 | * @j_maxlen: Total maximum capacity of the journal region on disk. | 716 | * @j_maxlen: Total maximum capacity of the journal region on disk. |
707 | * @j_list_lock: Protects the buffer lists and internal buffer state. | 717 | * @j_list_lock: Protects the buffer lists and internal buffer state. |
708 | * @j_inode: Optional inode where we store the journal. If present, all journal | 718 | * @j_inode: Optional inode where we store the journal. If present, all journal |
@@ -801,6 +811,9 @@ struct journal_s | |||
801 | /* Wait queue to wait for updates to complete */ | 811 | /* Wait queue to wait for updates to complete */ |
802 | wait_queue_head_t j_wait_updates; | 812 | wait_queue_head_t j_wait_updates; |
803 | 813 | ||
814 | /* Wait queue to wait for reserved buffer credits to drop */ | ||
815 | wait_queue_head_t j_wait_reserved; | ||
816 | |||
804 | /* Semaphore for locking against concurrent checkpoints */ | 817 | /* Semaphore for locking against concurrent checkpoints */ |
805 | struct mutex j_checkpoint_mutex; | 818 | struct mutex j_checkpoint_mutex; |
806 | 819 | ||
@@ -855,6 +868,9 @@ struct journal_s | |||
855 | /* Total maximum capacity of the journal region on disk. */ | 868 | /* Total maximum capacity of the journal region on disk. */ |
856 | unsigned int j_maxlen; | 869 | unsigned int j_maxlen; |
857 | 870 | ||
871 | /* Number of buffers reserved from the running transaction */ | ||
872 | atomic_t j_reserved_credits; | ||
873 | |||
858 | /* | 874 | /* |
859 | * Protects the buffer lists and internal buffer state. | 875 | * Protects the buffer lists and internal buffer state. |
860 | */ | 876 | */ |
@@ -1091,10 +1107,14 @@ static inline handle_t *journal_current_handle(void) | |||
1091 | */ | 1107 | */ |
1092 | 1108 | ||
1093 | extern handle_t *jbd2_journal_start(journal_t *, int nblocks); | 1109 | extern handle_t *jbd2_journal_start(journal_t *, int nblocks); |
1094 | extern handle_t *jbd2__journal_start(journal_t *, int nblocks, gfp_t gfp_mask, | 1110 | extern handle_t *jbd2__journal_start(journal_t *, int blocks, int rsv_blocks, |
1095 | unsigned int type, unsigned int line_no); | 1111 | gfp_t gfp_mask, unsigned int type, |
1112 | unsigned int line_no); | ||
1096 | extern int jbd2_journal_restart(handle_t *, int nblocks); | 1113 | extern int jbd2_journal_restart(handle_t *, int nblocks); |
1097 | extern int jbd2__journal_restart(handle_t *, int nblocks, gfp_t gfp_mask); | 1114 | extern int jbd2__journal_restart(handle_t *, int nblocks, gfp_t gfp_mask); |
1115 | extern int jbd2_journal_start_reserved(handle_t *handle, | ||
1116 | unsigned int type, unsigned int line_no); | ||
1117 | extern void jbd2_journal_free_reserved(handle_t *handle); | ||
1098 | extern int jbd2_journal_extend (handle_t *, int nblocks); | 1118 | extern int jbd2_journal_extend (handle_t *, int nblocks); |
1099 | extern int jbd2_journal_get_write_access(handle_t *, struct buffer_head *); | 1119 | extern int jbd2_journal_get_write_access(handle_t *, struct buffer_head *); |
1100 | extern int jbd2_journal_get_create_access (handle_t *, struct buffer_head *); | 1120 | extern int jbd2_journal_get_create_access (handle_t *, struct buffer_head *); |