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