LCOV - code coverage report
Current view: top level - fs/jbd2 - checkpoint.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 88 205 42.9 %
Date: 2020-09-30 20:25:40 Functions: 7 13 53.8 %
Branches: 58 172 33.7 %

           Branch data     Line data    Source code
       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                 :            :  *
       9                 :            :  * Checkpoint routines for the generic filesystem journaling code.
      10                 :            :  * Part of the ext2fs journaling system.
      11                 :            :  *
      12                 :            :  * Checkpointing is the process of ensuring that a section of the log is
      13                 :            :  * committed fully to disk, so that that portion of the log can be
      14                 :            :  * reused.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <linux/time.h>
      18                 :            : #include <linux/fs.h>
      19                 :            : #include <linux/jbd2.h>
      20                 :            : #include <linux/errno.h>
      21                 :            : #include <linux/slab.h>
      22                 :            : #include <linux/blkdev.h>
      23                 :            : #include <trace/events/jbd2.h>
      24                 :            : 
      25                 :            : /*
      26                 :            :  * Unlink a buffer from a transaction checkpoint list.
      27                 :            :  *
      28                 :            :  * Called with j_list_lock held.
      29                 :            :  */
      30                 :            : static inline void __buffer_unlink_first(struct journal_head *jh)
      31                 :            : {
      32                 :            :         transaction_t *transaction = jh->b_cp_transaction;
      33                 :            : 
      34                 :      43371 :         jh->b_cpnext->b_cpprev = jh->b_cpprev;
      35                 :      43371 :         jh->b_cpprev->b_cpnext = jh->b_cpnext;
      36   [ #  #  +  + ]:      43371 :         if (transaction->t_checkpoint_list == jh) {
      37                 :      20203 :                 transaction->t_checkpoint_list = jh->b_cpnext;
      38   [ #  #  +  + ]:      20203 :                 if (transaction->t_checkpoint_list == jh)
      39                 :       1843 :                         transaction->t_checkpoint_list = NULL;
      40                 :            :         }
      41                 :            : }
      42                 :            : 
      43                 :            : /*
      44                 :            :  * Unlink a buffer from a transaction checkpoint(io) list.
      45                 :            :  *
      46                 :            :  * Called with j_list_lock held.
      47                 :            :  */
      48                 :      43371 : static inline void __buffer_unlink(struct journal_head *jh)
      49                 :            : {
      50                 :      43371 :         transaction_t *transaction = jh->b_cp_transaction;
      51                 :            : 
      52                 :            :         __buffer_unlink_first(jh);
      53         [ -  + ]:      43371 :         if (transaction->t_checkpoint_io_list == jh) {
      54                 :          0 :                 transaction->t_checkpoint_io_list = jh->b_cpnext;
      55         [ #  # ]:          0 :                 if (transaction->t_checkpoint_io_list == jh)
      56                 :          0 :                         transaction->t_checkpoint_io_list = NULL;
      57                 :            :         }
      58                 :      43371 : }
      59                 :            : 
      60                 :            : /*
      61                 :            :  * Move a buffer from the checkpoint list to the checkpoint io list
      62                 :            :  *
      63                 :            :  * Called with j_list_lock held
      64                 :            :  */
      65                 :          0 : static inline void __buffer_relink_io(struct journal_head *jh)
      66                 :            : {
      67                 :          0 :         transaction_t *transaction = jh->b_cp_transaction;
      68                 :            : 
      69                 :            :         __buffer_unlink_first(jh);
      70                 :            : 
      71         [ #  # ]:          0 :         if (!transaction->t_checkpoint_io_list) {
      72                 :          0 :                 jh->b_cpnext = jh->b_cpprev = jh;
      73                 :            :         } else {
      74                 :          0 :                 jh->b_cpnext = transaction->t_checkpoint_io_list;
      75                 :          0 :                 jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
      76                 :          0 :                 jh->b_cpprev->b_cpnext = jh;
      77                 :          0 :                 jh->b_cpnext->b_cpprev = jh;
      78                 :            :         }
      79                 :          0 :         transaction->t_checkpoint_io_list = jh;
      80                 :          0 : }
      81                 :            : 
      82                 :            : /*
      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                 :            :  */
      89                 :      19192 : static int __try_to_free_cp_buf(struct journal_head *jh)
      90                 :            : {
      91                 :            :         int ret = 0;
      92                 :            :         struct buffer_head *bh = jh2bh(jh);
      93                 :            : 
      94   [ +  +  +  +  :      54082 :         if (jh->b_transaction == NULL && !buffer_locked(bh) &&
                   +  + ]
      95         [ +  - ]:      16925 :             !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
      96                 :            :                 JBUFFER_TRACE(jh, "remove from checkpoint list");
      97                 :      16925 :                 ret = __jbd2_journal_remove_checkpoint(jh) + 1;
      98                 :            :         }
      99                 :      19192 :         return ret;
     100                 :            : }
     101                 :            : 
     102                 :            : /*
     103                 :            :  * __jbd2_log_wait_for_space: wait until there is space in the journal.
     104                 :            :  *
     105                 :            :  * Called under j-state_lock *only*.  It will be unlocked if we have to wait
     106                 :            :  * for a checkpoint to free up some space in the log.
     107                 :            :  */
     108                 :          0 : void __jbd2_log_wait_for_space(journal_t *journal)
     109                 :            : {
     110                 :            :         int nblocks, space_left;
     111                 :            :         /* assert_spin_locked(&journal->j_state_lock); */
     112                 :            : 
     113                 :            :         nblocks = jbd2_space_needed(journal);
     114         [ #  # ]:          0 :         while (jbd2_log_space_left(journal) < nblocks) {
     115                 :            :                 write_unlock(&journal->j_state_lock);
     116                 :          0 :                 mutex_lock_io(&journal->j_checkpoint_mutex);
     117                 :            : 
     118                 :            :                 /*
     119                 :            :                  * Test again, another process may have checkpointed while we
     120                 :            :                  * were waiting for the checkpoint lock. If there are no
     121                 :            :                  * transactions ready to be checkpointed, try to recover
     122                 :            :                  * journal space by calling cleanup_journal_tail(), and if
     123                 :            :                  * that doesn't work, by waiting for the currently committing
     124                 :            :                  * transaction to complete.  If there is absolutely no way
     125                 :            :                  * to make progress, this is either a BUG or corrupted
     126                 :            :                  * filesystem, so abort the journal and leave a stack
     127                 :            :                  * trace for forensic evidence.
     128                 :            :                  */
     129                 :          0 :                 write_lock(&journal->j_state_lock);
     130         [ #  # ]:          0 :                 if (journal->j_flags & JBD2_ABORT) {
     131                 :          0 :                         mutex_unlock(&journal->j_checkpoint_mutex);
     132                 :          0 :                         return;
     133                 :            :                 }
     134                 :            :                 spin_lock(&journal->j_list_lock);
     135                 :            :                 space_left = jbd2_log_space_left(journal);
     136         [ #  # ]:          0 :                 if (space_left < nblocks) {
     137                 :          0 :                         int chkpt = journal->j_checkpoint_transactions != NULL;
     138                 :            :                         tid_t tid = 0;
     139                 :            : 
     140         [ #  # ]:          0 :                         if (journal->j_committing_transaction)
     141                 :          0 :                                 tid = journal->j_committing_transaction->t_tid;
     142                 :            :                         spin_unlock(&journal->j_list_lock);
     143                 :            :                         write_unlock(&journal->j_state_lock);
     144         [ #  # ]:          0 :                         if (chkpt) {
     145                 :          0 :                                 jbd2_log_do_checkpoint(journal);
     146         [ #  # ]:          0 :                         } else if (jbd2_cleanup_journal_tail(journal) == 0) {
     147                 :            :                                 /* We were able to recover space; yay! */
     148                 :            :                                 ;
     149         [ #  # ]:          0 :                         } else if (tid) {
     150                 :            :                                 /*
     151                 :            :                                  * jbd2_journal_commit_transaction() may want
     152                 :            :                                  * to take the checkpoint_mutex if JBD2_FLUSHED
     153                 :            :                                  * is set.  So we need to temporarily drop it.
     154                 :            :                                  */
     155                 :          0 :                                 mutex_unlock(&journal->j_checkpoint_mutex);
     156                 :          0 :                                 jbd2_log_wait_commit(journal, tid);
     157                 :          0 :                                 write_lock(&journal->j_state_lock);
     158                 :          0 :                                 continue;
     159                 :            :                         } else {
     160                 :          0 :                                 printk(KERN_ERR "%s: needed %d blocks and "
     161                 :            :                                        "only had %d space available\n",
     162                 :            :                                        __func__, nblocks, space_left);
     163                 :          0 :                                 printk(KERN_ERR "%s: no way to get more "
     164                 :            :                                        "journal space in %s\n", __func__,
     165                 :          0 :                                        journal->j_devname);
     166                 :          0 :                                 WARN_ON(1);
     167                 :          0 :                                 jbd2_journal_abort(journal, -EIO);
     168                 :            :                         }
     169                 :          0 :                         write_lock(&journal->j_state_lock);
     170                 :            :                 } else {
     171                 :            :                         spin_unlock(&journal->j_list_lock);
     172                 :            :                 }
     173                 :          0 :                 mutex_unlock(&journal->j_checkpoint_mutex);
     174                 :            :         }
     175                 :            : }
     176                 :            : 
     177                 :            : static void
     178                 :          0 : __flush_batch(journal_t *journal, int *batch_count)
     179                 :            : {
     180                 :            :         int i;
     181                 :            :         struct blk_plug plug;
     182                 :            : 
     183                 :          0 :         blk_start_plug(&plug);
     184         [ #  # ]:          0 :         for (i = 0; i < *batch_count; i++)
     185                 :          0 :                 write_dirty_buffer(journal->j_chkpt_bhs[i], REQ_SYNC);
     186                 :          0 :         blk_finish_plug(&plug);
     187                 :            : 
     188         [ #  # ]:          0 :         for (i = 0; i < *batch_count; i++) {
     189                 :          0 :                 struct buffer_head *bh = journal->j_chkpt_bhs[i];
     190                 :            :                 BUFFER_TRACE(bh, "brelse");
     191                 :          0 :                 __brelse(bh);
     192                 :            :         }
     193                 :          0 :         *batch_count = 0;
     194                 :          0 : }
     195                 :            : 
     196                 :            : /*
     197                 :            :  * Perform an actual checkpoint. We take the first transaction on the
     198                 :            :  * list of transactions to be checkpointed and send all its buffers
     199                 :            :  * to disk. We submit larger chunks of data at once.
     200                 :            :  *
     201                 :            :  * The journal should be locked before calling this function.
     202                 :            :  * Called with j_checkpoint_mutex held.
     203                 :            :  */
     204                 :          0 : int jbd2_log_do_checkpoint(journal_t *journal)
     205                 :            : {
     206                 :            :         struct journal_head     *jh;
     207                 :            :         struct buffer_head      *bh;
     208                 :            :         transaction_t           *transaction;
     209                 :            :         tid_t                   this_tid;
     210                 :          0 :         int                     result, batch_count = 0;
     211                 :            : 
     212                 :            :         jbd_debug(1, "Start checkpoint\n");
     213                 :            : 
     214                 :            :         /*
     215                 :            :          * First thing: if there are any transactions in the log which
     216                 :            :          * don't need checkpointing, just eliminate them from the
     217                 :            :          * journal straight away.
     218                 :            :          */
     219                 :          0 :         result = jbd2_cleanup_journal_tail(journal);
     220                 :          0 :         trace_jbd2_checkpoint(journal, result);
     221                 :            :         jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
     222         [ #  # ]:          0 :         if (result <= 0)
     223                 :            :                 return result;
     224                 :            : 
     225                 :            :         /*
     226                 :            :          * OK, we need to start writing disk blocks.  Take one transaction
     227                 :            :          * and write it.
     228                 :            :          */
     229                 :            :         result = 0;
     230                 :            :         spin_lock(&journal->j_list_lock);
     231         [ #  # ]:          0 :         if (!journal->j_checkpoint_transactions)
     232                 :            :                 goto out;
     233                 :            :         transaction = journal->j_checkpoint_transactions;
     234         [ #  # ]:          0 :         if (transaction->t_chp_stats.cs_chp_time == 0)
     235                 :          0 :                 transaction->t_chp_stats.cs_chp_time = jiffies;
     236                 :          0 :         this_tid = transaction->t_tid;
     237                 :            : restart:
     238                 :            :         /*
     239                 :            :          * If someone cleaned up this transaction while we slept, we're
     240                 :            :          * done (maybe it's a new transaction, but it fell at the same
     241                 :            :          * address).
     242                 :            :          */
     243   [ #  #  #  # ]:          0 :         if (journal->j_checkpoint_transactions != transaction ||
     244                 :          0 :             transaction->t_tid != this_tid)
     245                 :            :                 goto out;
     246                 :            : 
     247                 :            :         /* checkpoint all of the transaction's buffers */
     248         [ #  # ]:          0 :         while (transaction->t_checkpoint_list) {
     249                 :            :                 jh = transaction->t_checkpoint_list;
     250                 :            :                 bh = jh2bh(jh);
     251                 :            : 
     252         [ #  # ]:          0 :                 if (buffer_locked(bh)) {
     253                 :            :                         get_bh(bh);
     254                 :            :                         spin_unlock(&journal->j_list_lock);
     255                 :          0 :                         wait_on_buffer(bh);
     256                 :            :                         /* the journal_head may have gone by now */
     257                 :            :                         BUFFER_TRACE(bh, "brelse");
     258                 :          0 :                         __brelse(bh);
     259                 :          0 :                         goto retry;
     260                 :            :                 }
     261         [ #  # ]:          0 :                 if (jh->b_transaction != NULL) {
     262                 :          0 :                         transaction_t *t = jh->b_transaction;
     263                 :          0 :                         tid_t tid = t->t_tid;
     264                 :            : 
     265                 :          0 :                         transaction->t_chp_stats.cs_forced_to_close++;
     266                 :            :                         spin_unlock(&journal->j_list_lock);
     267         [ #  # ]:          0 :                         if (unlikely(journal->j_flags & JBD2_UNMOUNT))
     268                 :            :                                 /*
     269                 :            :                                  * The journal thread is dead; so
     270                 :            :                                  * starting and waiting for a commit
     271                 :            :                                  * to finish will cause us to wait for
     272                 :            :                                  * a _very_ long time.
     273                 :            :                                  */
     274                 :          0 :                                 printk(KERN_ERR
     275                 :            :                 "JBD2: %s: Waiting for Godot: block %llu\n",
     276                 :          0 :                 journal->j_devname, (unsigned long long) bh->b_blocknr);
     277                 :            : 
     278         [ #  # ]:          0 :                         if (batch_count)
     279                 :          0 :                                 __flush_batch(journal, &batch_count);
     280                 :          0 :                         jbd2_log_start_commit(journal, tid);
     281                 :            :                         /*
     282                 :            :                          * jbd2_journal_commit_transaction() may want
     283                 :            :                          * to take the checkpoint_mutex if JBD2_FLUSHED
     284                 :            :                          * is set, jbd2_update_log_tail() called by
     285                 :            :                          * jbd2_journal_commit_transaction() may also take
     286                 :            :                          * checkpoint_mutex.  So we need to temporarily
     287                 :            :                          * drop it.
     288                 :            :                          */
     289                 :          0 :                         mutex_unlock(&journal->j_checkpoint_mutex);
     290                 :          0 :                         jbd2_log_wait_commit(journal, tid);
     291                 :          0 :                         mutex_lock_io(&journal->j_checkpoint_mutex);
     292                 :            :                         spin_lock(&journal->j_list_lock);
     293                 :            :                         goto restart;
     294                 :            :                 }
     295         [ #  # ]:          0 :                 if (!buffer_dirty(bh)) {
     296   [ #  #  #  # ]:          0 :                         if (unlikely(buffer_write_io_error(bh)) && !result)
     297                 :            :                                 result = -EIO;
     298                 :            :                         BUFFER_TRACE(bh, "remove from checkpoint");
     299         [ #  # ]:          0 :                         if (__jbd2_journal_remove_checkpoint(jh))
     300                 :            :                                 /* The transaction was released; we're done */
     301                 :            :                                 goto out;
     302                 :          0 :                         continue;
     303                 :            :                 }
     304                 :            :                 /*
     305                 :            :                  * Important: we are about to write the buffer, and
     306                 :            :                  * possibly block, while still holding the journal
     307                 :            :                  * lock.  We cannot afford to let the transaction
     308                 :            :                  * logic start messing around with this buffer before
     309                 :            :                  * we write it to disk, as that would break
     310                 :            :                  * recoverability.
     311                 :            :                  */
     312                 :            :                 BUFFER_TRACE(bh, "queue");
     313                 :            :                 get_bh(bh);
     314         [ #  # ]:          0 :                 J_ASSERT_BH(bh, !buffer_jwrite(bh));
     315                 :          0 :                 journal->j_chkpt_bhs[batch_count++] = bh;
     316                 :          0 :                 __buffer_relink_io(jh);
     317                 :          0 :                 transaction->t_chp_stats.cs_written++;
     318   [ #  #  #  # ]:          0 :                 if ((batch_count == JBD2_NR_BATCH) ||
     319                 :            :                     need_resched() ||
     320                 :            :                     spin_needbreak(&journal->j_list_lock))
     321                 :            :                         goto unlock_and_flush;
     322                 :            :         }
     323                 :            : 
     324         [ #  # ]:          0 :         if (batch_count) {
     325                 :            :                 unlock_and_flush:
     326                 :            :                         spin_unlock(&journal->j_list_lock);
     327                 :            :                 retry:
     328         [ #  # ]:          0 :                         if (batch_count)
     329                 :          0 :                                 __flush_batch(journal, &batch_count);
     330                 :            :                         spin_lock(&journal->j_list_lock);
     331                 :            :                         goto restart;
     332                 :            :         }
     333                 :            : 
     334                 :            :         /*
     335                 :            :          * Now we issued all of the transaction's buffers, let's deal
     336                 :            :          * with the buffers that are out for I/O.
     337                 :            :          */
     338                 :            : restart2:
     339                 :            :         /* Did somebody clean up the transaction in the meanwhile? */
     340   [ #  #  #  # ]:          0 :         if (journal->j_checkpoint_transactions != transaction ||
     341                 :          0 :             transaction->t_tid != this_tid)
     342                 :            :                 goto out;
     343                 :            : 
     344         [ #  # ]:          0 :         while (transaction->t_checkpoint_io_list) {
     345                 :            :                 jh = transaction->t_checkpoint_io_list;
     346                 :            :                 bh = jh2bh(jh);
     347         [ #  # ]:          0 :                 if (buffer_locked(bh)) {
     348                 :            :                         get_bh(bh);
     349                 :            :                         spin_unlock(&journal->j_list_lock);
     350                 :          0 :                         wait_on_buffer(bh);
     351                 :            :                         /* the journal_head may have gone by now */
     352                 :            :                         BUFFER_TRACE(bh, "brelse");
     353                 :          0 :                         __brelse(bh);
     354                 :            :                         spin_lock(&journal->j_list_lock);
     355                 :            :                         goto restart2;
     356                 :            :                 }
     357   [ #  #  #  # ]:          0 :                 if (unlikely(buffer_write_io_error(bh)) && !result)
     358                 :            :                         result = -EIO;
     359                 :            : 
     360                 :            :                 /*
     361                 :            :                  * Now in whatever state the buffer currently is, we
     362                 :            :                  * know that it has been written out and so we can
     363                 :            :                  * drop it from the list
     364                 :            :                  */
     365         [ #  # ]:          0 :                 if (__jbd2_journal_remove_checkpoint(jh))
     366                 :            :                         break;
     367                 :            :         }
     368                 :            : out:
     369                 :            :         spin_unlock(&journal->j_list_lock);
     370         [ #  # ]:          0 :         if (result < 0)
     371                 :          0 :                 jbd2_journal_abort(journal, result);
     372                 :            :         else
     373                 :          0 :                 result = jbd2_cleanup_journal_tail(journal);
     374                 :            : 
     375                 :          0 :         return (result < 0) ? result : 0;
     376                 :            : }
     377                 :            : 
     378                 :            : /*
     379                 :            :  * Check the list of checkpoint transactions for the journal to see if
     380                 :            :  * we have already got rid of any since the last update of the log tail
     381                 :            :  * in the journal superblock.  If so, we can instantly roll the
     382                 :            :  * superblock forward to remove those transactions from the log.
     383                 :            :  *
     384                 :            :  * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
     385                 :            :  *
     386                 :            :  * Called with the journal lock held.
     387                 :            :  *
     388                 :            :  * This is the only part of the journaling code which really needs to be
     389                 :            :  * aware of transaction aborts.  Checkpointing involves writing to the
     390                 :            :  * main filesystem area rather than to the journal, so it can proceed
     391                 :            :  * even in abort state, but we must not update the super block if
     392                 :            :  * checkpointing may have failed.  Otherwise, we would lose some metadata
     393                 :            :  * buffers which should be written-back to the filesystem.
     394                 :            :  */
     395                 :            : 
     396                 :          0 : int jbd2_cleanup_journal_tail(journal_t *journal)
     397                 :            : {
     398                 :            :         tid_t           first_tid;
     399                 :            :         unsigned long   blocknr;
     400                 :            : 
     401         [ #  # ]:          0 :         if (is_journal_aborted(journal))
     402                 :            :                 return -EIO;
     403                 :            : 
     404         [ #  # ]:          0 :         if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr))
     405                 :            :                 return 1;
     406         [ #  # ]:          0 :         J_ASSERT(blocknr != 0);
     407                 :            : 
     408                 :            :         /*
     409                 :            :          * We need to make sure that any blocks that were recently written out
     410                 :            :          * --- perhaps by jbd2_log_do_checkpoint() --- are flushed out before
     411                 :            :          * we drop the transactions from the journal. It's unlikely this will
     412                 :            :          * be necessary, especially with an appropriately sized journal, but we
     413                 :            :          * need this to guarantee correctness.  Fortunately
     414                 :            :          * jbd2_cleanup_journal_tail() doesn't get called all that often.
     415                 :            :          */
     416         [ #  # ]:          0 :         if (journal->j_flags & JBD2_BARRIER)
     417                 :          0 :                 blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);
     418                 :            : 
     419                 :          0 :         return __jbd2_update_log_tail(journal, first_tid, blocknr);
     420                 :            : }
     421                 :            : 
     422                 :            : 
     423                 :            : /* Checkpoint list management */
     424                 :            : 
     425                 :            : /*
     426                 :            :  * journal_clean_one_cp_list
     427                 :            :  *
     428                 :            :  * Find all the written-back checkpoint buffers in the given list and
     429                 :            :  * release them. If 'destroy' is set, clean all buffers unconditionally.
     430                 :            :  *
     431                 :            :  * Called with j_list_lock held.
     432                 :            :  * Returns 1 if we freed the transaction, 0 otherwise.
     433                 :            :  */
     434                 :       6175 : static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy)
     435                 :            : {
     436                 :            :         struct journal_head *last_jh;
     437                 :            :         struct journal_head *next_jh = jh;
     438                 :            :         int ret;
     439                 :            : 
     440         [ +  + ]:       6175 :         if (!jh)
     441                 :            :                 return 0;
     442                 :            : 
     443                 :       3910 :         last_jh = jh->b_cpprev;
     444                 :            :         do {
     445                 :            :                 jh = next_jh;
     446                 :      19192 :                 next_jh = jh->b_cpnext;
     447         [ +  - ]:      19192 :                 if (!destroy)
     448                 :      19192 :                         ret = __try_to_free_cp_buf(jh);
     449                 :            :                 else
     450                 :          0 :                         ret = __jbd2_journal_remove_checkpoint(jh) + 1;
     451         [ +  + ]:      19192 :                 if (!ret)
     452                 :            :                         return 0;
     453         [ +  + ]:      16925 :                 if (ret == 2)
     454                 :            :                         return 1;
     455                 :            :                 /*
     456                 :            :                  * This function only frees up some memory
     457                 :            :                  * if possible so we dont have an obligation
     458                 :            :                  * to finish processing. Bail out if preemption
     459                 :            :                  * requested:
     460                 :            :                  */
     461         [ +  + ]:      15285 :                 if (need_resched())
     462                 :            :                         return 0;
     463         [ +  - ]:      15282 :         } while (jh != last_jh);
     464                 :            : 
     465                 :            :         return 0;
     466                 :            : }
     467                 :            : 
     468                 :            : /*
     469                 :            :  * journal_clean_checkpoint_list
     470                 :            :  *
     471                 :            :  * Find all the written-back checkpoint buffers in the journal and release them.
     472                 :            :  * If 'destroy' is set, release all buffers unconditionally.
     473                 :            :  *
     474                 :            :  * Called with j_list_lock held.
     475                 :            :  */
     476                 :       2527 : void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
     477                 :            : {
     478                 :            :         transaction_t *transaction, *last_transaction, *next_transaction;
     479                 :            :         int ret;
     480                 :            : 
     481                 :       2527 :         transaction = journal->j_checkpoint_transactions;
     482         [ +  + ]:       2527 :         if (!transaction)
     483                 :            :                 return;
     484                 :            : 
     485                 :       2295 :         last_transaction = transaction->t_cpprev;
     486                 :            :         next_transaction = transaction;
     487                 :            :         do {
     488                 :            :                 transaction = next_transaction;
     489                 :       3910 :                 next_transaction = transaction->t_cpnext;
     490                 :       3910 :                 ret = journal_clean_one_cp_list(transaction->t_checkpoint_list,
     491                 :            :                                                 destroy);
     492                 :            :                 /*
     493                 :            :                  * This function only frees up some memory if possible so we
     494                 :            :                  * dont have an obligation to finish processing. Bail out if
     495                 :            :                  * preemption requested:
     496                 :            :                  */
     497         [ +  + ]:       3910 :                 if (need_resched())
     498                 :            :                         return;
     499         [ +  + ]:       3905 :                 if (ret)
     500                 :       1640 :                         continue;
     501                 :            :                 /*
     502                 :            :                  * It is essential that we are as careful as in the case of
     503                 :            :                  * t_checkpoint_list with removing the buffer from the list as
     504                 :            :                  * we can possibly see not yet submitted buffers on io_list
     505                 :            :                  */
     506                 :       2265 :                 ret = journal_clean_one_cp_list(transaction->
     507                 :            :                                 t_checkpoint_io_list, destroy);
     508         [ +  - ]:       2265 :                 if (need_resched())
     509                 :            :                         return;
     510                 :            :                 /*
     511                 :            :                  * Stop scanning if we couldn't free the transaction. This
     512                 :            :                  * avoids pointless scanning of transactions which still
     513                 :            :                  * weren't checkpointed.
     514                 :            :                  */
     515         [ -  + ]:       2265 :                 if (!ret)
     516                 :            :                         return;
     517         [ +  + ]:       1640 :         } while (transaction != last_transaction);
     518                 :            : }
     519                 :            : 
     520                 :            : /*
     521                 :            :  * Remove buffers from all checkpoint lists as journal is aborted and we just
     522                 :            :  * need to free memory
     523                 :            :  */
     524                 :          0 : void jbd2_journal_destroy_checkpoint(journal_t *journal)
     525                 :            : {
     526                 :            :         /*
     527                 :            :          * We loop because __jbd2_journal_clean_checkpoint_list() may abort
     528                 :            :          * early due to a need of rescheduling.
     529                 :            :          */
     530                 :            :         while (1) {
     531                 :            :                 spin_lock(&journal->j_list_lock);
     532         [ #  # ]:          0 :                 if (!journal->j_checkpoint_transactions) {
     533                 :            :                         spin_unlock(&journal->j_list_lock);
     534                 :            :                         break;
     535                 :            :                 }
     536                 :          0 :                 __jbd2_journal_clean_checkpoint_list(journal, true);
     537                 :            :                 spin_unlock(&journal->j_list_lock);
     538                 :          0 :                 cond_resched();
     539                 :          0 :         }
     540                 :          0 : }
     541                 :            : 
     542                 :            : /*
     543                 :            :  * journal_remove_checkpoint: called after a buffer has been committed
     544                 :            :  * to disk (either by being write-back flushed to disk, or being
     545                 :            :  * committed to the log).
     546                 :            :  *
     547                 :            :  * We cannot safely clean a transaction out of the log until all of the
     548                 :            :  * buffer updates committed in that transaction have safely been stored
     549                 :            :  * elsewhere on disk.  To achieve this, all of the buffers in a
     550                 :            :  * transaction need to be maintained on the transaction's checkpoint
     551                 :            :  * lists until they have been rewritten, at which point this function is
     552                 :            :  * called to remove the buffer from the existing transaction's
     553                 :            :  * checkpoint lists.
     554                 :            :  *
     555                 :            :  * The function returns 1 if it frees the transaction, 0 otherwise.
     556                 :            :  * The function can free jh and bh.
     557                 :            :  *
     558                 :            :  * This function is called with j_list_lock held.
     559                 :            :  */
     560                 :      43371 : int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
     561                 :            : {
     562                 :            :         struct transaction_chp_stats_s *stats;
     563                 :            :         transaction_t *transaction;
     564                 :            :         journal_t *journal;
     565                 :            :         int ret = 0;
     566                 :            : 
     567                 :            :         JBUFFER_TRACE(jh, "entry");
     568                 :            : 
     569         [ +  - ]:      43371 :         if ((transaction = jh->b_cp_transaction) == NULL) {
     570                 :            :                 JBUFFER_TRACE(jh, "not on transaction");
     571                 :            :                 goto out;
     572                 :            :         }
     573                 :      43371 :         journal = transaction->t_journal;
     574                 :            : 
     575                 :            :         JBUFFER_TRACE(jh, "removing from transaction");
     576                 :      43371 :         __buffer_unlink(jh);
     577                 :      43371 :         jh->b_cp_transaction = NULL;
     578                 :      43371 :         jbd2_journal_put_journal_head(jh);
     579                 :            : 
     580   [ +  +  +  - ]:      45214 :         if (transaction->t_checkpoint_list != NULL ||
     581                 :       1843 :             transaction->t_checkpoint_io_list != NULL)
     582                 :            :                 goto out;
     583                 :            : 
     584                 :            :         /*
     585                 :            :          * There is one special case to worry about: if we have just pulled the
     586                 :            :          * buffer off a running or committing transaction's checkpoing list,
     587                 :            :          * then even if the checkpoint list is empty, the transaction obviously
     588                 :            :          * cannot be dropped!
     589                 :            :          *
     590                 :            :          * The locking here around t_state is a bit sleazy.
     591                 :            :          * See the comment at the end of jbd2_journal_commit_transaction().
     592                 :            :          */
     593         [ +  - ]:       1843 :         if (transaction->t_state != T_FINISHED)
     594                 :            :                 goto out;
     595                 :            : 
     596                 :            :         /* OK, that was the last buffer for the transaction: we can now
     597                 :            :            safely remove this transaction from the log */
     598                 :       1843 :         stats = &transaction->t_chp_stats;
     599         [ -  + ]:       1843 :         if (stats->cs_chp_time)
     600                 :          0 :                 stats->cs_chp_time = jbd2_time_diff(stats->cs_chp_time,
     601                 :            :                                                     jiffies);
     602                 :       3686 :         trace_jbd2_checkpoint_stats(journal->j_fs_dev->bd_dev,
     603                 :       1843 :                                     transaction->t_tid, stats);
     604                 :            : 
     605                 :       1843 :         __jbd2_journal_drop_transaction(journal, transaction);
     606                 :       1843 :         jbd2_journal_free_transaction(transaction);
     607                 :            :         ret = 1;
     608                 :            : out:
     609                 :      43371 :         return ret;
     610                 :            : }
     611                 :            : 
     612                 :            : /*
     613                 :            :  * journal_insert_checkpoint: put a committed buffer onto a checkpoint
     614                 :            :  * list so that we know when it is safe to clean the transaction out of
     615                 :            :  * the log.
     616                 :            :  *
     617                 :            :  * Called with the journal locked.
     618                 :            :  * Called with j_list_lock held.
     619                 :            :  */
     620                 :      97807 : void __jbd2_journal_insert_checkpoint(struct journal_head *jh,
     621                 :            :                                transaction_t *transaction)
     622                 :            : {
     623                 :            :         JBUFFER_TRACE(jh, "entry");
     624   [ +  -  -  + ]:     195614 :         J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh)));
     625         [ -  + ]:      97807 :         J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
     626                 :            : 
     627                 :            :         /* Get reference for checkpointing transaction */
     628                 :      97807 :         jbd2_journal_grab_journal_head(jh2bh(jh));
     629                 :      97807 :         jh->b_cp_transaction = transaction;
     630                 :            : 
     631         [ +  + ]:      97807 :         if (!transaction->t_checkpoint_list) {
     632                 :       2500 :                 jh->b_cpnext = jh->b_cpprev = jh;
     633                 :            :         } else {
     634                 :      95307 :                 jh->b_cpnext = transaction->t_checkpoint_list;
     635                 :      95307 :                 jh->b_cpprev = transaction->t_checkpoint_list->b_cpprev;
     636                 :      95307 :                 jh->b_cpprev->b_cpnext = jh;
     637                 :      95307 :                 jh->b_cpnext->b_cpprev = jh;
     638                 :            :         }
     639                 :      97807 :         transaction->t_checkpoint_list = jh;
     640                 :      97807 : }
     641                 :            : 
     642                 :            : /*
     643                 :            :  * We've finished with this transaction structure: adios...
     644                 :            :  *
     645                 :            :  * The transaction must have no links except for the checkpoint by this
     646                 :            :  * point.
     647                 :            :  *
     648                 :            :  * Called with the journal locked.
     649                 :            :  * Called with j_list_lock held.
     650                 :            :  */
     651                 :            : 
     652                 :       1870 : void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transaction)
     653                 :            : {
     654         [ -  + ]:       1870 :         assert_spin_locked(&journal->j_list_lock);
     655         [ +  - ]:       1870 :         if (transaction->t_cpnext) {
     656                 :       1870 :                 transaction->t_cpnext->t_cpprev = transaction->t_cpprev;
     657                 :       1870 :                 transaction->t_cpprev->t_cpnext = transaction->t_cpnext;
     658         [ +  + ]:       1870 :                 if (journal->j_checkpoint_transactions == transaction)
     659                 :       1696 :                         journal->j_checkpoint_transactions =
     660                 :       1696 :                                 transaction->t_cpnext;
     661         [ +  + ]:       1870 :                 if (journal->j_checkpoint_transactions == transaction)
     662                 :         57 :                         journal->j_checkpoint_transactions = NULL;
     663                 :            :         }
     664                 :            : 
     665         [ -  + ]:       1870 :         J_ASSERT(transaction->t_state == T_FINISHED);
     666         [ -  + ]:       1870 :         J_ASSERT(transaction->t_buffers == NULL);
     667         [ -  + ]:       1870 :         J_ASSERT(transaction->t_forget == NULL);
     668         [ -  + ]:       1870 :         J_ASSERT(transaction->t_shadow_list == NULL);
     669         [ -  + ]:       1870 :         J_ASSERT(transaction->t_checkpoint_list == NULL);
     670         [ -  + ]:       1870 :         J_ASSERT(transaction->t_checkpoint_io_list == NULL);
     671         [ -  + ]:       1870 :         J_ASSERT(atomic_read(&transaction->t_updates) == 0);
     672         [ -  + ]:       1870 :         J_ASSERT(journal->j_committing_transaction != transaction);
     673         [ -  + ]:       1870 :         J_ASSERT(journal->j_running_transaction != transaction);
     674                 :            : 
     675                 :       1870 :         trace_jbd2_drop_transaction(journal, transaction);
     676                 :            : 
     677                 :            :         jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
     678                 :       1870 : }

Generated by: LCOV version 1.14