1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 28984d137SAndrew Morton /* 38984d137SAndrew Morton * Interface between ext4 and JBD 48984d137SAndrew Morton */ 58984d137SAndrew Morton 63dcf5451SChristoph Hellwig #include "ext4_jbd2.h" 78984d137SAndrew Morton 8d6797d14STheodore Ts'o #include <trace/events/ext4.h> 9d6797d14STheodore Ts'o 1046797ad7SEric Biggers int ext4_inode_journal_mode(struct inode *inode) 1146797ad7SEric Biggers { 1246797ad7SEric Biggers if (EXT4_JOURNAL(inode) == NULL) 1346797ad7SEric Biggers return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */ 1446797ad7SEric Biggers /* We do not support data journalling with delayed allocation */ 1546797ad7SEric Biggers if (!S_ISREG(inode->i_mode) || 1646797ad7SEric Biggers ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) || 1746797ad7SEric Biggers test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || 1846797ad7SEric Biggers (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) && 1946797ad7SEric Biggers !test_opt(inode->i_sb, DELALLOC))) { 2046797ad7SEric Biggers /* We do not support data journalling for encrypted data */ 2146797ad7SEric Biggers if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) 2246797ad7SEric Biggers return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */ 2346797ad7SEric Biggers return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */ 2446797ad7SEric Biggers } 2546797ad7SEric Biggers if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) 2646797ad7SEric Biggers return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */ 2746797ad7SEric Biggers if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) 2846797ad7SEric Biggers return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */ 2946797ad7SEric Biggers BUG(); 3046797ad7SEric Biggers } 3146797ad7SEric Biggers 32722887ddSTheodore Ts'o /* Just increment the non-pointer handle value */ 33722887ddSTheodore Ts'o static handle_t *ext4_get_nojournal(void) 34722887ddSTheodore Ts'o { 35722887ddSTheodore Ts'o handle_t *handle = current->journal_info; 36722887ddSTheodore Ts'o unsigned long ref_cnt = (unsigned long)handle; 37722887ddSTheodore Ts'o 38722887ddSTheodore Ts'o BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT); 39722887ddSTheodore Ts'o 40722887ddSTheodore Ts'o ref_cnt++; 41722887ddSTheodore Ts'o handle = (handle_t *)ref_cnt; 42722887ddSTheodore Ts'o 43722887ddSTheodore Ts'o current->journal_info = handle; 44722887ddSTheodore Ts'o return handle; 45722887ddSTheodore Ts'o } 46722887ddSTheodore Ts'o 47722887ddSTheodore Ts'o 48722887ddSTheodore Ts'o /* Decrement the non-pointer handle value */ 49722887ddSTheodore Ts'o static void ext4_put_nojournal(handle_t *handle) 50722887ddSTheodore Ts'o { 51722887ddSTheodore Ts'o unsigned long ref_cnt = (unsigned long)handle; 52722887ddSTheodore Ts'o 53722887ddSTheodore Ts'o BUG_ON(ref_cnt == 0); 54722887ddSTheodore Ts'o 55722887ddSTheodore Ts'o ref_cnt--; 56722887ddSTheodore Ts'o handle = (handle_t *)ref_cnt; 57722887ddSTheodore Ts'o 58722887ddSTheodore Ts'o current->journal_info = handle; 59722887ddSTheodore Ts'o } 60722887ddSTheodore Ts'o 61722887ddSTheodore Ts'o /* 62722887ddSTheodore Ts'o * Wrappers for jbd2_journal_start/end. 63722887ddSTheodore Ts'o */ 645fe2fe89SJan Kara static int ext4_journal_check_start(struct super_block *sb) 65722887ddSTheodore Ts'o { 66722887ddSTheodore Ts'o journal_t *journal; 67722887ddSTheodore Ts'o 68b10a44c3STheodore Ts'o might_sleep(); 690db1ff22STheodore Ts'o 700db1ff22STheodore Ts'o if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) 710db1ff22STheodore Ts'o return -EIO; 720db1ff22STheodore Ts'o 73bc98a42cSDavid Howells if (sb_rdonly(sb)) 745fe2fe89SJan Kara return -EROFS; 75722887ddSTheodore Ts'o WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); 76722887ddSTheodore Ts'o journal = EXT4_SB(sb)->s_journal; 77722887ddSTheodore Ts'o /* 78722887ddSTheodore Ts'o * Special case here: if the journal has aborted behind our 79722887ddSTheodore Ts'o * backs (eg. EIO in the commit thread), then we still need to 80722887ddSTheodore Ts'o * take the FS itself readonly cleanly. 81722887ddSTheodore Ts'o */ 825fe2fe89SJan Kara if (journal && is_journal_aborted(journal)) { 8354d3adbcSTheodore Ts'o ext4_abort(sb, -journal->j_errno, "Detected aborted journal"); 845fe2fe89SJan Kara return -EROFS; 85722887ddSTheodore Ts'o } 865fe2fe89SJan Kara return 0; 875fe2fe89SJan Kara } 885fe2fe89SJan Kara 89*5f3e2403Schangfengnan handle_t *__ext4_journal_start_sb(struct inode *inode, 90*5f3e2403Schangfengnan struct super_block *sb, unsigned int line, 9183448bdfSJan Kara int type, int blocks, int rsv_blocks, 9283448bdfSJan Kara int revoke_creds) 935fe2fe89SJan Kara { 945fe2fe89SJan Kara journal_t *journal; 955fe2fe89SJan Kara int err; 96*5f3e2403Schangfengnan if (inode) 97*5f3e2403Schangfengnan trace_ext4_journal_start_inode(inode, blocks, rsv_blocks, 98*5f3e2403Schangfengnan revoke_creds, type, 99*5f3e2403Schangfengnan _RET_IP_); 100*5f3e2403Schangfengnan else 101*5f3e2403Schangfengnan trace_ext4_journal_start_sb(sb, blocks, rsv_blocks, 102*5f3e2403Schangfengnan revoke_creds, type, 10383448bdfSJan Kara _RET_IP_); 1045fe2fe89SJan Kara err = ext4_journal_check_start(sb); 1055fe2fe89SJan Kara if (err < 0) 1065fe2fe89SJan Kara return ERR_PTR(err); 1075fe2fe89SJan Kara 1085fe2fe89SJan Kara journal = EXT4_SB(sb)->s_journal; 1098016e29fSHarshad Shirwadkar if (!journal || (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) 1105fe2fe89SJan Kara return ext4_get_nojournal(); 11183448bdfSJan Kara return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds, 11283448bdfSJan Kara GFP_NOFS, type, line); 113722887ddSTheodore Ts'o } 114722887ddSTheodore Ts'o 115722887ddSTheodore Ts'o int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) 116722887ddSTheodore Ts'o { 117722887ddSTheodore Ts'o struct super_block *sb; 118722887ddSTheodore Ts'o int err; 119722887ddSTheodore Ts'o int rc; 120722887ddSTheodore Ts'o 121722887ddSTheodore Ts'o if (!ext4_handle_valid(handle)) { 122722887ddSTheodore Ts'o ext4_put_nojournal(handle); 123722887ddSTheodore Ts'o return 0; 124722887ddSTheodore Ts'o } 1259d506594SLukas Czerner 1266934da92SLukas Czerner err = handle->h_err; 1279d506594SLukas Czerner if (!handle->h_transaction) { 1286934da92SLukas Czerner rc = jbd2_journal_stop(handle); 1296934da92SLukas Czerner return err ? err : rc; 1309d506594SLukas Czerner } 1319d506594SLukas Czerner 132722887ddSTheodore Ts'o sb = handle->h_transaction->t_journal->j_private; 133722887ddSTheodore Ts'o rc = jbd2_journal_stop(handle); 134722887ddSTheodore Ts'o 135722887ddSTheodore Ts'o if (!err) 136722887ddSTheodore Ts'o err = rc; 137722887ddSTheodore Ts'o if (err) 138722887ddSTheodore Ts'o __ext4_std_error(sb, where, line, err); 139722887ddSTheodore Ts'o return err; 140722887ddSTheodore Ts'o } 141722887ddSTheodore Ts'o 1425fe2fe89SJan Kara handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line, 1435fe2fe89SJan Kara int type) 1445fe2fe89SJan Kara { 1455fe2fe89SJan Kara struct super_block *sb; 1465fe2fe89SJan Kara int err; 1475fe2fe89SJan Kara 1485fe2fe89SJan Kara if (!ext4_handle_valid(handle)) 1495fe2fe89SJan Kara return ext4_get_nojournal(); 1505fe2fe89SJan Kara 1515fe2fe89SJan Kara sb = handle->h_journal->j_private; 152a9a8344eSJan Kara trace_ext4_journal_start_reserved(sb, 153a9a8344eSJan Kara jbd2_handle_buffer_credits(handle), _RET_IP_); 1545fe2fe89SJan Kara err = ext4_journal_check_start(sb); 1555fe2fe89SJan Kara if (err < 0) { 1565fe2fe89SJan Kara jbd2_journal_free_reserved(handle); 1575fe2fe89SJan Kara return ERR_PTR(err); 1585fe2fe89SJan Kara } 1595fe2fe89SJan Kara 1605fe2fe89SJan Kara err = jbd2_journal_start_reserved(handle, type, line); 1615fe2fe89SJan Kara if (err < 0) 1625fe2fe89SJan Kara return ERR_PTR(err); 1635fe2fe89SJan Kara return handle; 1645fe2fe89SJan Kara } 1655fe2fe89SJan Kara 166a4130367SJan Kara int __ext4_journal_ensure_credits(handle_t *handle, int check_cred, 16783448bdfSJan Kara int extend_cred, int revoke_cred) 168a4130367SJan Kara { 169a4130367SJan Kara if (!ext4_handle_valid(handle)) 170a4130367SJan Kara return 0; 171298b5c52SYe Bin if (is_handle_aborted(handle)) 172298b5c52SYe Bin return -EROFS; 17383448bdfSJan Kara if (jbd2_handle_buffer_credits(handle) >= check_cred && 17483448bdfSJan Kara handle->h_revoke_credits >= revoke_cred) 175a4130367SJan Kara return 0; 17683448bdfSJan Kara extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle)); 17783448bdfSJan Kara revoke_cred = max(0, revoke_cred - handle->h_revoke_credits); 17883448bdfSJan Kara return ext4_journal_extend(handle, extend_cred, revoke_cred); 179a4130367SJan Kara } 180a4130367SJan Kara 181c197855eSStephen Hemminger static void ext4_journal_abort_handle(const char *caller, unsigned int line, 182c197855eSStephen Hemminger const char *err_fn, 183c197855eSStephen Hemminger struct buffer_head *bh, 184722887ddSTheodore Ts'o handle_t *handle, int err) 185722887ddSTheodore Ts'o { 186722887ddSTheodore Ts'o char nbuf[16]; 187722887ddSTheodore Ts'o const char *errstr = ext4_decode_error(NULL, err, nbuf); 188722887ddSTheodore Ts'o 189722887ddSTheodore Ts'o BUG_ON(!ext4_handle_valid(handle)); 190722887ddSTheodore Ts'o 191722887ddSTheodore Ts'o if (bh) 192722887ddSTheodore Ts'o BUFFER_TRACE(bh, "abort"); 193722887ddSTheodore Ts'o 194722887ddSTheodore Ts'o if (!handle->h_err) 195722887ddSTheodore Ts'o handle->h_err = err; 196722887ddSTheodore Ts'o 197722887ddSTheodore Ts'o if (is_handle_aborted(handle)) 198722887ddSTheodore Ts'o return; 199722887ddSTheodore Ts'o 200722887ddSTheodore Ts'o printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n", 201722887ddSTheodore Ts'o caller, line, errstr, err_fn); 202722887ddSTheodore Ts'o 203722887ddSTheodore Ts'o jbd2_journal_abort_handle(handle); 204722887ddSTheodore Ts'o } 205722887ddSTheodore Ts'o 206bc71726cSzhangyi (F) static void ext4_check_bdev_write_error(struct super_block *sb) 207bc71726cSzhangyi (F) { 208bc71726cSzhangyi (F) struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; 209bc71726cSzhangyi (F) struct ext4_sb_info *sbi = EXT4_SB(sb); 210bc71726cSzhangyi (F) int err; 211bc71726cSzhangyi (F) 212bc71726cSzhangyi (F) /* 213bc71726cSzhangyi (F) * If the block device has write error flag, it may have failed to 214bc71726cSzhangyi (F) * async write out metadata buffers in the background. In this case, 215bc71726cSzhangyi (F) * we could read old data from disk and write it out again, which 216bc71726cSzhangyi (F) * may lead to on-disk filesystem inconsistency. 217bc71726cSzhangyi (F) */ 218bc71726cSzhangyi (F) if (errseq_check(&mapping->wb_err, READ_ONCE(sbi->s_bdev_wb_err))) { 219bc71726cSzhangyi (F) spin_lock(&sbi->s_bdev_wb_lock); 220bc71726cSzhangyi (F) err = errseq_check_and_advance(&mapping->wb_err, &sbi->s_bdev_wb_err); 221bc71726cSzhangyi (F) spin_unlock(&sbi->s_bdev_wb_lock); 222bc71726cSzhangyi (F) if (err) 223bc71726cSzhangyi (F) ext4_error_err(sb, -err, 224bc71726cSzhangyi (F) "Error while async write back metadata"); 225bc71726cSzhangyi (F) } 226bc71726cSzhangyi (F) } 227bc71726cSzhangyi (F) 22890c7201bSTheodore Ts'o int __ext4_journal_get_write_access(const char *where, unsigned int line, 229188c299eSJan Kara handle_t *handle, struct super_block *sb, 230188c299eSJan Kara struct buffer_head *bh, 231188c299eSJan Kara enum ext4_journal_trigger_type trigger_type) 2328984d137SAndrew Morton { 233188c299eSJan Kara int err; 2340390131bSFrank Mayhar 235b10a44c3STheodore Ts'o might_sleep(); 236b10a44c3STheodore Ts'o 237bc71726cSzhangyi (F) if (bh->b_bdev->bd_super) 238bc71726cSzhangyi (F) ext4_check_bdev_write_error(bh->b_bdev->bd_super); 239bc71726cSzhangyi (F) 2400390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 2410390131bSFrank Mayhar err = jbd2_journal_get_write_access(handle, bh); 242188c299eSJan Kara if (err) { 24390c7201bSTheodore Ts'o ext4_journal_abort_handle(where, line, __func__, bh, 2440390131bSFrank Mayhar handle, err); 2458984d137SAndrew Morton return err; 2468984d137SAndrew Morton } 247188c299eSJan Kara } 248188c299eSJan Kara if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb)) 249188c299eSJan Kara return 0; 250188c299eSJan Kara BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT); 251188c299eSJan Kara jbd2_journal_set_triggers(bh, 252188c299eSJan Kara &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers); 253188c299eSJan Kara return 0; 254188c299eSJan Kara } 2558984d137SAndrew Morton 256d6797d14STheodore Ts'o /* 257d6797d14STheodore Ts'o * The ext4 forget function must perform a revoke if we are freeing data 258d6797d14STheodore Ts'o * which has been journaled. Metadata (eg. indirect blocks) must be 259d6797d14STheodore Ts'o * revoked in all cases. 260d6797d14STheodore Ts'o * 261d6797d14STheodore Ts'o * "bh" may be NULL: a metadata block may have been freed from memory 262d6797d14STheodore Ts'o * but there may still be a record of it in the journal, and that record 263d6797d14STheodore Ts'o * still needs to be revoked. 264d6797d14STheodore Ts'o */ 26590c7201bSTheodore Ts'o int __ext4_forget(const char *where, unsigned int line, handle_t *handle, 26690c7201bSTheodore Ts'o int is_metadata, struct inode *inode, 26790c7201bSTheodore Ts'o struct buffer_head *bh, ext4_fsblk_t blocknr) 268d6797d14STheodore Ts'o { 269d6797d14STheodore Ts'o int err; 270d6797d14STheodore Ts'o 271d6797d14STheodore Ts'o might_sleep(); 272d6797d14STheodore Ts'o 273d6797d14STheodore Ts'o trace_ext4_forget(inode, is_metadata, blocknr); 274d6797d14STheodore Ts'o BUFFER_TRACE(bh, "enter"); 275d6797d14STheodore Ts'o 2764978c659SJan Kara ext4_debug("forgetting bh %p: is_metadata=%d, mode %o, data mode %x\n", 277d6797d14STheodore Ts'o bh, is_metadata, inode->i_mode, 278d6797d14STheodore Ts'o test_opt(inode->i_sb, DATA_FLAGS)); 279d6797d14STheodore Ts'o 280e4684b3fSTheodore Ts'o /* In the no journal case, we can just do a bforget and return */ 281e4684b3fSTheodore Ts'o if (!ext4_handle_valid(handle)) { 282e4684b3fSTheodore Ts'o bforget(bh); 283e4684b3fSTheodore Ts'o return 0; 284e4684b3fSTheodore Ts'o } 285e4684b3fSTheodore Ts'o 286d6797d14STheodore Ts'o /* Never use the revoke function if we are doing full data 287d6797d14STheodore Ts'o * journaling: there is no need to, and a V1 superblock won't 288d6797d14STheodore Ts'o * support it. Otherwise, only skip the revoke on un-journaled 289d6797d14STheodore Ts'o * data blocks. */ 290d6797d14STheodore Ts'o 291d6797d14STheodore Ts'o if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || 292d6797d14STheodore Ts'o (!is_metadata && !ext4_should_journal_data(inode))) { 293d6797d14STheodore Ts'o if (bh) { 294d6797d14STheodore Ts'o BUFFER_TRACE(bh, "call jbd2_journal_forget"); 295b7e57e7cSTheodore Ts'o err = jbd2_journal_forget(handle, bh); 296b7e57e7cSTheodore Ts'o if (err) 29790c7201bSTheodore Ts'o ext4_journal_abort_handle(where, line, __func__, 29890c7201bSTheodore Ts'o bh, handle, err); 299b7e57e7cSTheodore Ts'o return err; 300d6797d14STheodore Ts'o } 301d6797d14STheodore Ts'o return 0; 302d6797d14STheodore Ts'o } 303d6797d14STheodore Ts'o 304d6797d14STheodore Ts'o /* 305d6797d14STheodore Ts'o * data!=journal && (is_metadata || should_journal_data(inode)) 306d6797d14STheodore Ts'o */ 307e4684b3fSTheodore Ts'o BUFFER_TRACE(bh, "call jbd2_journal_revoke"); 308e4684b3fSTheodore Ts'o err = jbd2_journal_revoke(handle, blocknr, bh); 309e4684b3fSTheodore Ts'o if (err) { 31090c7201bSTheodore Ts'o ext4_journal_abort_handle(where, line, __func__, 31190c7201bSTheodore Ts'o bh, handle, err); 312014c9caaSJan Kara __ext4_error(inode->i_sb, where, line, true, -err, 0, 313d6797d14STheodore Ts'o "error %d when attempting revoke", err); 314e4684b3fSTheodore Ts'o } 315d6797d14STheodore Ts'o BUFFER_TRACE(bh, "exit"); 316d6797d14STheodore Ts'o return err; 317d6797d14STheodore Ts'o } 318d6797d14STheodore Ts'o 31990c7201bSTheodore Ts'o int __ext4_journal_get_create_access(const char *where, unsigned int line, 320188c299eSJan Kara handle_t *handle, struct super_block *sb, 321188c299eSJan Kara struct buffer_head *bh, 322188c299eSJan Kara enum ext4_journal_trigger_type trigger_type) 3238984d137SAndrew Morton { 324188c299eSJan Kara int err; 3250390131bSFrank Mayhar 326188c299eSJan Kara if (!ext4_handle_valid(handle)) 327188c299eSJan Kara return 0; 328188c299eSJan Kara 3290390131bSFrank Mayhar err = jbd2_journal_get_create_access(handle, bh); 330188c299eSJan Kara if (err) { 331188c299eSJan Kara ext4_journal_abort_handle(where, line, __func__, bh, handle, 332188c299eSJan Kara err); 3338984d137SAndrew Morton return err; 3348984d137SAndrew Morton } 335188c299eSJan Kara if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb)) 336188c299eSJan Kara return 0; 337188c299eSJan Kara BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT); 338188c299eSJan Kara jbd2_journal_set_triggers(bh, 339188c299eSJan Kara &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers); 340188c299eSJan Kara return 0; 341188c299eSJan Kara } 3428984d137SAndrew Morton 34390c7201bSTheodore Ts'o int __ext4_handle_dirty_metadata(const char *where, unsigned int line, 34490c7201bSTheodore Ts'o handle_t *handle, struct inode *inode, 34590c7201bSTheodore Ts'o struct buffer_head *bh) 3468984d137SAndrew Morton { 3470390131bSFrank Mayhar int err = 0; 3480390131bSFrank Mayhar 349b10a44c3STheodore Ts'o might_sleep(); 350b10a44c3STheodore Ts'o 35113fca323STheodore Ts'o set_buffer_meta(bh); 35213fca323STheodore Ts'o set_buffer_prio(bh); 353558d6450SYe Bin set_buffer_uptodate(bh); 3540390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 3550390131bSFrank Mayhar err = jbd2_journal_dirty_metadata(handle, bh); 356c5d31192SDmitry Monakhov /* Errors can only happen due to aborted journal or a nasty bug */ 357c5d31192SDmitry Monakhov if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) { 35891aa11faSJan Kara ext4_journal_abort_handle(where, line, __func__, bh, 35991aa11faSJan Kara handle, err); 36066a4cb18STheodore Ts'o if (inode == NULL) { 36166a4cb18STheodore Ts'o pr_err("EXT4: jbd2_journal_dirty_metadata " 36266a4cb18STheodore Ts'o "failed: handle type %u started at " 36366a4cb18STheodore Ts'o "line %u, credits %u/%u, errcode %d", 36466a4cb18STheodore Ts'o handle->h_type, 36566a4cb18STheodore Ts'o handle->h_line_no, 36666a4cb18STheodore Ts'o handle->h_requested_credits, 367a9a8344eSJan Kara jbd2_handle_buffer_credits(handle), err); 36866a4cb18STheodore Ts'o return err; 36966a4cb18STheodore Ts'o } 370ae1495b1STheodore Ts'o ext4_error_inode(inode, where, line, 371ae1495b1STheodore Ts'o bh->b_blocknr, 372ae1495b1STheodore Ts'o "journal_dirty_metadata failed: " 373ae1495b1STheodore Ts'o "handle type %u started at line %u, " 374ae1495b1STheodore Ts'o "credits %u/%u, errcode %d", 375ae1495b1STheodore Ts'o handle->h_type, 376ae1495b1STheodore Ts'o handle->h_line_no, 377ae1495b1STheodore Ts'o handle->h_requested_credits, 378a9a8344eSJan Kara jbd2_handle_buffer_credits(handle), 379a9a8344eSJan Kara err); 3809ea7a0dfSTheodore Ts'o } 3810390131bSFrank Mayhar } else { 38273b50c1cSCurt Wohlgemuth if (inode) 383fe188c0eSTheodore Ts'o mark_buffer_dirty_inode(bh, inode); 384fe188c0eSTheodore Ts'o else 3850390131bSFrank Mayhar mark_buffer_dirty(bh); 3860390131bSFrank Mayhar if (inode && inode_needs_sync(inode)) { 3870390131bSFrank Mayhar sync_dirty_buffer(bh); 3880390131bSFrank Mayhar if (buffer_req(bh) && !buffer_uptodate(bh)) { 38954d3adbcSTheodore Ts'o ext4_error_inode_err(inode, where, line, 39054d3adbcSTheodore Ts'o bh->b_blocknr, EIO, 391c398eda0STheodore Ts'o "IO error syncing itable block"); 3920390131bSFrank Mayhar err = -EIO; 3930390131bSFrank Mayhar } 3940390131bSFrank Mayhar } 3950390131bSFrank Mayhar } 3968984d137SAndrew Morton return err; 3978984d137SAndrew Morton } 398