LCOV - code coverage report
Current view: top level - fs/ext4 - ext4_jbd2.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsx @ Mon Jul 31 20:08:34 PDT 2023 Lines: 134 185 72.4 %
Date: 2023-07-31 20:08:34 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    40732817 : int ext4_inode_journal_mode(struct inode *inode)
      11             : {
      12    40732817 :         if (EXT4_JOURNAL(inode) == NULL)
      13             :                 return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
      14             :         /* We do not support data journalling with delayed allocation */
      15    40411464 :         if (!S_ISREG(inode->i_mode) ||
      16    39443471 :             ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
      17    39443471 :             test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
      18       73110 :             (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
      19       73110 :             !test_opt(inode->i_sb, DELALLOC))) {
      20             :                 /* We do not support data journalling for encrypted data */
      21      987631 :                 if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
      22             :                         return EXT4_INODE_ORDERED_DATA_MODE;  /* ordered */
      23      987631 :                 return EXT4_INODE_JOURNAL_DATA_MODE;    /* journal data */
      24             :         }
      25    39423833 :         if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
      26             :                 return EXT4_INODE_ORDERED_DATA_MODE;    /* ordered */
      27       30018 :         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      516294 :         handle_t *handle = current->journal_info;
      36      516294 :         unsigned long ref_cnt = (unsigned long)handle;
      37             : 
      38      516294 :         BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
      39             : 
      40      516294 :         ref_cnt++;
      41      516294 :         handle = (handle_t *)ref_cnt;
      42             : 
      43      516294 :         current->journal_info = handle;
      44      516294 :         return handle;
      45             : }
      46             : 
      47             : 
      48             : /* Decrement the non-pointer handle value */
      49             : static void ext4_put_nojournal(handle_t *handle)
      50             : {
      51      516294 :         unsigned long ref_cnt = (unsigned long)handle;
      52             : 
      53           0 :         BUG_ON(ref_cnt == 0);
      54             : 
      55      516294 :         ref_cnt--;
      56      516294 :         handle = (handle_t *)ref_cnt;
      57             : 
      58      516294 :         current->journal_info = handle;
      59             : }
      60             : 
      61             : /*
      62             :  * Wrappers for jbd2_journal_start/end.
      63             :  */
      64    60722388 : static int ext4_journal_check_start(struct super_block *sb)
      65             : {
      66    60722388 :         journal_t *journal;
      67             : 
      68    60722388 :         might_sleep();
      69             : 
      70   121536564 :         if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
      71             :                 return -EIO;
      72             : 
      73    60717548 :         if (sb_rdonly(sb))
      74             :                 return -EROFS;
      75    60717546 :         WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
      76    60717546 :         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    60717546 :         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    59662606 : 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    59662606 :         journal_t *journal;
      95    59662606 :         int err;
      96    59662606 :         if (inode)
      97    56826118 :                 trace_ext4_journal_start_inode(inode, blocks, rsv_blocks,
      98             :                                         revoke_creds, type,
      99    56828778 :                                         _RET_IP_);
     100             :         else
     101     2830183 :                 trace_ext4_journal_start_sb(sb, blocks, rsv_blocks,
     102             :                                         revoke_creds, type,
     103     2833828 :                                         _RET_IP_);
     104    59613540 :         err = ext4_journal_check_start(sb);
     105    59625210 :         if (err < 0)
     106       50737 :                 return ERR_PTR(err);
     107             : 
     108    59574473 :         journal = EXT4_SB(sb)->s_journal;
     109    59574473 :         if (!journal || (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
     110      516294 :                 return ext4_get_nojournal();
     111    59058179 :         return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds,
     112             :                                    GFP_NOFS, type, line);
     113             : }
     114             : 
     115    60770934 : int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
     116             : {
     117    60770934 :         struct super_block *sb;
     118    60770934 :         int err;
     119    60770934 :         int rc;
     120             : 
     121    60770934 :         if (!ext4_handle_valid(handle)) {
     122      516294 :                 ext4_put_nojournal(handle);
     123      516294 :                 return 0;
     124             :         }
     125             : 
     126    60254640 :         err = handle->h_err;
     127    60254640 :         if (!handle->h_transaction) {
     128           0 :                 rc = jbd2_journal_stop(handle);
     129           0 :                 return err ? err : rc;
     130             :         }
     131             : 
     132    60254640 :         sb = handle->h_transaction->t_journal->j_private;
     133    60254640 :         rc = jbd2_journal_stop(handle);
     134             : 
     135    60240307 :         if (!err)
     136    60217038 :                 err = rc;
     137    60240307 :         if (err)
     138           0 :                 __ext4_std_error(sb, where, line, err);
     139             :         return err;
     140             : }
     141             : 
     142     1117341 : handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
     143             :                                         int type)
     144             : {
     145     1117341 :         struct super_block *sb;
     146     1117341 :         int err;
     147             : 
     148     1117341 :         if (!ext4_handle_valid(handle))
     149           0 :                 return ext4_get_nojournal();
     150             : 
     151     1117341 :         sb = handle->h_journal->j_private;
     152     1117341 :         trace_ext4_journal_start_reserved(sb,
     153     1117341 :                                 jbd2_handle_buffer_credits(handle), _RET_IP_);
     154     1117341 :         err = ext4_journal_check_start(sb);
     155     1117341 :         if (err < 0) {
     156           0 :                 jbd2_journal_free_reserved(handle);
     157           0 :                 return ERR_PTR(err);
     158             :         }
     159             : 
     160     1117341 :         err = jbd2_journal_start_reserved(handle, type, line);
     161     1117341 :         if (err < 0)
     162           0 :                 return ERR_PTR(err);
     163             :         return handle;
     164             : }
     165             : 
     166     4892386 : int __ext4_journal_ensure_credits(handle_t *handle, int check_cred,
     167             :                                   int extend_cred, int revoke_cred)
     168             : {
     169     4892386 :         if (!ext4_handle_valid(handle))
     170             :                 return 0;
     171     9784770 :         if (is_handle_aborted(handle))
     172             :                 return -EROFS;
     173     4892385 :         if (jbd2_handle_buffer_credits(handle) >= check_cred &&
     174     4877014 :             handle->h_revoke_credits >= revoke_cred)
     175             :                 return 0;
     176       17325 :         extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle));
     177       17385 :         revoke_cred = max(0, revoke_cred - handle->h_revoke_credits);
     178       17385 :         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   132967935 : static void ext4_check_bdev_write_error(struct super_block *sb)
     207             : {
     208   132967935 :         struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
     209   132967935 :         struct ext4_sb_info *sbi = EXT4_SB(sb);
     210   132967935 :         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   132967935 :         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   132981299 : }
     227             : 
     228   133197608 : 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   133197608 :         int err;
     234             : 
     235   133197608 :         might_sleep();
     236             : 
     237   133294030 :         if (bh->b_bdev->bd_super)
     238   132999738 :                 ext4_check_bdev_write_error(bh->b_bdev->bd_super);
     239             : 
     240   133194919 :         if (ext4_handle_valid(handle)) {
     241   129279942 :                 err = jbd2_journal_get_write_access(handle, bh);
     242   129403275 :                 if (err) {
     243           0 :                         ext4_journal_abort_handle(where, line, __func__, bh,
     244             :                                                   handle, err);
     245           0 :                         return err;
     246             :                 }
     247             :         }
     248   133318252 :         if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
     249   133318252 :                 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      289161 : 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      289161 :         int err;
     270             : 
     271      289161 :         might_sleep();
     272             : 
     273      289163 :         trace_ext4_forget(inode, is_metadata, blocknr);
     274      289161 :         BUFFER_TRACE(bh, "enter");
     275             : 
     276      289161 :         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      289161 :         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      289161 :         if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
     292           0 :             (!is_metadata && !ext4_should_journal_data(inode))) {
     293        2044 :                 if (bh) {
     294        2044 :                         BUFFER_TRACE(bh, "call jbd2_journal_forget");
     295        2044 :                         err = jbd2_journal_forget(handle, bh);
     296        2048 :                         if (err)
     297           0 :                                 ext4_journal_abort_handle(where, line, __func__,
     298             :                                                           bh, handle, err);
     299        2048 :                         return err;
     300             :                 }
     301             :                 return 0;
     302             :         }
     303             : 
     304             :         /*
     305             :          * data!=journal && (is_metadata || should_journal_data(inode))
     306             :          */
     307      287117 :         BUFFER_TRACE(bh, "call jbd2_journal_revoke");
     308      287117 :         err = jbd2_journal_revoke(handle, blocknr, bh);
     309      287160 :         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      533618 : 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      533618 :         int err;
     325             : 
     326      533618 :         if (!ext4_handle_valid(handle))
     327             :                 return 0;
     328             : 
     329      417465 :         err = jbd2_journal_get_create_access(handle, bh);
     330      417851 :         if (err) {
     331           0 :                 ext4_journal_abort_handle(where, line, __func__, bh, handle,
     332             :                                           err);
     333           0 :                 return err;
     334             :         }
     335      417851 :         if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
     336      417851 :                 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   131083806 : 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   131083806 :         int err = 0;
     348             : 
     349   131083806 :         might_sleep();
     350             : 
     351   131081899 :         set_buffer_meta(bh);
     352   131081954 :         set_buffer_prio(bh);
     353   131082512 :         set_buffer_uptodate(bh);
     354   131082512 :         if (ext4_handle_valid(handle)) {
     355   127450493 :                 err = jbd2_journal_dirty_metadata(handle, bh);
     356             :                 /* Errors can only happen due to aborted journal or a nasty bug */
     357   254567438 :                 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     3632019 :                 if (inode)
     383      664823 :                         mark_buffer_dirty_inode(bh, inode);
     384             :                 else
     385     2967196 :                         mark_buffer_dirty(bh);
     386     3632019 :                 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