LCOV - code coverage report
Current view: top level - fs/ext4 - ext4_jbd2.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 136 185 73.5 %
Date: 2023-07-31 20:08:12 Functions: 11 12 91.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Interface between ext4 and JBD
       4             :  */
       5             : 
       6             : #include "ext4_jbd2.h"
       7             : 
       8             : #include <trace/events/ext4.h>
       9             : 
      10    37266815 : int ext4_inode_journal_mode(struct inode *inode)
      11             : {
      12    37266815 :         if (EXT4_JOURNAL(inode) == NULL)
      13             :                 return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
      14             :         /* We do not support data journalling with delayed allocation */
      15    36945568 :         if (!S_ISREG(inode->i_mode) ||
      16    36030198 :             ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
      17    36030198 :             test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
      18       73124 :             (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
      19       73124 :             !test_opt(inode->i_sb, DELALLOC))) {
      20             :                 /* We do not support data journalling for encrypted data */
      21      935297 :                 if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
      22             :                         return EXT4_INODE_ORDERED_DATA_MODE;  /* ordered */
      23      935297 :                 return EXT4_INODE_JOURNAL_DATA_MODE;    /* journal data */
      24             :         }
      25    36010271 :         if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
      26             :                 return EXT4_INODE_ORDERED_DATA_MODE;    /* ordered */
      27       30063 :         if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
      28             :                 return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
      29           0 :         BUG();
      30             : }
      31             : 
      32             : /* Just increment the non-pointer handle value */
      33             : static handle_t *ext4_get_nojournal(void)
      34             : {
      35      516233 :         handle_t *handle = current->journal_info;
      36      516233 :         unsigned long ref_cnt = (unsigned long)handle;
      37             : 
      38      516233 :         BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
      39             : 
      40      516233 :         ref_cnt++;
      41      516233 :         handle = (handle_t *)ref_cnt;
      42             : 
      43      516233 :         current->journal_info = handle;
      44      516233 :         return handle;
      45             : }
      46             : 
      47             : 
      48             : /* Decrement the non-pointer handle value */
      49             : static void ext4_put_nojournal(handle_t *handle)
      50             : {
      51      516233 :         unsigned long ref_cnt = (unsigned long)handle;
      52             : 
      53           0 :         BUG_ON(ref_cnt == 0);
      54             : 
      55      516233 :         ref_cnt--;
      56      516233 :         handle = (handle_t *)ref_cnt;
      57             : 
      58      516233 :         current->journal_info = handle;
      59             : }
      60             : 
      61             : /*
      62             :  * Wrappers for jbd2_journal_start/end.
      63             :  */
      64    56520182 : static int ext4_journal_check_start(struct super_block *sb)
      65             : {
      66    56520182 :         journal_t *journal;
      67             : 
      68    56520182 :         might_sleep();
      69             : 
      70   113182514 :         if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
      71             :                 return -EIO;
      72             : 
      73    56540593 :         if (sb_rdonly(sb))
      74             :                 return -EROFS;
      75    56540591 :         WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
      76    56540591 :         journal = EXT4_SB(sb)->s_journal;
      77             :         /*
      78             :          * Special case here: if the journal has aborted behind our
      79             :          * backs (eg. EIO in the commit thread), then we still need to
      80             :          * take the FS itself readonly cleanly.
      81             :          */
      82    56540591 :         if (journal && is_journal_aborted(journal)) {
      83           1 :                 ext4_abort(sb, -journal->j_errno, "Detected aborted journal");
      84           1 :                 return -EROFS;
      85             :         }
      86             :         return 0;
      87             : }
      88             : 
      89    55469567 : handle_t *__ext4_journal_start_sb(struct inode *inode,
      90             :                                   struct super_block *sb, unsigned int line,
      91             :                                   int type, int blocks, int rsv_blocks,
      92             :                                   int revoke_creds)
      93             : {
      94    55469567 :         journal_t *journal;
      95    55469567 :         int err;
      96    55469567 :         if (inode)
      97    52684462 :                 trace_ext4_journal_start_inode(inode, blocks, rsv_blocks,
      98             :                                         revoke_creds, type,
      99    52692098 :                                         _RET_IP_);
     100             :         else
     101     2774551 :                 trace_ext4_journal_start_sb(sb, blocks, rsv_blocks,
     102             :                                         revoke_creds, type,
     103     2777469 :                                         _RET_IP_);
     104    55401026 :         err = ext4_journal_check_start(sb);
     105    55423526 :         if (err < 0)
     106       50651 :                 return ERR_PTR(err);
     107             : 
     108    55372875 :         journal = EXT4_SB(sb)->s_journal;
     109    55372875 :         if (!journal || (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
     110      516233 :                 return ext4_get_nojournal();
     111    54856642 :         return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds,
     112             :                                    GFP_NOFS, type, line);
     113             : }
     114             : 
     115    56607504 : int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
     116             : {
     117    56607504 :         struct super_block *sb;
     118    56607504 :         int err;
     119    56607504 :         int rc;
     120             : 
     121    56607504 :         if (!ext4_handle_valid(handle)) {
     122      516233 :                 ext4_put_nojournal(handle);
     123      516233 :                 return 0;
     124             :         }
     125             : 
     126    56091271 :         err = handle->h_err;
     127    56091271 :         if (!handle->h_transaction) {
     128           0 :                 rc = jbd2_journal_stop(handle);
     129           0 :                 return err ? err : rc;
     130             :         }
     131             : 
     132    56091271 :         sb = handle->h_transaction->t_journal->j_private;
     133    56091271 :         rc = jbd2_journal_stop(handle);
     134             : 
     135    56089729 :         if (!err)
     136    56064249 :                 err = rc;
     137    56089729 :         if (err)
     138           0 :                 __ext4_std_error(sb, where, line, err);
     139             :         return err;
     140             : }
     141             : 
     142     1122615 : handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
     143             :                                         int type)
     144             : {
     145     1122615 :         struct super_block *sb;
     146     1122615 :         int err;
     147             : 
     148     1122615 :         if (!ext4_handle_valid(handle))
     149           0 :                 return ext4_get_nojournal();
     150             : 
     151     1122615 :         sb = handle->h_journal->j_private;
     152     1122615 :         trace_ext4_journal_start_reserved(sb,
     153     1122615 :                                 jbd2_handle_buffer_credits(handle), _RET_IP_);
     154     1122615 :         err = ext4_journal_check_start(sb);
     155     1122615 :         if (err < 0) {
     156          16 :                 jbd2_journal_free_reserved(handle);
     157          16 :                 return ERR_PTR(err);
     158             :         }
     159             : 
     160     1122599 :         err = jbd2_journal_start_reserved(handle, type, line);
     161     1122599 :         if (err < 0)
     162           0 :                 return ERR_PTR(err);
     163             :         return handle;
     164             : }
     165             : 
     166     4622223 : int __ext4_journal_ensure_credits(handle_t *handle, int check_cred,
     167             :                                   int extend_cred, int revoke_cred)
     168             : {
     169     4622223 :         if (!ext4_handle_valid(handle))
     170             :                 return 0;
     171     9244444 :         if (is_handle_aborted(handle))
     172             :                 return -EROFS;
     173     4622222 :         if (jbd2_handle_buffer_credits(handle) >= check_cred &&
     174     4605990 :             handle->h_revoke_credits >= revoke_cred)
     175             :                 return 0;
     176       15964 :         extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle));
     177       15994 :         revoke_cred = max(0, revoke_cred - handle->h_revoke_credits);
     178       15994 :         return ext4_journal_extend(handle, extend_cred, revoke_cred);
     179             : }
     180             : 
     181           0 : static void ext4_journal_abort_handle(const char *caller, unsigned int line,
     182             :                                       const char *err_fn,
     183             :                                       struct buffer_head *bh,
     184             :                                       handle_t *handle, int err)
     185             : {
     186           0 :         char nbuf[16];
     187           0 :         const char *errstr = ext4_decode_error(NULL, err, nbuf);
     188             : 
     189           0 :         BUG_ON(!ext4_handle_valid(handle));
     190             : 
     191           0 :         if (bh)
     192           0 :                 BUFFER_TRACE(bh, "abort");
     193             : 
     194           0 :         if (!handle->h_err)
     195           0 :                 handle->h_err = err;
     196             : 
     197           0 :         if (is_handle_aborted(handle))
     198           0 :                 return;
     199             : 
     200           0 :         printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
     201             :                caller, line, errstr, err_fn);
     202             : 
     203           0 :         jbd2_journal_abort_handle(handle);
     204             : }
     205             : 
     206   121200898 : static void ext4_check_bdev_write_error(struct super_block *sb)
     207             : {
     208   121200898 :         struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
     209   121200898 :         struct ext4_sb_info *sbi = EXT4_SB(sb);
     210   121200898 :         int err;
     211             : 
     212             :         /*
     213             :          * If the block device has write error flag, it may have failed to
     214             :          * async write out metadata buffers in the background. In this case,
     215             :          * we could read old data from disk and write it out again, which
     216             :          * may lead to on-disk filesystem inconsistency.
     217             :          */
     218   121200898 :         if (errseq_check(&mapping->wb_err, READ_ONCE(sbi->s_bdev_wb_err))) {
     219           0 :                 spin_lock(&sbi->s_bdev_wb_lock);
     220           0 :                 err = errseq_check_and_advance(&mapping->wb_err, &sbi->s_bdev_wb_err);
     221           0 :                 spin_unlock(&sbi->s_bdev_wb_lock);
     222           0 :                 if (err)
     223           0 :                         ext4_error_err(sb, -err,
     224             :                                        "Error while async write back metadata");
     225             :         }
     226   121242037 : }
     227             : 
     228   121499628 : int __ext4_journal_get_write_access(const char *where, unsigned int line,
     229             :                                     handle_t *handle, struct super_block *sb,
     230             :                                     struct buffer_head *bh,
     231             :                                     enum ext4_journal_trigger_type trigger_type)
     232             : {
     233   121499628 :         int err;
     234             : 
     235   121499628 :         might_sleep();
     236             : 
     237   121614719 :         if (bh->b_bdev->bd_super)
     238   121228592 :                 ext4_check_bdev_write_error(bh->b_bdev->bd_super);
     239             : 
     240   121554458 :         if (ext4_handle_valid(handle)) {
     241   117638485 :                 err = jbd2_journal_get_write_access(handle, bh);
     242   117743224 :                 if (err) {
     243           0 :                         ext4_journal_abort_handle(where, line, __func__, bh,
     244             :                                                   handle, err);
     245           0 :                         return err;
     246             :                 }
     247             :         }
     248   121659197 :         if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
     249   121659197 :                 return 0;
     250           0 :         BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
     251           0 :         jbd2_journal_set_triggers(bh,
     252           0 :                 &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
     253           0 :         return 0;
     254             : }
     255             : 
     256             : /*
     257             :  * The ext4 forget function must perform a revoke if we are freeing data
     258             :  * which has been journaled.  Metadata (eg. indirect blocks) must be
     259             :  * revoked in all cases.
     260             :  *
     261             :  * "bh" may be NULL: a metadata block may have been freed from memory
     262             :  * but there may still be a record of it in the journal, and that record
     263             :  * still needs to be revoked.
     264             :  */
     265      278550 : int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
     266             :                   int is_metadata, struct inode *inode,
     267             :                   struct buffer_head *bh, ext4_fsblk_t blocknr)
     268             : {
     269      278550 :         int err;
     270             : 
     271      278550 :         might_sleep();
     272             : 
     273      278556 :         trace_ext4_forget(inode, is_metadata, blocknr);
     274      278557 :         BUFFER_TRACE(bh, "enter");
     275             : 
     276      278557 :         ext4_debug("forgetting bh %p: is_metadata=%d, mode %o, data mode %x\n",
     277             :                   bh, is_metadata, inode->i_mode,
     278             :                   test_opt(inode->i_sb, DATA_FLAGS));
     279             : 
     280             :         /* In the no journal case, we can just do a bforget and return */
     281      278557 :         if (!ext4_handle_valid(handle)) {
     282           0 :                 bforget(bh);
     283           0 :                 return 0;
     284             :         }
     285             : 
     286             :         /* Never use the revoke function if we are doing full data
     287             :          * journaling: there is no need to, and a V1 superblock won't
     288             :          * support it.  Otherwise, only skip the revoke on un-journaled
     289             :          * data blocks. */
     290             : 
     291      278557 :         if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
     292           0 :             (!is_metadata && !ext4_should_journal_data(inode))) {
     293        2073 :                 if (bh) {
     294        2073 :                         BUFFER_TRACE(bh, "call jbd2_journal_forget");
     295        2073 :                         err = jbd2_journal_forget(handle, bh);
     296        2079 :                         if (err)
     297           0 :                                 ext4_journal_abort_handle(where, line, __func__,
     298             :                                                           bh, handle, err);
     299        2079 :                         return err;
     300             :                 }
     301             :                 return 0;
     302             :         }
     303             : 
     304             :         /*
     305             :          * data!=journal && (is_metadata || should_journal_data(inode))
     306             :          */
     307      276484 :         BUFFER_TRACE(bh, "call jbd2_journal_revoke");
     308      276484 :         err = jbd2_journal_revoke(handle, blocknr, bh);
     309      276525 :         if (err) {
     310           0 :                 ext4_journal_abort_handle(where, line, __func__,
     311             :                                           bh, handle, err);
     312           0 :                 __ext4_error(inode->i_sb, where, line, true, -err, 0,
     313             :                              "error %d when attempting revoke", err);
     314             :         }
     315             :         BUFFER_TRACE(bh, "exit");
     316             :         return err;
     317             : }
     318             : 
     319      516987 : int __ext4_journal_get_create_access(const char *where, unsigned int line,
     320             :                                 handle_t *handle, struct super_block *sb,
     321             :                                 struct buffer_head *bh,
     322             :                                 enum ext4_journal_trigger_type trigger_type)
     323             : {
     324      516987 :         int err;
     325             : 
     326      516987 :         if (!ext4_handle_valid(handle))
     327             :                 return 0;
     328             : 
     329      400894 :         err = jbd2_journal_get_create_access(handle, bh);
     330      401335 :         if (err) {
     331           0 :                 ext4_journal_abort_handle(where, line, __func__, bh, handle,
     332             :                                           err);
     333           0 :                 return err;
     334             :         }
     335      401335 :         if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
     336      401335 :                 return 0;
     337           0 :         BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
     338           0 :         jbd2_journal_set_triggers(bh,
     339           0 :                 &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
     340           0 :         return 0;
     341             : }
     342             : 
     343   119381067 : int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
     344             :                                  handle_t *handle, struct inode *inode,
     345             :                                  struct buffer_head *bh)
     346             : {
     347   119381067 :         int err = 0;
     348             : 
     349   119381067 :         might_sleep();
     350             : 
     351   119380909 :         set_buffer_meta(bh);
     352   119380998 :         set_buffer_prio(bh);
     353   119381501 :         set_buffer_uptodate(bh);
     354   119381501 :         if (ext4_handle_valid(handle)) {
     355   115749969 :                 err = jbd2_journal_dirty_metadata(handle, bh);
     356             :                 /* Errors can only happen due to aborted journal or a nasty bug */
     357   231154998 :                 if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) {
     358           0 :                         ext4_journal_abort_handle(where, line, __func__, bh,
     359             :                                                   handle, err);
     360           0 :                         if (inode == NULL) {
     361           0 :                                 pr_err("EXT4: jbd2_journal_dirty_metadata "
     362             :                                        "failed: handle type %u started at "
     363             :                                        "line %u, credits %u/%u, errcode %d",
     364             :                                        handle->h_type,
     365             :                                        handle->h_line_no,
     366             :                                        handle->h_requested_credits,
     367             :                                        jbd2_handle_buffer_credits(handle), err);
     368           0 :                                 return err;
     369             :                         }
     370           0 :                         ext4_error_inode(inode, where, line,
     371             :                                          bh->b_blocknr,
     372             :                                          "journal_dirty_metadata failed: "
     373             :                                          "handle type %u started at line %u, "
     374             :                                          "credits %u/%u, errcode %d",
     375             :                                          handle->h_type,
     376             :                                          handle->h_line_no,
     377             :                                          handle->h_requested_credits,
     378             :                                          jbd2_handle_buffer_credits(handle),
     379             :                                          err);
     380             :                 }
     381             :         } else {
     382     3631532 :                 if (inode)
     383      664578 :                         mark_buffer_dirty_inode(bh, inode);
     384             :                 else
     385     2966954 :                         mark_buffer_dirty(bh);
     386     3631532 :                 if (inode && inode_needs_sync(inode)) {
     387          36 :                         sync_dirty_buffer(bh);
     388         108 :                         if (buffer_req(bh) && !buffer_uptodate(bh)) {
     389           0 :                                 ext4_error_inode_err(inode, where, line,
     390             :                                                      bh->b_blocknr, EIO,
     391             :                                         "IO error syncing itable block");
     392           0 :                                 err = -EIO;
     393             :                         }
     394             :                 }
     395             :         }
     396             :         return err;
     397             : }

Generated by: LCOV version 1.14