1 /* 2 * Interface between ext4 and JBD 3 */ 4 5 #include "ext4_jbd2.h" 6 7 #include <trace/events/ext4.h> 8 9 int __ext4_journal_get_write_access(const char *where, unsigned int line, 10 handle_t *handle, struct buffer_head *bh) 11 { 12 int err = 0; 13 14 if (ext4_handle_valid(handle)) { 15 err = jbd2_journal_get_write_access(handle, bh); 16 if (err) 17 ext4_journal_abort_handle(where, line, __func__, bh, 18 handle, err); 19 } 20 return err; 21 } 22 23 /* 24 * The ext4 forget function must perform a revoke if we are freeing data 25 * which has been journaled. Metadata (eg. indirect blocks) must be 26 * revoked in all cases. 27 * 28 * "bh" may be NULL: a metadata block may have been freed from memory 29 * but there may still be a record of it in the journal, and that record 30 * still needs to be revoked. 31 * 32 * If the handle isn't valid we're not journaling, but we still need to 33 * call into ext4_journal_revoke() to put the buffer head. 34 */ 35 int __ext4_forget(const char *where, unsigned int line, handle_t *handle, 36 int is_metadata, struct inode *inode, 37 struct buffer_head *bh, ext4_fsblk_t blocknr) 38 { 39 int err; 40 41 might_sleep(); 42 43 trace_ext4_forget(inode, is_metadata, blocknr); 44 BUFFER_TRACE(bh, "enter"); 45 46 jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, " 47 "data mode %x\n", 48 bh, is_metadata, inode->i_mode, 49 test_opt(inode->i_sb, DATA_FLAGS)); 50 51 /* In the no journal case, we can just do a bforget and return */ 52 if (!ext4_handle_valid(handle)) { 53 bforget(bh); 54 return 0; 55 } 56 57 /* Never use the revoke function if we are doing full data 58 * journaling: there is no need to, and a V1 superblock won't 59 * support it. Otherwise, only skip the revoke on un-journaled 60 * data blocks. */ 61 62 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || 63 (!is_metadata && !ext4_should_journal_data(inode))) { 64 if (bh) { 65 BUFFER_TRACE(bh, "call jbd2_journal_forget"); 66 err = jbd2_journal_forget(handle, bh); 67 if (err) 68 ext4_journal_abort_handle(where, line, __func__, 69 bh, handle, err); 70 return err; 71 } 72 return 0; 73 } 74 75 /* 76 * data!=journal && (is_metadata || should_journal_data(inode)) 77 */ 78 BUFFER_TRACE(bh, "call jbd2_journal_revoke"); 79 err = jbd2_journal_revoke(handle, blocknr, bh); 80 if (err) { 81 ext4_journal_abort_handle(where, line, __func__, 82 bh, handle, err); 83 __ext4_abort(inode->i_sb, where, line, 84 "error %d when attempting revoke", err); 85 } 86 BUFFER_TRACE(bh, "exit"); 87 return err; 88 } 89 90 int __ext4_journal_get_create_access(const char *where, unsigned int line, 91 handle_t *handle, struct buffer_head *bh) 92 { 93 int err = 0; 94 95 if (ext4_handle_valid(handle)) { 96 err = jbd2_journal_get_create_access(handle, bh); 97 if (err) 98 ext4_journal_abort_handle(where, line, __func__, 99 bh, handle, err); 100 } 101 return err; 102 } 103 104 int __ext4_handle_dirty_metadata(const char *where, unsigned int line, 105 handle_t *handle, struct inode *inode, 106 struct buffer_head *bh) 107 { 108 int err = 0; 109 110 if (ext4_handle_valid(handle)) { 111 err = jbd2_journal_dirty_metadata(handle, bh); 112 if (err) { 113 /* Errors can only happen if there is a bug */ 114 handle->h_err = err; 115 __ext4_journal_stop(where, line, handle); 116 } 117 } else { 118 if (inode) 119 mark_buffer_dirty_inode(bh, inode); 120 else 121 mark_buffer_dirty(bh); 122 if (inode && inode_needs_sync(inode)) { 123 sync_dirty_buffer(bh); 124 if (buffer_req(bh) && !buffer_uptodate(bh)) { 125 struct ext4_super_block *es; 126 127 es = EXT4_SB(inode->i_sb)->s_es; 128 es->s_last_error_block = 129 cpu_to_le64(bh->b_blocknr); 130 ext4_error_inode(inode, where, line, 131 bh->b_blocknr, 132 "IO error syncing itable block"); 133 err = -EIO; 134 } 135 } 136 } 137 return err; 138 } 139 140 int __ext4_handle_dirty_super(const char *where, unsigned int line, 141 handle_t *handle, struct super_block *sb) 142 { 143 struct buffer_head *bh = EXT4_SB(sb)->s_sbh; 144 int err = 0; 145 146 ext4_superblock_csum_set(sb); 147 if (ext4_handle_valid(handle)) { 148 err = jbd2_journal_dirty_metadata(handle, bh); 149 if (err) 150 ext4_journal_abort_handle(where, line, __func__, 151 bh, handle, err); 152 } else 153 mark_buffer_dirty(bh); 154 return err; 155 } 156