18984d137SAndrew Morton /* 28984d137SAndrew Morton * Interface between ext4 and JBD 38984d137SAndrew Morton */ 48984d137SAndrew Morton 53dcf5451SChristoph Hellwig #include "ext4_jbd2.h" 68984d137SAndrew Morton 7d6797d14STheodore Ts'o #include <trace/events/ext4.h> 8d6797d14STheodore Ts'o 98984d137SAndrew Morton int __ext4_journal_get_undo_access(const char *where, handle_t *handle, 108984d137SAndrew Morton struct buffer_head *bh) 118984d137SAndrew Morton { 120390131bSFrank Mayhar int err = 0; 130390131bSFrank Mayhar 140390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 150390131bSFrank Mayhar err = jbd2_journal_get_undo_access(handle, bh); 168984d137SAndrew Morton if (err) 170390131bSFrank Mayhar ext4_journal_abort_handle(where, __func__, bh, 180390131bSFrank Mayhar handle, err); 190390131bSFrank Mayhar } 208984d137SAndrew Morton return err; 218984d137SAndrew Morton } 228984d137SAndrew Morton 238984d137SAndrew Morton int __ext4_journal_get_write_access(const char *where, handle_t *handle, 248984d137SAndrew Morton struct buffer_head *bh) 258984d137SAndrew Morton { 260390131bSFrank Mayhar int err = 0; 270390131bSFrank Mayhar 280390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 290390131bSFrank Mayhar err = jbd2_journal_get_write_access(handle, bh); 308984d137SAndrew Morton if (err) 310390131bSFrank Mayhar ext4_journal_abort_handle(where, __func__, bh, 320390131bSFrank Mayhar handle, err); 330390131bSFrank Mayhar } 348984d137SAndrew Morton return err; 358984d137SAndrew Morton } 368984d137SAndrew Morton 378984d137SAndrew Morton int __ext4_journal_forget(const char *where, handle_t *handle, 388984d137SAndrew Morton struct buffer_head *bh) 398984d137SAndrew Morton { 400390131bSFrank Mayhar int err = 0; 410390131bSFrank Mayhar 420390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 430390131bSFrank Mayhar err = jbd2_journal_forget(handle, bh); 448984d137SAndrew Morton if (err) 450390131bSFrank Mayhar ext4_journal_abort_handle(where, __func__, bh, 460390131bSFrank Mayhar handle, err); 470390131bSFrank Mayhar } 48e6b5d301SCurt Wohlgemuth else 49c7acb4c1STheodore Ts'o bforget(bh); 508984d137SAndrew Morton return err; 518984d137SAndrew Morton } 528984d137SAndrew Morton 538984d137SAndrew Morton int __ext4_journal_revoke(const char *where, handle_t *handle, 548984d137SAndrew Morton ext4_fsblk_t blocknr, struct buffer_head *bh) 558984d137SAndrew Morton { 560390131bSFrank Mayhar int err = 0; 570390131bSFrank Mayhar 580390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 590390131bSFrank Mayhar err = jbd2_journal_revoke(handle, blocknr, bh); 608984d137SAndrew Morton if (err) 610390131bSFrank Mayhar ext4_journal_abort_handle(where, __func__, bh, 620390131bSFrank Mayhar handle, err); 630390131bSFrank Mayhar } 64e6b5d301SCurt Wohlgemuth else 65c7acb4c1STheodore Ts'o bforget(bh); 668984d137SAndrew Morton return err; 678984d137SAndrew Morton } 688984d137SAndrew Morton 69d6797d14STheodore Ts'o /* 70d6797d14STheodore Ts'o * The ext4 forget function must perform a revoke if we are freeing data 71d6797d14STheodore Ts'o * which has been journaled. Metadata (eg. indirect blocks) must be 72d6797d14STheodore Ts'o * revoked in all cases. 73d6797d14STheodore Ts'o * 74d6797d14STheodore Ts'o * "bh" may be NULL: a metadata block may have been freed from memory 75d6797d14STheodore Ts'o * but there may still be a record of it in the journal, and that record 76d6797d14STheodore Ts'o * still needs to be revoked. 77d6797d14STheodore Ts'o * 78d6797d14STheodore Ts'o * If the handle isn't valid we're not journaling, but we still need to 79d6797d14STheodore Ts'o * call into ext4_journal_revoke() to put the buffer head. 80d6797d14STheodore Ts'o */ 81d6797d14STheodore Ts'o int __ext4_forget(const char *where, handle_t *handle, int is_metadata, 82d6797d14STheodore Ts'o struct inode *inode, struct buffer_head *bh, 83d6797d14STheodore Ts'o ext4_fsblk_t blocknr) 84d6797d14STheodore Ts'o { 85d6797d14STheodore Ts'o int err; 86d6797d14STheodore Ts'o 87d6797d14STheodore Ts'o might_sleep(); 88d6797d14STheodore Ts'o 89d6797d14STheodore Ts'o trace_ext4_forget(inode, is_metadata, blocknr); 90d6797d14STheodore Ts'o BUFFER_TRACE(bh, "enter"); 91d6797d14STheodore Ts'o 92d6797d14STheodore Ts'o jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, " 93d6797d14STheodore Ts'o "data mode %x\n", 94d6797d14STheodore Ts'o bh, is_metadata, inode->i_mode, 95d6797d14STheodore Ts'o test_opt(inode->i_sb, DATA_FLAGS)); 96d6797d14STheodore Ts'o 97d6797d14STheodore Ts'o /* Never use the revoke function if we are doing full data 98d6797d14STheodore Ts'o * journaling: there is no need to, and a V1 superblock won't 99d6797d14STheodore Ts'o * support it. Otherwise, only skip the revoke on un-journaled 100d6797d14STheodore Ts'o * data blocks. */ 101d6797d14STheodore Ts'o 102d6797d14STheodore Ts'o if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || 103d6797d14STheodore Ts'o (!is_metadata && !ext4_should_journal_data(inode))) { 104d6797d14STheodore Ts'o if (bh) { 105d6797d14STheodore Ts'o BUFFER_TRACE(bh, "call jbd2_journal_forget"); 106d6797d14STheodore Ts'o return __ext4_journal_forget(where, handle, bh); 107d6797d14STheodore Ts'o } 108d6797d14STheodore Ts'o return 0; 109d6797d14STheodore Ts'o } 110d6797d14STheodore Ts'o 111d6797d14STheodore Ts'o /* 112d6797d14STheodore Ts'o * data!=journal && (is_metadata || should_journal_data(inode)) 113d6797d14STheodore Ts'o */ 114d6797d14STheodore Ts'o BUFFER_TRACE(bh, "call ext4_journal_revoke"); 115d6797d14STheodore Ts'o err = __ext4_journal_revoke(where, handle, blocknr, bh); 116d6797d14STheodore Ts'o if (err) 117d6797d14STheodore Ts'o ext4_abort(inode->i_sb, __func__, 118d6797d14STheodore Ts'o "error %d when attempting revoke", err); 119d6797d14STheodore Ts'o BUFFER_TRACE(bh, "exit"); 120d6797d14STheodore Ts'o return err; 121d6797d14STheodore Ts'o } 122d6797d14STheodore Ts'o 1238984d137SAndrew Morton int __ext4_journal_get_create_access(const char *where, 1248984d137SAndrew Morton handle_t *handle, struct buffer_head *bh) 1258984d137SAndrew Morton { 1260390131bSFrank Mayhar int err = 0; 1270390131bSFrank Mayhar 1280390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 1290390131bSFrank Mayhar err = jbd2_journal_get_create_access(handle, bh); 1308984d137SAndrew Morton if (err) 1310390131bSFrank Mayhar ext4_journal_abort_handle(where, __func__, bh, 1320390131bSFrank Mayhar handle, err); 1330390131bSFrank Mayhar } 1348984d137SAndrew Morton return err; 1358984d137SAndrew Morton } 1368984d137SAndrew Morton 1370390131bSFrank Mayhar int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, 1380390131bSFrank Mayhar struct inode *inode, struct buffer_head *bh) 1398984d137SAndrew Morton { 1400390131bSFrank Mayhar int err = 0; 1410390131bSFrank Mayhar 1420390131bSFrank Mayhar if (ext4_handle_valid(handle)) { 1430390131bSFrank Mayhar err = jbd2_journal_dirty_metadata(handle, bh); 1448984d137SAndrew Morton if (err) 1450390131bSFrank Mayhar ext4_journal_abort_handle(where, __func__, bh, 1460390131bSFrank Mayhar handle, err); 1470390131bSFrank Mayhar } else { 148fe188c0eSTheodore Ts'o if (inode && bh) 149fe188c0eSTheodore Ts'o mark_buffer_dirty_inode(bh, inode); 150fe188c0eSTheodore Ts'o else 1510390131bSFrank Mayhar mark_buffer_dirty(bh); 1520390131bSFrank Mayhar if (inode && inode_needs_sync(inode)) { 1530390131bSFrank Mayhar sync_dirty_buffer(bh); 1540390131bSFrank Mayhar if (buffer_req(bh) && !buffer_uptodate(bh)) { 1550390131bSFrank Mayhar ext4_error(inode->i_sb, __func__, 1560390131bSFrank Mayhar "IO error syncing inode, " 1570390131bSFrank Mayhar "inode=%lu, block=%llu", 1580390131bSFrank Mayhar inode->i_ino, 1590390131bSFrank Mayhar (unsigned long long) bh->b_blocknr); 1600390131bSFrank Mayhar err = -EIO; 1610390131bSFrank Mayhar } 1620390131bSFrank Mayhar } 1630390131bSFrank Mayhar } 1648984d137SAndrew Morton return err; 1658984d137SAndrew Morton } 166