checkpoint.c (214eb5a4d8a2032fb9f0711d1b202eb88ee02920) checkpoint.c (4ba3fcdde7e36af93610ceb3cc38365b14539865)
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * linux/fs/jbd2/checkpoint.c
4 *
5 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
6 *
7 * Copyright 1999 Red Hat Software --- All Rights Reserved
8 *

--- 66 unchanged lines hidden (view full) ---

75 jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
76 jh->b_cpprev->b_cpnext = jh;
77 jh->b_cpnext->b_cpprev = jh;
78 }
79 transaction->t_checkpoint_io_list = jh;
80}
81
82/*
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * linux/fs/jbd2/checkpoint.c
4 *
5 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
6 *
7 * Copyright 1999 Red Hat Software --- All Rights Reserved
8 *

--- 66 unchanged lines hidden (view full) ---

75 jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
76 jh->b_cpprev->b_cpnext = jh;
77 jh->b_cpnext->b_cpprev = jh;
78 }
79 transaction->t_checkpoint_io_list = jh;
80}
81
82/*
83 * Check a checkpoint buffer could be release or not.
84 *
85 * Requires j_list_lock
86 */
87static inline bool __cp_buffer_busy(struct journal_head *jh)
88{
89 struct buffer_head *bh = jh2bh(jh);
90
91 return (jh->b_transaction || buffer_locked(bh) || buffer_dirty(bh));
92}
93
94/*
83 * Try to release a checkpointed buffer from its transaction.
84 * Returns 1 if we released it and 2 if we also released the
85 * whole transaction.
86 *
87 * Requires j_list_lock
88 */
89static int __try_to_free_cp_buf(struct journal_head *jh)
90{

--- 363 unchanged lines hidden (view full) ---

454 if (need_resched())
455 return 0;
456 } while (jh != last_jh);
457
458 return 0;
459}
460
461/*
95 * Try to release a checkpointed buffer from its transaction.
96 * Returns 1 if we released it and 2 if we also released the
97 * whole transaction.
98 *
99 * Requires j_list_lock
100 */
101static int __try_to_free_cp_buf(struct journal_head *jh)
102{

--- 363 unchanged lines hidden (view full) ---

466 if (need_resched())
467 return 0;
468 } while (jh != last_jh);
469
470 return 0;
471}
472
473/*
474 * journal_shrink_one_cp_list
475 *
476 * Find 'nr_to_scan' written-back checkpoint buffers in the given list
477 * and try to release them. If the whole transaction is released, set
478 * the 'released' parameter. Return the number of released checkpointed
479 * buffers.
480 *
481 * Called with j_list_lock held.
482 */
483static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
484 unsigned long *nr_to_scan,
485 bool *released)
486{
487 struct journal_head *last_jh;
488 struct journal_head *next_jh = jh;
489 unsigned long nr_freed = 0;
490 int ret;
491
492 if (!jh || *nr_to_scan == 0)
493 return 0;
494
495 last_jh = jh->b_cpprev;
496 do {
497 jh = next_jh;
498 next_jh = jh->b_cpnext;
499
500 (*nr_to_scan)--;
501 if (__cp_buffer_busy(jh))
502 continue;
503
504 nr_freed++;
505 ret = __jbd2_journal_remove_checkpoint(jh);
506 if (ret) {
507 *released = true;
508 break;
509 }
510
511 if (need_resched())
512 break;
513 } while (jh != last_jh && *nr_to_scan);
514
515 return nr_freed;
516}
517
518/*
519 * jbd2_journal_shrink_checkpoint_list
520 *
521 * Find 'nr_to_scan' written-back checkpoint buffers in the journal
522 * and try to release them. Return the number of released checkpointed
523 * buffers.
524 *
525 * Called with j_list_lock held.
526 */
527unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal,
528 unsigned long *nr_to_scan)
529{
530 transaction_t *transaction, *last_transaction, *next_transaction;
531 bool released;
532 tid_t first_tid = 0, last_tid = 0, next_tid = 0;
533 tid_t tid = 0;
534 unsigned long nr_freed = 0;
535 unsigned long nr_scanned = *nr_to_scan;
536
537again:
538 spin_lock(&journal->j_list_lock);
539 if (!journal->j_checkpoint_transactions) {
540 spin_unlock(&journal->j_list_lock);
541 goto out;
542 }
543
544 /*
545 * Get next shrink transaction, resume previous scan or start
546 * over again. If some others do checkpoint and drop transaction
547 * from the checkpoint list, we ignore saved j_shrink_transaction
548 * and start over unconditionally.
549 */
550 if (journal->j_shrink_transaction)
551 transaction = journal->j_shrink_transaction;
552 else
553 transaction = journal->j_checkpoint_transactions;
554
555 if (!first_tid)
556 first_tid = transaction->t_tid;
557 last_transaction = journal->j_checkpoint_transactions->t_cpprev;
558 next_transaction = transaction;
559 last_tid = last_transaction->t_tid;
560 do {
561 transaction = next_transaction;
562 next_transaction = transaction->t_cpnext;
563 tid = transaction->t_tid;
564 released = false;
565
566 nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list,
567 nr_to_scan, &released);
568 if (*nr_to_scan == 0)
569 break;
570 if (need_resched() || spin_needbreak(&journal->j_list_lock))
571 break;
572 if (released)
573 continue;
574
575 nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list,
576 nr_to_scan, &released);
577 if (*nr_to_scan == 0)
578 break;
579 if (need_resched() || spin_needbreak(&journal->j_list_lock))
580 break;
581 } while (transaction != last_transaction);
582
583 if (transaction != last_transaction) {
584 journal->j_shrink_transaction = next_transaction;
585 next_tid = next_transaction->t_tid;
586 } else {
587 journal->j_shrink_transaction = NULL;
588 next_tid = 0;
589 }
590
591 spin_unlock(&journal->j_list_lock);
592 cond_resched();
593
594 if (*nr_to_scan && next_tid)
595 goto again;
596out:
597 nr_scanned -= *nr_to_scan;
598 trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid,
599 nr_freed, nr_scanned, next_tid);
600
601 return nr_freed;
602}
603
604/*
462 * journal_clean_checkpoint_list
463 *
464 * Find all the written-back checkpoint buffers in the journal and release them.
465 * If 'destroy' is set, release all buffers unconditionally.
466 *
467 * Called with j_list_lock held.
468 */
469void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)

--- 105 unchanged lines hidden (view full) ---

575 * jbd2_journal_destroy(). So mark the writeback IO error in the
576 * journal here and we abort the journal later from a better context.
577 */
578 if (buffer_write_io_error(bh))
579 set_bit(JBD2_CHECKPOINT_IO_ERROR, &journal->j_atomic_flags);
580
581 __buffer_unlink(jh);
582 jh->b_cp_transaction = NULL;
605 * journal_clean_checkpoint_list
606 *
607 * Find all the written-back checkpoint buffers in the journal and release them.
608 * If 'destroy' is set, release all buffers unconditionally.
609 *
610 * Called with j_list_lock held.
611 */
612void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)

--- 105 unchanged lines hidden (view full) ---

718 * jbd2_journal_destroy(). So mark the writeback IO error in the
719 * journal here and we abort the journal later from a better context.
720 */
721 if (buffer_write_io_error(bh))
722 set_bit(JBD2_CHECKPOINT_IO_ERROR, &journal->j_atomic_flags);
723
724 __buffer_unlink(jh);
725 jh->b_cp_transaction = NULL;
726 percpu_counter_dec(&journal->j_jh_shrink_count);
583 jbd2_journal_put_journal_head(jh);
584
585 /* Is this transaction empty? */
586 if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list)
587 return 0;
588
589 /*
590 * There is one special case to worry about: if we have just pulled the

--- 46 unchanged lines hidden (view full) ---

637 jh->b_cpnext = jh->b_cpprev = jh;
638 } else {
639 jh->b_cpnext = transaction->t_checkpoint_list;
640 jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;
641 jh->b_cpprev->b_cpnext = jh;
642 jh->b_cpnext->b_cpprev = jh;
643 }
644 transaction->t_checkpoint_list = jh;
727 jbd2_journal_put_journal_head(jh);
728
729 /* Is this transaction empty? */
730 if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list)
731 return 0;
732
733 /*
734 * There is one special case to worry about: if we have just pulled the

--- 46 unchanged lines hidden (view full) ---

781 jh->b_cpnext = jh->b_cpprev = jh;
782 } else {
783 jh->b_cpnext = transaction->t_checkpoint_list;
784 jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;
785 jh->b_cpprev->b_cpnext = jh;
786 jh->b_cpnext->b_cpprev = jh;
787 }
788 transaction->t_checkpoint_list = jh;
789 percpu_counter_inc(&transaction->t_journal->j_jh_shrink_count);
645}
646
647/*
648 * We've finished with this transaction structure: adios...
649 *
650 * The transaction must have no links except for the checkpoint by this
651 * point.
652 *
653 * Called with the journal locked.
654 * Called with j_list_lock held.
655 */
656
657void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transaction)
658{
659 assert_spin_locked(&journal->j_list_lock);
790}
791
792/*
793 * We've finished with this transaction structure: adios...
794 *
795 * The transaction must have no links except for the checkpoint by this
796 * point.
797 *
798 * Called with the journal locked.
799 * Called with j_list_lock held.
800 */
801
802void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transaction)
803{
804 assert_spin_locked(&journal->j_list_lock);
805
806 journal->j_shrink_transaction = NULL;
660 if (transaction->t_cpnext) {
661 transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
662 transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
663 if (journal->j_checkpoint_transactions == transaction)
664 journal->j_checkpoint_transactions =
665 transaction->t_cpnext;
666 if (journal->j_checkpoint_transactions == transaction)
667 journal->j_checkpoint_transactions = NULL;

--- 16 unchanged lines hidden ---
807 if (transaction->t_cpnext) {
808 transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
809 transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
810 if (journal->j_checkpoint_transactions == transaction)
811 journal->j_checkpoint_transactions =
812 transaction->t_cpnext;
813 if (journal->j_checkpoint_transactions == transaction)
814 journal->j_checkpoint_transactions = NULL;

--- 16 unchanged lines hidden ---