Merge tag 'docs-5.6' of git://git.lwn.net/linux
[linux-2.6-microblaze.git] / fs / ext4 / ext4_jbd2.c
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 }