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
ext4_inode_journal_mode(struct inode * inode)10 int ext4_inode_journal_mode(struct inode *inode)
11 {
12 if (EXT4_JOURNAL(inode) == NULL)
13 return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
14 /* We do not support data journalling with delayed allocation */
15 if (!S_ISREG(inode->i_mode) ||
16 ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
17 test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
18 (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
19 !test_opt(inode->i_sb, DELALLOC) &&
20 !mapping_large_folio_support(inode->i_mapping))) {
21 /* We do not support data journalling for encrypted data */
22 if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
23 return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
24 return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
25 }
26 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
27 return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
28 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
29 return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
30 BUG();
31 }
32
33 /* Just increment the non-pointer handle value */
ext4_get_nojournal(void)34 static handle_t *ext4_get_nojournal(void)
35 {
36 handle_t *handle = current->journal_info;
37 unsigned long ref_cnt = (unsigned long)handle;
38
39 BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
40
41 ref_cnt++;
42 handle = (handle_t *)ref_cnt;
43
44 current->journal_info = handle;
45 return handle;
46 }
47
48
49 /* Decrement the non-pointer handle value */
ext4_put_nojournal(handle_t * handle)50 static void ext4_put_nojournal(handle_t *handle)
51 {
52 unsigned long ref_cnt = (unsigned long)handle;
53
54 BUG_ON(ref_cnt == 0);
55
56 ref_cnt--;
57 handle = (handle_t *)ref_cnt;
58
59 current->journal_info = handle;
60 }
61
62 /*
63 * Wrappers for jbd2_journal_start/end.
64 */
ext4_journal_check_start(struct super_block * sb)65 static int ext4_journal_check_start(struct super_block *sb)
66 {
67 int ret;
68 journal_t *journal;
69
70 might_sleep();
71
72 ret = ext4_emergency_state(sb);
73 if (unlikely(ret))
74 return ret;
75
76 if (WARN_ON_ONCE(sb_rdonly(sb)))
77 return -EROFS;
78
79 WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
80 journal = EXT4_SB(sb)->s_journal;
81 /*
82 * Special case here: if the journal has aborted behind our
83 * backs (eg. EIO in the commit thread), then we still need to
84 * take the FS itself readonly cleanly.
85 */
86 if (journal && is_journal_aborted(journal)) {
87 ext4_abort(sb, -journal->j_errno, "Detected aborted journal");
88 return -EROFS;
89 }
90 return 0;
91 }
92
__ext4_journal_start_sb(struct inode * inode,struct super_block * sb,unsigned int line,int type,int blocks,int rsv_blocks,int revoke_creds)93 handle_t *__ext4_journal_start_sb(struct inode *inode,
94 struct super_block *sb, unsigned int line,
95 int type, int blocks, int rsv_blocks,
96 int revoke_creds)
97 {
98 journal_t *journal;
99 int err;
100 if (inode)
101 trace_ext4_journal_start_inode(inode, blocks, rsv_blocks,
102 revoke_creds, type,
103 _RET_IP_);
104 else
105 trace_ext4_journal_start_sb(sb, blocks, rsv_blocks,
106 revoke_creds, type,
107 _RET_IP_);
108 err = ext4_journal_check_start(sb);
109 if (err < 0)
110 return ERR_PTR(err);
111
112 journal = EXT4_SB(sb)->s_journal;
113 if (!journal || (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
114 return ext4_get_nojournal();
115 return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds,
116 GFP_NOFS, type, line);
117 }
118
__ext4_journal_stop(const char * where,unsigned int line,handle_t * handle)119 int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
120 {
121 struct super_block *sb;
122 int err;
123 int rc;
124
125 if (!ext4_handle_valid(handle)) {
126 ext4_put_nojournal(handle);
127 return 0;
128 }
129
130 err = handle->h_err;
131 if (!handle->h_transaction) {
132 rc = jbd2_journal_stop(handle);
133 return err ? err : rc;
134 }
135
136 sb = handle->h_transaction->t_journal->j_private;
137 rc = jbd2_journal_stop(handle);
138
139 if (!err)
140 err = rc;
141 if (err)
142 __ext4_std_error(sb, where, line, err);
143 return err;
144 }
145
__ext4_journal_start_reserved(handle_t * handle,unsigned int line,int type)146 handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
147 int type)
148 {
149 struct super_block *sb;
150 int err;
151
152 if (!ext4_handle_valid(handle))
153 return ext4_get_nojournal();
154
155 sb = handle->h_journal->j_private;
156 trace_ext4_journal_start_reserved(sb,
157 jbd2_handle_buffer_credits(handle), _RET_IP_);
158 err = ext4_journal_check_start(sb);
159 if (err < 0) {
160 jbd2_journal_free_reserved(handle);
161 return ERR_PTR(err);
162 }
163
164 err = jbd2_journal_start_reserved(handle, type, line);
165 if (err < 0)
166 return ERR_PTR(err);
167 return handle;
168 }
169
__ext4_journal_ensure_credits(handle_t * handle,int check_cred,int extend_cred,int revoke_cred)170 int __ext4_journal_ensure_credits(handle_t *handle, int check_cred,
171 int extend_cred, int revoke_cred)
172 {
173 if (!ext4_handle_valid(handle))
174 return 0;
175 if (is_handle_aborted(handle))
176 return -EROFS;
177 if (jbd2_handle_buffer_credits(handle) >= check_cred &&
178 handle->h_revoke_credits >= revoke_cred)
179 return 0;
180 extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle));
181 revoke_cred = max(0, revoke_cred - handle->h_revoke_credits);
182 return ext4_journal_extend(handle, extend_cred, revoke_cred);
183 }
184
ext4_journal_abort_handle(const char * caller,unsigned int line,const char * err_fn,struct buffer_head * bh,handle_t * handle,int err)185 static void ext4_journal_abort_handle(const char *caller, unsigned int line,
186 const char *err_fn,
187 struct buffer_head *bh,
188 handle_t *handle, int err)
189 {
190 char nbuf[16];
191 const char *errstr = ext4_decode_error(NULL, err, nbuf);
192
193 BUG_ON(!ext4_handle_valid(handle));
194
195 if (bh)
196 BUFFER_TRACE(bh, "abort");
197
198 if (!handle->h_err)
199 handle->h_err = err;
200
201 if (is_handle_aborted(handle))
202 return;
203
204 printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s\n",
205 caller, line, errstr, err_fn);
206
207 jbd2_journal_abort_handle(handle);
208 }
209
ext4_check_bdev_write_error(struct super_block * sb)210 static void ext4_check_bdev_write_error(struct super_block *sb)
211 {
212 struct address_space *mapping = sb->s_bdev->bd_mapping;
213 struct ext4_sb_info *sbi = EXT4_SB(sb);
214 int err;
215
216 /*
217 * If the block device has write error flag, it may have failed to
218 * async write out metadata buffers in the background. In this case,
219 * we could read old data from disk and write it out again, which
220 * may lead to on-disk filesystem inconsistency.
221 */
222 if (errseq_check(&mapping->wb_err, READ_ONCE(sbi->s_bdev_wb_err))) {
223 spin_lock(&sbi->s_bdev_wb_lock);
224 err = errseq_check_and_advance(&mapping->wb_err, &sbi->s_bdev_wb_err);
225 spin_unlock(&sbi->s_bdev_wb_lock);
226 if (err)
227 ext4_error_err(sb, -err,
228 "Error while async write back metadata");
229 }
230 }
231
__ext4_journal_get_write_access(const char * where,unsigned int line,handle_t * handle,struct super_block * sb,struct buffer_head * bh,enum ext4_journal_trigger_type trigger_type)232 int __ext4_journal_get_write_access(const char *where, unsigned int line,
233 handle_t *handle, struct super_block *sb,
234 struct buffer_head *bh,
235 enum ext4_journal_trigger_type trigger_type)
236 {
237 int err;
238
239 might_sleep();
240
241 if (ext4_handle_valid(handle)) {
242 err = jbd2_journal_get_write_access(handle, bh);
243 if (err) {
244 ext4_journal_abort_handle(where, line, __func__, bh,
245 handle, err);
246 return err;
247 }
248 } else
249 ext4_check_bdev_write_error(sb);
250 if (trigger_type == EXT4_JTR_NONE ||
251 !ext4_has_feature_metadata_csum(sb))
252 return 0;
253 BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
254 jbd2_journal_set_triggers(bh,
255 &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
256 return 0;
257 }
258
259 /*
260 * The ext4 forget function must perform a revoke if we are freeing data
261 * which has been journaled. Metadata (eg. indirect blocks) must be
262 * revoked in all cases.
263 *
264 * "bh" may be NULL: a metadata block may have been freed from memory
265 * but there may still be a record of it in the journal, and that record
266 * still needs to be revoked.
267 */
__ext4_forget(const char * where,unsigned int line,handle_t * handle,int is_metadata,struct inode * inode,struct buffer_head * bh,ext4_fsblk_t blocknr)268 int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
269 int is_metadata, struct inode *inode,
270 struct buffer_head *bh, ext4_fsblk_t blocknr)
271 {
272 int err;
273
274 might_sleep();
275
276 trace_ext4_forget(inode, is_metadata, blocknr);
277 BUFFER_TRACE(bh, "enter");
278
279 ext4_debug("forgetting bh %p: is_metadata=%d, mode %o, data mode %x\n",
280 bh, is_metadata, inode->i_mode,
281 test_opt(inode->i_sb, DATA_FLAGS));
282
283 /*
284 * In the no journal case, we should wait for the ongoing buffer
285 * to complete and do a forget.
286 */
287 if (!ext4_handle_valid(handle)) {
288 if (bh) {
289 clear_buffer_dirty(bh);
290 wait_on_buffer(bh);
291 __bforget(bh);
292 }
293 return 0;
294 }
295
296 /* Never use the revoke function if we are doing full data
297 * journaling: there is no need to, and a V1 superblock won't
298 * support it. Otherwise, only skip the revoke on un-journaled
299 * data blocks. */
300
301 if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
302 (!is_metadata && !ext4_should_journal_data(inode))) {
303 if (bh) {
304 BUFFER_TRACE(bh, "call jbd2_journal_forget");
305 err = jbd2_journal_forget(handle, bh);
306 if (err)
307 ext4_journal_abort_handle(where, line, __func__,
308 bh, handle, err);
309 return err;
310 }
311 return 0;
312 }
313
314 /*
315 * data!=journal && (is_metadata || should_journal_data(inode))
316 */
317 BUFFER_TRACE(bh, "call jbd2_journal_revoke");
318 err = jbd2_journal_revoke(handle, blocknr, bh);
319 if (err) {
320 ext4_journal_abort_handle(where, line, __func__,
321 bh, handle, err);
322 __ext4_error(inode->i_sb, where, line, true, -err, 0,
323 "error %d when attempting revoke", err);
324 }
325 BUFFER_TRACE(bh, "exit");
326 return err;
327 }
328
__ext4_journal_get_create_access(const char * where,unsigned int line,handle_t * handle,struct super_block * sb,struct buffer_head * bh,enum ext4_journal_trigger_type trigger_type)329 int __ext4_journal_get_create_access(const char *where, unsigned int line,
330 handle_t *handle, struct super_block *sb,
331 struct buffer_head *bh,
332 enum ext4_journal_trigger_type trigger_type)
333 {
334 int err;
335
336 if (!ext4_handle_valid(handle))
337 return 0;
338
339 err = jbd2_journal_get_create_access(handle, bh);
340 if (err) {
341 ext4_journal_abort_handle(where, line, __func__, bh, handle,
342 err);
343 return err;
344 }
345 if (trigger_type == EXT4_JTR_NONE ||
346 !ext4_has_feature_metadata_csum(sb))
347 return 0;
348 BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
349 jbd2_journal_set_triggers(bh,
350 &EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
351 return 0;
352 }
353
__ext4_handle_dirty_metadata(const char * where,unsigned int line,handle_t * handle,struct inode * inode,struct buffer_head * bh)354 int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
355 handle_t *handle, struct inode *inode,
356 struct buffer_head *bh)
357 {
358 int err = 0;
359
360 might_sleep();
361
362 set_buffer_meta(bh);
363 set_buffer_prio(bh);
364 set_buffer_uptodate(bh);
365 if (ext4_handle_valid(handle)) {
366 err = jbd2_journal_dirty_metadata(handle, bh);
367 /* Errors can only happen due to aborted journal or a nasty bug */
368 if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) {
369 ext4_journal_abort_handle(where, line, __func__, bh,
370 handle, err);
371 if (inode == NULL) {
372 pr_err("EXT4: jbd2_journal_dirty_metadata "
373 "failed: handle type %u started at "
374 "line %u, credits %u/%u, errcode %d",
375 handle->h_type,
376 handle->h_line_no,
377 handle->h_requested_credits,
378 jbd2_handle_buffer_credits(handle), err);
379 return err;
380 }
381 ext4_error_inode(inode, where, line,
382 bh->b_blocknr,
383 "journal_dirty_metadata failed: "
384 "handle type %u started at line %u, "
385 "credits %u/%u, errcode %d",
386 handle->h_type,
387 handle->h_line_no,
388 handle->h_requested_credits,
389 jbd2_handle_buffer_credits(handle),
390 err);
391 }
392 } else {
393 if (inode)
394 mark_buffer_dirty_inode(bh, inode);
395 else
396 mark_buffer_dirty(bh);
397 if (inode && inode_needs_sync(inode)) {
398 sync_dirty_buffer(bh);
399 if (buffer_req(bh) && !buffer_uptodate(bh)) {
400 ext4_error_inode_err(inode, where, line,
401 bh->b_blocknr, EIO,
402 "IO error syncing itable block");
403 err = -EIO;
404 }
405 }
406 }
407 return err;
408 }
409