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 /* Just increment the non-pointer handle value */ 11 static handle_t *ext4_get_nojournal(void) 12 { 13 handle_t *handle = current->journal_info; 14 unsigned long ref_cnt = (unsigned long)handle; 15 16 BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT); 17 18 ref_cnt++; 19 handle = (handle_t *)ref_cnt; 20 21 current->journal_info = handle; 22 return handle; 23 } 24 25 26 /* Decrement the non-pointer handle value */ 27 static void ext4_put_nojournal(handle_t *handle) 28 { 29 unsigned long ref_cnt = (unsigned long)handle; 30 31 BUG_ON(ref_cnt == 0); 32 33 ref_cnt--; 34 handle = (handle_t *)ref_cnt; 35 36 current->journal_info = handle; 37 } 38 39 /* 40 * Wrappers for jbd2_journal_start/end. 41 */ 42 static int ext4_journal_check_start(struct super_block *sb) 43 { 44 journal_t *journal; 45 46 might_sleep(); 47 48 if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) 49 return -EIO; 50 51 if (sb_rdonly(sb)) 52 return -EROFS; 53 WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE); 54 journal = EXT4_SB(sb)->s_journal; 55 /* 56 * Special case here: if the journal has aborted behind our 57 * backs (eg. EIO in the commit thread), then we still need to 58 * take the FS itself readonly cleanly. 59 */ 60 if (journal && is_journal_aborted(journal)) { 61 ext4_abort(sb, "Detected aborted journal"); 62 return -EROFS; 63 } 64 return 0; 65 } 66 67 handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line, 68 int type, int blocks, int rsv_blocks, 69 int revoke_creds) 70 { 71 journal_t *journal; 72 int err; 73 74 trace_ext4_journal_start(sb, blocks, rsv_blocks, revoke_creds, 75 _RET_IP_); 76 err = ext4_journal_check_start(sb); 77 if (err < 0) 78 return ERR_PTR(err); 79 80 journal = EXT4_SB(sb)->s_journal; 81 if (!journal) 82 return ext4_get_nojournal(); 83 return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds, 84 GFP_NOFS, type, line); 85 } 86 87 int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) 88 { 89 struct super_block *sb; 90 int err; 91 int rc; 92 93 if (!ext4_handle_valid(handle)) { 94 ext4_put_nojournal(handle); 95 return 0; 96 } 97 98 err = handle->h_err; 99 if (!handle->h_transaction) { 100 rc = jbd2_journal_stop(handle); 101 return err ? err : rc; 102 } 103 104 sb = handle->h_transaction->t_journal->j_private; 105 rc = jbd2_journal_stop(handle); 106 107 if (!err) 108 err = rc; 109 if (err) 110 __ext4_std_error(sb, where, line, err); 111 return err; 112 } 113 114 handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line, 115 int type) 116 { 117 struct super_block *sb; 118 int err; 119 120 if (!ext4_handle_valid(handle)) 121 return ext4_get_nojournal(); 122 123 sb = handle->h_journal->j_private; 124 trace_ext4_journal_start_reserved(sb, 125 jbd2_handle_buffer_credits(handle), _RET_IP_); 126 err = ext4_journal_check_start(sb); 127 if (err < 0) { 128 jbd2_journal_free_reserved(handle); 129 return ERR_PTR(err); 130 } 131 132 err = jbd2_journal_start_reserved(handle, type, line); 133 if (err < 0) 134 return ERR_PTR(err); 135 return handle; 136 } 137 138 int __ext4_journal_ensure_credits(handle_t *handle, int check_cred, 139 int extend_cred, int revoke_cred) 140 { 141 if (!ext4_handle_valid(handle)) 142 return 0; 143 if (jbd2_handle_buffer_credits(handle) >= check_cred && 144 handle->h_revoke_credits >= revoke_cred) 145 return 0; 146 extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle)); 147 revoke_cred = max(0, revoke_cred - handle->h_revoke_credits); 148 return ext4_journal_extend(handle, extend_cred, revoke_cred); 149 } 150 151 static void ext4_journal_abort_handle(const char *caller, unsigned int line, 152 const char *err_fn, 153 struct buffer_head *bh, 154 handle_t *handle, int err) 155 { 156 char nbuf[16]; 157 const char *errstr = ext4_decode_error(NULL, err, nbuf); 158 159 BUG_ON(!ext4_handle_valid(handle)); 160 161 if (bh) 162 BUFFER_TRACE(bh, "abort"); 163 164 if (!handle->h_err) 165 handle->h_err = err; 166 167 if (is_handle_aborted(handle)) 168 return; 169 170 printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n", 171 caller, line, errstr, err_fn); 172 173 jbd2_journal_abort_handle(handle); 174 } 175 176 int __ext4_journal_get_write_access(const char *where, unsigned int line, 177 handle_t *handle, struct buffer_head *bh) 178 { 179 int err = 0; 180 181 might_sleep(); 182 183 if (ext4_handle_valid(handle)) { 184 err = jbd2_journal_get_write_access(handle, bh); 185 if (err) 186 ext4_journal_abort_handle(where, line, __func__, bh, 187 handle, err); 188 } 189 return err; 190 } 191 192 /* 193 * The ext4 forget function must perform a revoke if we are freeing data 194 * which has been journaled. Metadata (eg. indirect blocks) must be 195 * revoked in all cases. 196 * 197 * "bh" may be NULL: a metadata block may have been freed from memory 198 * but there may still be a record of it in the journal, and that record 199 * still needs to be revoked. 200 * 201 * If the handle isn't valid we're not journaling, but we still need to 202 * call into ext4_journal_revoke() to put the buffer head. 203 */ 204 int __ext4_forget(const char *where, unsigned int line, handle_t *handle, 205 int is_metadata, struct inode *inode, 206 struct buffer_head *bh, ext4_fsblk_t blocknr) 207 { 208 int err; 209 210 might_sleep(); 211 212 trace_ext4_forget(inode, is_metadata, blocknr); 213 BUFFER_TRACE(bh, "enter"); 214 215 jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, " 216 "data mode %x\n", 217 bh, is_metadata, inode->i_mode, 218 test_opt(inode->i_sb, DATA_FLAGS)); 219 220 /* In the no journal case, we can just do a bforget and return */ 221 if (!ext4_handle_valid(handle)) { 222 bforget(bh); 223 return 0; 224 } 225 226 /* Never use the revoke function if we are doing full data 227 * journaling: there is no need to, and a V1 superblock won't 228 * support it. Otherwise, only skip the revoke on un-journaled 229 * data blocks. */ 230 231 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || 232 (!is_metadata && !ext4_should_journal_data(inode))) { 233 if (bh) { 234 BUFFER_TRACE(bh, "call jbd2_journal_forget"); 235 err = jbd2_journal_forget(handle, bh); 236 if (err) 237 ext4_journal_abort_handle(where, line, __func__, 238 bh, handle, err); 239 return err; 240 } 241 return 0; 242 } 243 244 /* 245 * data!=journal && (is_metadata || should_journal_data(inode)) 246 */ 247 BUFFER_TRACE(bh, "call jbd2_journal_revoke"); 248 err = jbd2_journal_revoke(handle, blocknr, bh); 249 if (err) { 250 ext4_journal_abort_handle(where, line, __func__, 251 bh, handle, err); 252 __ext4_abort(inode->i_sb, where, line, 253 "error %d when attempting revoke", err); 254 } 255 BUFFER_TRACE(bh, "exit"); 256 return err; 257 } 258 259 int __ext4_journal_get_create_access(const char *where, unsigned int line, 260 handle_t *handle, struct buffer_head *bh) 261 { 262 int err = 0; 263 264 if (ext4_handle_valid(handle)) { 265 err = jbd2_journal_get_create_access(handle, bh); 266 if (err) 267 ext4_journal_abort_handle(where, line, __func__, 268 bh, handle, err); 269 } 270 return err; 271 } 272 273 int __ext4_handle_dirty_metadata(const char *where, unsigned int line, 274 handle_t *handle, struct inode *inode, 275 struct buffer_head *bh) 276 { 277 int err = 0; 278 279 might_sleep(); 280 281 set_buffer_meta(bh); 282 set_buffer_prio(bh); 283 if (ext4_handle_valid(handle)) { 284 err = jbd2_journal_dirty_metadata(handle, bh); 285 /* Errors can only happen due to aborted journal or a nasty bug */ 286 if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) { 287 ext4_journal_abort_handle(where, line, __func__, bh, 288 handle, err); 289 if (inode == NULL) { 290 pr_err("EXT4: jbd2_journal_dirty_metadata " 291 "failed: handle type %u started at " 292 "line %u, credits %u/%u, errcode %d", 293 handle->h_type, 294 handle->h_line_no, 295 handle->h_requested_credits, 296 jbd2_handle_buffer_credits(handle), err); 297 return err; 298 } 299 ext4_error_inode(inode, where, line, 300 bh->b_blocknr, 301 "journal_dirty_metadata failed: " 302 "handle type %u started at line %u, " 303 "credits %u/%u, errcode %d", 304 handle->h_type, 305 handle->h_line_no, 306 handle->h_requested_credits, 307 jbd2_handle_buffer_credits(handle), 308 err); 309 } 310 } else { 311 if (inode) 312 mark_buffer_dirty_inode(bh, inode); 313 else 314 mark_buffer_dirty(bh); 315 if (inode && inode_needs_sync(inode)) { 316 sync_dirty_buffer(bh); 317 if (buffer_req(bh) && !buffer_uptodate(bh)) { 318 struct ext4_super_block *es; 319 320 es = EXT4_SB(inode->i_sb)->s_es; 321 es->s_last_error_block = 322 cpu_to_le64(bh->b_blocknr); 323 ext4_error_inode(inode, where, line, 324 bh->b_blocknr, 325 "IO error syncing itable block"); 326 err = -EIO; 327 } 328 } 329 } 330 return err; 331 } 332 333 int __ext4_handle_dirty_super(const char *where, unsigned int line, 334 handle_t *handle, struct super_block *sb) 335 { 336 struct buffer_head *bh = EXT4_SB(sb)->s_sbh; 337 int err = 0; 338 339 ext4_superblock_csum_set(sb); 340 if (ext4_handle_valid(handle)) { 341 err = jbd2_journal_dirty_metadata(handle, bh); 342 if (err) 343 ext4_journal_abort_handle(where, line, __func__, 344 bh, handle, err); 345 } else 346 mark_buffer_dirty(bh); 347 return err; 348 } 349