Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Interface between ext4 and JBD
0004  */
0005 
0006 #include "ext4_jbd2.h"
0007 
0008 #include <trace/events/ext4.h>
0009 
0010 int ext4_inode_journal_mode(struct inode *inode)
0011 {
0012     if (EXT4_JOURNAL(inode) == NULL)
0013         return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
0014     /* We do not support data journalling with delayed allocation */
0015     if (!S_ISREG(inode->i_mode) ||
0016         ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
0017         test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
0018         (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
0019         !test_opt(inode->i_sb, DELALLOC))) {
0020         /* We do not support data journalling for encrypted data */
0021         if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
0022             return EXT4_INODE_ORDERED_DATA_MODE;  /* ordered */
0023         return EXT4_INODE_JOURNAL_DATA_MODE;    /* journal data */
0024     }
0025     if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
0026         return EXT4_INODE_ORDERED_DATA_MODE;    /* ordered */
0027     if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
0028         return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
0029     BUG();
0030 }
0031 
0032 /* Just increment the non-pointer handle value */
0033 static handle_t *ext4_get_nojournal(void)
0034 {
0035     handle_t *handle = current->journal_info;
0036     unsigned long ref_cnt = (unsigned long)handle;
0037 
0038     BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
0039 
0040     ref_cnt++;
0041     handle = (handle_t *)ref_cnt;
0042 
0043     current->journal_info = handle;
0044     return handle;
0045 }
0046 
0047 
0048 /* Decrement the non-pointer handle value */
0049 static void ext4_put_nojournal(handle_t *handle)
0050 {
0051     unsigned long ref_cnt = (unsigned long)handle;
0052 
0053     BUG_ON(ref_cnt == 0);
0054 
0055     ref_cnt--;
0056     handle = (handle_t *)ref_cnt;
0057 
0058     current->journal_info = handle;
0059 }
0060 
0061 /*
0062  * Wrappers for jbd2_journal_start/end.
0063  */
0064 static int ext4_journal_check_start(struct super_block *sb)
0065 {
0066     journal_t *journal;
0067 
0068     might_sleep();
0069 
0070     if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
0071         return -EIO;
0072 
0073     if (sb_rdonly(sb))
0074         return -EROFS;
0075     WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
0076     journal = EXT4_SB(sb)->s_journal;
0077     /*
0078      * Special case here: if the journal has aborted behind our
0079      * backs (eg. EIO in the commit thread), then we still need to
0080      * take the FS itself readonly cleanly.
0081      */
0082     if (journal && is_journal_aborted(journal)) {
0083         ext4_abort(sb, -journal->j_errno, "Detected aborted journal");
0084         return -EROFS;
0085     }
0086     return 0;
0087 }
0088 
0089 handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
0090                   int type, int blocks, int rsv_blocks,
0091                   int revoke_creds)
0092 {
0093     journal_t *journal;
0094     int err;
0095 
0096     trace_ext4_journal_start(sb, blocks, rsv_blocks, revoke_creds,
0097                  _RET_IP_);
0098     err = ext4_journal_check_start(sb);
0099     if (err < 0)
0100         return ERR_PTR(err);
0101 
0102     journal = EXT4_SB(sb)->s_journal;
0103     if (!journal || (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
0104         return ext4_get_nojournal();
0105     return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds,
0106                    GFP_NOFS, type, line);
0107 }
0108 
0109 int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
0110 {
0111     struct super_block *sb;
0112     int err;
0113     int rc;
0114 
0115     if (!ext4_handle_valid(handle)) {
0116         ext4_put_nojournal(handle);
0117         return 0;
0118     }
0119 
0120     err = handle->h_err;
0121     if (!handle->h_transaction) {
0122         rc = jbd2_journal_stop(handle);
0123         return err ? err : rc;
0124     }
0125 
0126     sb = handle->h_transaction->t_journal->j_private;
0127     rc = jbd2_journal_stop(handle);
0128 
0129     if (!err)
0130         err = rc;
0131     if (err)
0132         __ext4_std_error(sb, where, line, err);
0133     return err;
0134 }
0135 
0136 handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
0137                     int type)
0138 {
0139     struct super_block *sb;
0140     int err;
0141 
0142     if (!ext4_handle_valid(handle))
0143         return ext4_get_nojournal();
0144 
0145     sb = handle->h_journal->j_private;
0146     trace_ext4_journal_start_reserved(sb,
0147                 jbd2_handle_buffer_credits(handle), _RET_IP_);
0148     err = ext4_journal_check_start(sb);
0149     if (err < 0) {
0150         jbd2_journal_free_reserved(handle);
0151         return ERR_PTR(err);
0152     }
0153 
0154     err = jbd2_journal_start_reserved(handle, type, line);
0155     if (err < 0)
0156         return ERR_PTR(err);
0157     return handle;
0158 }
0159 
0160 int __ext4_journal_ensure_credits(handle_t *handle, int check_cred,
0161                   int extend_cred, int revoke_cred)
0162 {
0163     if (!ext4_handle_valid(handle))
0164         return 0;
0165     if (is_handle_aborted(handle))
0166         return -EROFS;
0167     if (jbd2_handle_buffer_credits(handle) >= check_cred &&
0168         handle->h_revoke_credits >= revoke_cred)
0169         return 0;
0170     extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle));
0171     revoke_cred = max(0, revoke_cred - handle->h_revoke_credits);
0172     return ext4_journal_extend(handle, extend_cred, revoke_cred);
0173 }
0174 
0175 static void ext4_journal_abort_handle(const char *caller, unsigned int line,
0176                       const char *err_fn,
0177                       struct buffer_head *bh,
0178                       handle_t *handle, int err)
0179 {
0180     char nbuf[16];
0181     const char *errstr = ext4_decode_error(NULL, err, nbuf);
0182 
0183     BUG_ON(!ext4_handle_valid(handle));
0184 
0185     if (bh)
0186         BUFFER_TRACE(bh, "abort");
0187 
0188     if (!handle->h_err)
0189         handle->h_err = err;
0190 
0191     if (is_handle_aborted(handle))
0192         return;
0193 
0194     printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
0195            caller, line, errstr, err_fn);
0196 
0197     jbd2_journal_abort_handle(handle);
0198 }
0199 
0200 static void ext4_check_bdev_write_error(struct super_block *sb)
0201 {
0202     struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
0203     struct ext4_sb_info *sbi = EXT4_SB(sb);
0204     int err;
0205 
0206     /*
0207      * If the block device has write error flag, it may have failed to
0208      * async write out metadata buffers in the background. In this case,
0209      * we could read old data from disk and write it out again, which
0210      * may lead to on-disk filesystem inconsistency.
0211      */
0212     if (errseq_check(&mapping->wb_err, READ_ONCE(sbi->s_bdev_wb_err))) {
0213         spin_lock(&sbi->s_bdev_wb_lock);
0214         err = errseq_check_and_advance(&mapping->wb_err, &sbi->s_bdev_wb_err);
0215         spin_unlock(&sbi->s_bdev_wb_lock);
0216         if (err)
0217             ext4_error_err(sb, -err,
0218                        "Error while async write back metadata");
0219     }
0220 }
0221 
0222 int __ext4_journal_get_write_access(const char *where, unsigned int line,
0223                     handle_t *handle, struct super_block *sb,
0224                     struct buffer_head *bh,
0225                     enum ext4_journal_trigger_type trigger_type)
0226 {
0227     int err;
0228 
0229     might_sleep();
0230 
0231     if (bh->b_bdev->bd_super)
0232         ext4_check_bdev_write_error(bh->b_bdev->bd_super);
0233 
0234     if (ext4_handle_valid(handle)) {
0235         err = jbd2_journal_get_write_access(handle, bh);
0236         if (err) {
0237             ext4_journal_abort_handle(where, line, __func__, bh,
0238                           handle, err);
0239             return err;
0240         }
0241     }
0242     if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
0243         return 0;
0244     BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
0245     jbd2_journal_set_triggers(bh,
0246         &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
0247     return 0;
0248 }
0249 
0250 /*
0251  * The ext4 forget function must perform a revoke if we are freeing data
0252  * which has been journaled.  Metadata (eg. indirect blocks) must be
0253  * revoked in all cases.
0254  *
0255  * "bh" may be NULL: a metadata block may have been freed from memory
0256  * but there may still be a record of it in the journal, and that record
0257  * still needs to be revoked.
0258  */
0259 int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
0260           int is_metadata, struct inode *inode,
0261           struct buffer_head *bh, ext4_fsblk_t blocknr)
0262 {
0263     int err;
0264 
0265     might_sleep();
0266 
0267     trace_ext4_forget(inode, is_metadata, blocknr);
0268     BUFFER_TRACE(bh, "enter");
0269 
0270     ext4_debug("forgetting bh %p: is_metadata=%d, mode %o, data mode %x\n",
0271           bh, is_metadata, inode->i_mode,
0272           test_opt(inode->i_sb, DATA_FLAGS));
0273 
0274     /* In the no journal case, we can just do a bforget and return */
0275     if (!ext4_handle_valid(handle)) {
0276         bforget(bh);
0277         return 0;
0278     }
0279 
0280     /* Never use the revoke function if we are doing full data
0281      * journaling: there is no need to, and a V1 superblock won't
0282      * support it.  Otherwise, only skip the revoke on un-journaled
0283      * data blocks. */
0284 
0285     if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
0286         (!is_metadata && !ext4_should_journal_data(inode))) {
0287         if (bh) {
0288             BUFFER_TRACE(bh, "call jbd2_journal_forget");
0289             err = jbd2_journal_forget(handle, bh);
0290             if (err)
0291                 ext4_journal_abort_handle(where, line, __func__,
0292                               bh, handle, err);
0293             return err;
0294         }
0295         return 0;
0296     }
0297 
0298     /*
0299      * data!=journal && (is_metadata || should_journal_data(inode))
0300      */
0301     BUFFER_TRACE(bh, "call jbd2_journal_revoke");
0302     err = jbd2_journal_revoke(handle, blocknr, bh);
0303     if (err) {
0304         ext4_journal_abort_handle(where, line, __func__,
0305                       bh, handle, err);
0306         __ext4_error(inode->i_sb, where, line, true, -err, 0,
0307                  "error %d when attempting revoke", err);
0308     }
0309     BUFFER_TRACE(bh, "exit");
0310     return err;
0311 }
0312 
0313 int __ext4_journal_get_create_access(const char *where, unsigned int line,
0314                 handle_t *handle, struct super_block *sb,
0315                 struct buffer_head *bh,
0316                 enum ext4_journal_trigger_type trigger_type)
0317 {
0318     int err;
0319 
0320     if (!ext4_handle_valid(handle))
0321         return 0;
0322 
0323     err = jbd2_journal_get_create_access(handle, bh);
0324     if (err) {
0325         ext4_journal_abort_handle(where, line, __func__, bh, handle,
0326                       err);
0327         return err;
0328     }
0329     if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
0330         return 0;
0331     BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
0332     jbd2_journal_set_triggers(bh,
0333         &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
0334     return 0;
0335 }
0336 
0337 int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
0338                  handle_t *handle, struct inode *inode,
0339                  struct buffer_head *bh)
0340 {
0341     int err = 0;
0342 
0343     might_sleep();
0344 
0345     set_buffer_meta(bh);
0346     set_buffer_prio(bh);
0347     set_buffer_uptodate(bh);
0348     if (ext4_handle_valid(handle)) {
0349         err = jbd2_journal_dirty_metadata(handle, bh);
0350         /* Errors can only happen due to aborted journal or a nasty bug */
0351         if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) {
0352             ext4_journal_abort_handle(where, line, __func__, bh,
0353                           handle, err);
0354             if (inode == NULL) {
0355                 pr_err("EXT4: jbd2_journal_dirty_metadata "
0356                        "failed: handle type %u started at "
0357                        "line %u, credits %u/%u, errcode %d",
0358                        handle->h_type,
0359                        handle->h_line_no,
0360                        handle->h_requested_credits,
0361                        jbd2_handle_buffer_credits(handle), err);
0362                 return err;
0363             }
0364             ext4_error_inode(inode, where, line,
0365                      bh->b_blocknr,
0366                      "journal_dirty_metadata failed: "
0367                      "handle type %u started at line %u, "
0368                      "credits %u/%u, errcode %d",
0369                      handle->h_type,
0370                      handle->h_line_no,
0371                      handle->h_requested_credits,
0372                      jbd2_handle_buffer_credits(handle),
0373                      err);
0374         }
0375     } else {
0376         if (inode)
0377             mark_buffer_dirty_inode(bh, inode);
0378         else
0379             mark_buffer_dirty(bh);
0380         if (inode && inode_needs_sync(inode)) {
0381             sync_dirty_buffer(bh);
0382             if (buffer_req(bh) && !buffer_uptodate(bh)) {
0383                 ext4_error_inode_err(inode, where, line,
0384                              bh->b_blocknr, EIO,
0385                     "IO error syncing itable block");
0386                 err = -EIO;
0387             }
0388         }
0389     }
0390     return err;
0391 }