Blame view

fs/ext4/ext4_jbd2.c 10.3 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
8984d137d   Andrew Morton   [PATCH] ext4: uni...
2
3
4
  /*
   * Interface between ext4 and JBD
   */
3dcf54515   Christoph Hellwig   ext4: move header...
5
  #include "ext4_jbd2.h"
8984d137d   Andrew Morton   [PATCH] ext4: uni...
6

d6797d14b   Theodore Ts'o   ext4: move ext4_f...
7
  #include <trace/events/ext4.h>
46797ad75   Eric Biggers   ext4: uninline ex...
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  int ext4_inode_journal_mode(struct inode *inode)
  {
  	if (EXT4_JOURNAL(inode) == NULL)
  		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
  	/* We do not support data journalling with delayed allocation */
  	if (!S_ISREG(inode->i_mode) ||
  	    ext4_test_inode_flag(inode, EXT4_INODE_EA_INODE) ||
  	    test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
  	    (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
  	    !test_opt(inode->i_sb, DELALLOC))) {
  		/* We do not support data journalling for encrypted data */
  		if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode))
  			return EXT4_INODE_ORDERED_DATA_MODE;  /* ordered */
  		return EXT4_INODE_JOURNAL_DATA_MODE;	/* journal data */
  	}
  	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
  		return EXT4_INODE_ORDERED_DATA_MODE;	/* ordered */
  	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
  		return EXT4_INODE_WRITEBACK_DATA_MODE;	/* writeback */
  	BUG();
  }
722887ddc   Theodore Ts'o   ext4: move the jb...
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  /* Just increment the non-pointer handle value */
  static handle_t *ext4_get_nojournal(void)
  {
  	handle_t *handle = current->journal_info;
  	unsigned long ref_cnt = (unsigned long)handle;
  
  	BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
  
  	ref_cnt++;
  	handle = (handle_t *)ref_cnt;
  
  	current->journal_info = handle;
  	return handle;
  }
  
  
  /* Decrement the non-pointer handle value */
  static void ext4_put_nojournal(handle_t *handle)
  {
  	unsigned long ref_cnt = (unsigned long)handle;
  
  	BUG_ON(ref_cnt == 0);
  
  	ref_cnt--;
  	handle = (handle_t *)ref_cnt;
  
  	current->journal_info = handle;
  }
  
  /*
   * Wrappers for jbd2_journal_start/end.
   */
5fe2fe895   Jan Kara   ext4: provide wra...
61
  static int ext4_journal_check_start(struct super_block *sb)
722887ddc   Theodore Ts'o   ext4: move the jb...
62
63
  {
  	journal_t *journal;
b10a44c36   Theodore Ts'o   ext4: add might_s...
64
  	might_sleep();
0db1ff222   Theodore Ts'o   ext4: add shutdow...
65
66
67
  
  	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
  		return -EIO;
bc98a42c1   David Howells   VFS: Convert sb->...
68
  	if (sb_rdonly(sb))
5fe2fe895   Jan Kara   ext4: provide wra...
69
  		return -EROFS;
722887ddc   Theodore Ts'o   ext4: move the jb...
70
71
  	WARN_ON(sb->s_writers.frozen == SB_FREEZE_COMPLETE);
  	journal = EXT4_SB(sb)->s_journal;
722887ddc   Theodore Ts'o   ext4: move the jb...
72
73
74
75
76
  	/*
  	 * Special case here: if the journal has aborted behind our
  	 * backs (eg. EIO in the commit thread), then we still need to
  	 * take the FS itself readonly cleanly.
  	 */
5fe2fe895   Jan Kara   ext4: provide wra...
77
  	if (journal && is_journal_aborted(journal)) {
54d3adbc2   Theodore Ts'o   ext4: save all er...
78
  		ext4_abort(sb, -journal->j_errno, "Detected aborted journal");
5fe2fe895   Jan Kara   ext4: provide wra...
79
  		return -EROFS;
722887ddc   Theodore Ts'o   ext4: move the jb...
80
  	}
5fe2fe895   Jan Kara   ext4: provide wra...
81
82
83
84
  	return 0;
  }
  
  handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line,
83448bdfb   Jan Kara   ext4: Reserve rev...
85
86
  				  int type, int blocks, int rsv_blocks,
  				  int revoke_creds)
5fe2fe895   Jan Kara   ext4: provide wra...
87
88
89
  {
  	journal_t *journal;
  	int err;
83448bdfb   Jan Kara   ext4: Reserve rev...
90
91
  	trace_ext4_journal_start(sb, blocks, rsv_blocks, revoke_creds,
  				 _RET_IP_);
5fe2fe895   Jan Kara   ext4: provide wra...
92
93
94
95
96
  	err = ext4_journal_check_start(sb);
  	if (err < 0)
  		return ERR_PTR(err);
  
  	journal = EXT4_SB(sb)->s_journal;
8016e29f4   Harshad Shirwadkar   ext4: fast commit...
97
  	if (!journal || (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY))
5fe2fe895   Jan Kara   ext4: provide wra...
98
  		return ext4_get_nojournal();
83448bdfb   Jan Kara   ext4: Reserve rev...
99
100
  	return jbd2__journal_start(journal, blocks, rsv_blocks, revoke_creds,
  				   GFP_NOFS, type, line);
722887ddc   Theodore Ts'o   ext4: move the jb...
101
102
103
104
105
106
107
108
109
110
111
112
  }
  
  int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
  {
  	struct super_block *sb;
  	int err;
  	int rc;
  
  	if (!ext4_handle_valid(handle)) {
  		ext4_put_nojournal(handle);
  		return 0;
  	}
9d5065940   Lukas Czerner   ext4: fix NULL po...
113

6934da923   Lukas Czerner   ext4: fix potenti...
114
  	err = handle->h_err;
9d5065940   Lukas Czerner   ext4: fix NULL po...
115
  	if (!handle->h_transaction) {
6934da923   Lukas Czerner   ext4: fix potenti...
116
117
  		rc = jbd2_journal_stop(handle);
  		return err ? err : rc;
9d5065940   Lukas Czerner   ext4: fix NULL po...
118
  	}
722887ddc   Theodore Ts'o   ext4: move the jb...
119
  	sb = handle->h_transaction->t_journal->j_private;
722887ddc   Theodore Ts'o   ext4: move the jb...
120
121
122
123
124
125
126
127
  	rc = jbd2_journal_stop(handle);
  
  	if (!err)
  		err = rc;
  	if (err)
  		__ext4_std_error(sb, where, line, err);
  	return err;
  }
5fe2fe895   Jan Kara   ext4: provide wra...
128
129
130
131
132
133
134
135
136
137
  handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line,
  					int type)
  {
  	struct super_block *sb;
  	int err;
  
  	if (!ext4_handle_valid(handle))
  		return ext4_get_nojournal();
  
  	sb = handle->h_journal->j_private;
a9a8344ee   Jan Kara   ext4, jbd2: Provi...
138
139
  	trace_ext4_journal_start_reserved(sb,
  				jbd2_handle_buffer_credits(handle), _RET_IP_);
5fe2fe895   Jan Kara   ext4: provide wra...
140
141
142
143
144
145
146
147
148
149
150
  	err = ext4_journal_check_start(sb);
  	if (err < 0) {
  		jbd2_journal_free_reserved(handle);
  		return ERR_PTR(err);
  	}
  
  	err = jbd2_journal_start_reserved(handle, type, line);
  	if (err < 0)
  		return ERR_PTR(err);
  	return handle;
  }
a41303679   Jan Kara   ext4: Provide fun...
151
  int __ext4_journal_ensure_credits(handle_t *handle, int check_cred,
83448bdfb   Jan Kara   ext4: Reserve rev...
152
  				  int extend_cred, int revoke_cred)
a41303679   Jan Kara   ext4: Provide fun...
153
154
155
  {
  	if (!ext4_handle_valid(handle))
  		return 0;
83448bdfb   Jan Kara   ext4: Reserve rev...
156
157
  	if (jbd2_handle_buffer_credits(handle) >= check_cred &&
  	    handle->h_revoke_credits >= revoke_cred)
a41303679   Jan Kara   ext4: Provide fun...
158
  		return 0;
83448bdfb   Jan Kara   ext4: Reserve rev...
159
160
161
  	extend_cred = max(0, extend_cred - jbd2_handle_buffer_credits(handle));
  	revoke_cred = max(0, revoke_cred - handle->h_revoke_credits);
  	return ext4_journal_extend(handle, extend_cred, revoke_cred);
a41303679   Jan Kara   ext4: Provide fun...
162
  }
c197855ea   Stephen Hemminger   ext4: make local ...
163
164
165
166
  static void ext4_journal_abort_handle(const char *caller, unsigned int line,
  				      const char *err_fn,
  				      struct buffer_head *bh,
  				      handle_t *handle, int err)
722887ddc   Theodore Ts'o   ext4: move the jb...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  {
  	char nbuf[16];
  	const char *errstr = ext4_decode_error(NULL, err, nbuf);
  
  	BUG_ON(!ext4_handle_valid(handle));
  
  	if (bh)
  		BUFFER_TRACE(bh, "abort");
  
  	if (!handle->h_err)
  		handle->h_err = err;
  
  	if (is_handle_aborted(handle))
  		return;
  
  	printk(KERN_ERR "EXT4-fs: %s:%d: aborting transaction: %s in %s
  ",
  	       caller, line, errstr, err_fn);
  
  	jbd2_journal_abort_handle(handle);
  }
bc71726c7   zhangyi (F)   ext4: abort the f...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  static void ext4_check_bdev_write_error(struct super_block *sb)
  {
  	struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
  	struct ext4_sb_info *sbi = EXT4_SB(sb);
  	int err;
  
  	/*
  	 * If the block device has write error flag, it may have failed to
  	 * async write out metadata buffers in the background. In this case,
  	 * we could read old data from disk and write it out again, which
  	 * may lead to on-disk filesystem inconsistency.
  	 */
  	if (errseq_check(&mapping->wb_err, READ_ONCE(sbi->s_bdev_wb_err))) {
  		spin_lock(&sbi->s_bdev_wb_lock);
  		err = errseq_check_and_advance(&mapping->wb_err, &sbi->s_bdev_wb_err);
  		spin_unlock(&sbi->s_bdev_wb_lock);
  		if (err)
  			ext4_error_err(sb, -err,
  				       "Error while async write back metadata");
  	}
  }
90c7201b9   Theodore Ts'o   ext4: Pass line n...
209
210
  int __ext4_journal_get_write_access(const char *where, unsigned int line,
  				    handle_t *handle, struct buffer_head *bh)
8984d137d   Andrew Morton   [PATCH] ext4: uni...
211
  {
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
212
  	int err = 0;
b10a44c36   Theodore Ts'o   ext4: add might_s...
213
  	might_sleep();
bc71726c7   zhangyi (F)   ext4: abort the f...
214
215
  	if (bh->b_bdev->bd_super)
  		ext4_check_bdev_write_error(bh->b_bdev->bd_super);
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
216
217
218
  	if (ext4_handle_valid(handle)) {
  		err = jbd2_journal_get_write_access(handle, bh);
  		if (err)
90c7201b9   Theodore Ts'o   ext4: Pass line n...
219
  			ext4_journal_abort_handle(where, line, __func__, bh,
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
220
221
  						  handle, err);
  	}
8984d137d   Andrew Morton   [PATCH] ext4: uni...
222
223
  	return err;
  }
d6797d14b   Theodore Ts'o   ext4: move ext4_f...
224
225
226
227
228
229
230
231
232
233
234
235
  /*
   * The ext4 forget function must perform a revoke if we are freeing data
   * which has been journaled.  Metadata (eg. indirect blocks) must be
   * revoked in all cases.
   *
   * "bh" may be NULL: a metadata block may have been freed from memory
   * but there may still be a record of it in the journal, and that record
   * still needs to be revoked.
   *
   * If the handle isn't valid we're not journaling, but we still need to
   * call into ext4_journal_revoke() to put the buffer head.
   */
90c7201b9   Theodore Ts'o   ext4: Pass line n...
236
237
238
  int __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)
d6797d14b   Theodore Ts'o   ext4: move ext4_f...
239
240
241
242
243
244
245
246
247
248
249
250
251
  {
  	int err;
  
  	might_sleep();
  
  	trace_ext4_forget(inode, is_metadata, blocknr);
  	BUFFER_TRACE(bh, "enter");
  
  	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
  		  "data mode %x
  ",
  		  bh, is_metadata, inode->i_mode,
  		  test_opt(inode->i_sb, DATA_FLAGS));
e4684b3fb   Theodore Ts'o   ext4: fold ext4_j...
252
253
254
255
256
  	/* In the no journal case, we can just do a bforget and return */
  	if (!ext4_handle_valid(handle)) {
  		bforget(bh);
  		return 0;
  	}
d6797d14b   Theodore Ts'o   ext4: move ext4_f...
257
258
259
260
261
262
263
264
265
  	/* Never use the revoke function if we are doing full data
  	 * journaling: there is no need to, and a V1 superblock won't
  	 * support it.  Otherwise, only skip the revoke on un-journaled
  	 * data blocks. */
  
  	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
  	    (!is_metadata && !ext4_should_journal_data(inode))) {
  		if (bh) {
  			BUFFER_TRACE(bh, "call jbd2_journal_forget");
b7e57e7c2   Theodore Ts'o   ext4: fold ext4_j...
266
267
  			err = jbd2_journal_forget(handle, bh);
  			if (err)
90c7201b9   Theodore Ts'o   ext4: Pass line n...
268
269
  				ext4_journal_abort_handle(where, line, __func__,
  							  bh, handle, err);
b7e57e7c2   Theodore Ts'o   ext4: fold ext4_j...
270
  			return err;
d6797d14b   Theodore Ts'o   ext4: move ext4_f...
271
272
273
274
275
276
277
  		}
  		return 0;
  	}
  
  	/*
  	 * data!=journal && (is_metadata || should_journal_data(inode))
  	 */
e4684b3fb   Theodore Ts'o   ext4: fold ext4_j...
278
279
280
  	BUFFER_TRACE(bh, "call jbd2_journal_revoke");
  	err = jbd2_journal_revoke(handle, blocknr, bh);
  	if (err) {
90c7201b9   Theodore Ts'o   ext4: Pass line n...
281
282
  		ext4_journal_abort_handle(where, line, __func__,
  					  bh, handle, err);
54d3adbc2   Theodore Ts'o   ext4: save all er...
283
  		__ext4_abort(inode->i_sb, where, line, -err,
c398eda0e   Theodore Ts'o   ext4: Pass line n...
284
  			   "error %d when attempting revoke", err);
e4684b3fb   Theodore Ts'o   ext4: fold ext4_j...
285
  	}
d6797d14b   Theodore Ts'o   ext4: move ext4_f...
286
287
288
  	BUFFER_TRACE(bh, "exit");
  	return err;
  }
90c7201b9   Theodore Ts'o   ext4: Pass line n...
289
  int __ext4_journal_get_create_access(const char *where, unsigned int line,
8984d137d   Andrew Morton   [PATCH] ext4: uni...
290
291
  				handle_t *handle, struct buffer_head *bh)
  {
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
292
293
294
295
296
  	int err = 0;
  
  	if (ext4_handle_valid(handle)) {
  		err = jbd2_journal_get_create_access(handle, bh);
  		if (err)
90c7201b9   Theodore Ts'o   ext4: Pass line n...
297
298
  			ext4_journal_abort_handle(where, line, __func__,
  						  bh, handle, err);
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
299
  	}
8984d137d   Andrew Morton   [PATCH] ext4: uni...
300
301
  	return err;
  }
90c7201b9   Theodore Ts'o   ext4: Pass line n...
302
303
304
  int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
  				 handle_t *handle, struct inode *inode,
  				 struct buffer_head *bh)
8984d137d   Andrew Morton   [PATCH] ext4: uni...
305
  {
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
306
  	int err = 0;
b10a44c36   Theodore Ts'o   ext4: add might_s...
307
  	might_sleep();
13fca323e   Theodore Ts'o   ext4: mark metada...
308
309
  	set_buffer_meta(bh);
  	set_buffer_prio(bh);
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
310
311
  	if (ext4_handle_valid(handle)) {
  		err = jbd2_journal_dirty_metadata(handle, bh);
c5d311926   Dmitry Monakhov   ext4: fix over-de...
312
313
  		/* Errors can only happen due to aborted journal or a nasty bug */
  		if (!is_handle_aborted(handle) && WARN_ON_ONCE(err)) {
91aa11fae   Jan Kara   jbd2: Fix use aft...
314
315
  			ext4_journal_abort_handle(where, line, __func__, bh,
  						  handle, err);
66a4cb187   Theodore Ts'o   jbd2: improve err...
316
317
318
319
320
321
322
  			if (inode == NULL) {
  				pr_err("EXT4: jbd2_journal_dirty_metadata "
  				       "failed: handle type %u started at "
  				       "line %u, credits %u/%u, errcode %d",
  				       handle->h_type,
  				       handle->h_line_no,
  				       handle->h_requested_credits,
a9a8344ee   Jan Kara   ext4, jbd2: Provi...
323
  				       jbd2_handle_buffer_credits(handle), err);
66a4cb187   Theodore Ts'o   jbd2: improve err...
324
325
  				return err;
  			}
ae1495b12   Theodore Ts'o   ext4: call ext4_e...
326
327
328
329
330
331
332
333
  			ext4_error_inode(inode, where, line,
  					 bh->b_blocknr,
  					 "journal_dirty_metadata failed: "
  					 "handle type %u started at line %u, "
  					 "credits %u/%u, errcode %d",
  					 handle->h_type,
  					 handle->h_line_no,
  					 handle->h_requested_credits,
a9a8344ee   Jan Kara   ext4, jbd2: Provi...
334
335
  					 jbd2_handle_buffer_credits(handle),
  					 err);
9ea7a0df6   Theodore Ts'o   jbd2: add debuggi...
336
  		}
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
337
  	} else {
f2eeca099   Harshad Shirwadkar   ext4: force buffe...
338
  		set_buffer_uptodate(bh);
73b50c1c9   Curt Wohlgemuth   ext4: Fix BUG_ON ...
339
  		if (inode)
fe188c0e0   Theodore Ts'o   ext4: Assure that...
340
341
342
  			mark_buffer_dirty_inode(bh, inode);
  		else
  			mark_buffer_dirty(bh);
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
343
344
345
  		if (inode && inode_needs_sync(inode)) {
  			sync_dirty_buffer(bh);
  			if (buffer_req(bh) && !buffer_uptodate(bh)) {
54d3adbc2   Theodore Ts'o   ext4: save all er...
346
347
  				ext4_error_inode_err(inode, where, line,
  						     bh->b_blocknr, EIO,
c398eda0e   Theodore Ts'o   ext4: Pass line n...
348
  					"IO error syncing itable block");
0390131ba   Frank Mayhar   ext4: Allow ext4 ...
349
350
351
352
  				err = -EIO;
  			}
  		}
  	}
8984d137d   Andrew Morton   [PATCH] ext4: uni...
353
354
  	return err;
  }
a0375156c   Theodore Ts'o   ext4: Clean up s_...
355

90c7201b9   Theodore Ts'o   ext4: Pass line n...
356
  int __ext4_handle_dirty_super(const char *where, unsigned int line,
b50924c2c   Artem Bityutskiy   ext4: remove unne...
357
  			      handle_t *handle, struct super_block *sb)
a0375156c   Theodore Ts'o   ext4: Clean up s_...
358
359
360
  {
  	struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
  	int err = 0;
06db49e68   Theodore Ts'o   ext4: fix metadat...
361
  	ext4_superblock_csum_set(sb);
a0375156c   Theodore Ts'o   ext4: Clean up s_...
362
363
364
  	if (ext4_handle_valid(handle)) {
  		err = jbd2_journal_dirty_metadata(handle, bh);
  		if (err)
90c7201b9   Theodore Ts'o   ext4: Pass line n...
365
366
  			ext4_journal_abort_handle(where, line, __func__,
  						  bh, handle, err);
06db49e68   Theodore Ts'o   ext4: fix metadat...
367
  	} else
a9c473178   Darrick J. Wong   ext4: calculate a...
368
  		mark_buffer_dirty(bh);
a0375156c   Theodore Ts'o   ext4: Clean up s_...
369
370
  	return err;
  }