diff options
Diffstat (limited to 'fs/jbd2/checkpoint.c')
-rw-r--r-- | fs/jbd2/checkpoint.c | 56 |
1 files changed, 24 insertions, 32 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 3ab4c5ee12ce..988b32ed4c87 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -421,16 +421,15 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
421 | * release them. | 421 | * release them. |
422 | * | 422 | * |
423 | * Called with j_list_lock held. | 423 | * Called with j_list_lock held. |
424 | * Returns number of buffers reaped (for debug) | 424 | * Returns 1 if we freed the transaction, 0 otherwise. |
425 | */ | 425 | */ |
426 | 426 | static int journal_clean_one_cp_list(struct journal_head *jh) | |
427 | static int journal_clean_one_cp_list(struct journal_head *jh, int *released) | ||
428 | { | 427 | { |
429 | struct journal_head *last_jh; | 428 | struct journal_head *last_jh; |
430 | struct journal_head *next_jh = jh; | 429 | struct journal_head *next_jh = jh; |
431 | int ret, freed = 0; | 430 | int ret; |
431 | int freed = 0; | ||
432 | 432 | ||
433 | *released = 0; | ||
434 | if (!jh) | 433 | if (!jh) |
435 | return 0; | 434 | return 0; |
436 | 435 | ||
@@ -441,11 +440,9 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released) | |||
441 | ret = __try_to_free_cp_buf(jh); | 440 | ret = __try_to_free_cp_buf(jh); |
442 | if (!ret) | 441 | if (!ret) |
443 | return freed; | 442 | return freed; |
444 | freed++; | 443 | if (ret == 2) |
445 | if (ret == 2) { | 444 | return 1; |
446 | *released = 1; | 445 | freed = 1; |
447 | return freed; | ||
448 | } | ||
449 | /* | 446 | /* |
450 | * This function only frees up some memory | 447 | * This function only frees up some memory |
451 | * if possible so we dont have an obligation | 448 | * if possible so we dont have an obligation |
@@ -465,53 +462,48 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released) | |||
465 | * Find all the written-back checkpoint buffers in the journal and release them. | 462 | * Find all the written-back checkpoint buffers in the journal and release them. |
466 | * | 463 | * |
467 | * Called with j_list_lock held. | 464 | * Called with j_list_lock held. |
468 | * Returns number of buffers reaped (for debug) | ||
469 | */ | 465 | */ |
470 | 466 | void __jbd2_journal_clean_checkpoint_list(journal_t *journal) | |
471 | int __jbd2_journal_clean_checkpoint_list(journal_t *journal) | ||
472 | { | 467 | { |
473 | transaction_t *transaction, *last_transaction, *next_transaction; | 468 | transaction_t *transaction, *last_transaction, *next_transaction; |
474 | int ret; | 469 | int ret; |
475 | int freed = 0; | ||
476 | int released; | ||
477 | 470 | ||
478 | transaction = journal->j_checkpoint_transactions; | 471 | transaction = journal->j_checkpoint_transactions; |
479 | if (!transaction) | 472 | if (!transaction) |
480 | goto out; | 473 | return; |
481 | 474 | ||
482 | last_transaction = transaction->t_cpprev; | 475 | last_transaction = transaction->t_cpprev; |
483 | next_transaction = transaction; | 476 | next_transaction = transaction; |
484 | do { | 477 | do { |
485 | transaction = next_transaction; | 478 | transaction = next_transaction; |
486 | next_transaction = transaction->t_cpnext; | 479 | next_transaction = transaction->t_cpnext; |
487 | ret = journal_clean_one_cp_list(transaction-> | 480 | ret = journal_clean_one_cp_list(transaction->t_checkpoint_list); |
488 | t_checkpoint_list, &released); | ||
489 | /* | 481 | /* |
490 | * This function only frees up some memory if possible so we | 482 | * This function only frees up some memory if possible so we |
491 | * dont have an obligation to finish processing. Bail out if | 483 | * dont have an obligation to finish processing. Bail out if |
492 | * preemption requested: | 484 | * preemption requested: |
493 | */ | 485 | */ |
494 | if (need_resched()) { | 486 | if (need_resched()) |
495 | freed += ret; | 487 | return; |
496 | goto out; | 488 | if (ret) |
497 | } | ||
498 | if (released) { | ||
499 | freed += ret; | ||
500 | continue; | 489 | continue; |
501 | } | ||
502 | /* | 490 | /* |
503 | * It is essential that we are as careful as in the case of | 491 | * It is essential that we are as careful as in the case of |
504 | * t_checkpoint_list with removing the buffer from the list as | 492 | * t_checkpoint_list with removing the buffer from the list as |
505 | * we can possibly see not yet submitted buffers on io_list | 493 | * we can possibly see not yet submitted buffers on io_list |
506 | */ | 494 | */ |
507 | ret += journal_clean_one_cp_list(transaction-> | 495 | ret = journal_clean_one_cp_list(transaction-> |
508 | t_checkpoint_io_list, &released); | 496 | t_checkpoint_io_list); |
509 | freed += ret; | 497 | if (need_resched()) |
510 | if (need_resched() || !ret) | 498 | return; |
511 | goto out; | 499 | /* |
500 | * Stop scanning if we couldn't free the transaction. This | ||
501 | * avoids pointless scanning of transactions which still | ||
502 | * weren't checkpointed. | ||
503 | */ | ||
504 | if (!ret) | ||
505 | return; | ||
512 | } while (transaction != last_transaction); | 506 | } while (transaction != last_transaction); |
513 | out: | ||
514 | return freed; | ||
515 | } | 507 | } |
516 | 508 | ||
517 | /* | 509 | /* |