Skip to content

Commit 188c299

Browse files
jankaratytso
authored andcommitted
ext4: Support for checksumming from journal triggers
JBD2 layer support triggers which are called when journaling layer moves buffer to a certain state. We can use the frozen trigger, which gets called when buffer data is frozen and about to be written out to the journal, to compute block checksums for some buffer types (similarly as does ocfs2). This avoids unnecessary repeated recomputation of the checksum (at the cost of larger window where memory corruption won't be caught by checksumming) and is even necessary when there are unsynchronized updaters of the checksummed data. So add superblock and journal trigger type arguments to ext4_journal_get_write_access() and ext4_journal_get_create_access() so that frozen triggers can be set accordingly. Also add inode argument to ext4_walk_page_buffers() and all the callbacks used with that function for the same purpose. This patch is mostly only a change of prototype of the above mentioned functions and a few small helpers. Real checksumming will come later. Reviewed-by: Theodore Ts'o <[email protected]> Signed-off-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent a54c461 commit 188c299

File tree

16 files changed

+259
-128
lines changed

16 files changed

+259
-128
lines changed

fs/ext4/ext4.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,6 +1447,24 @@ struct ext4_super_block {
14471447

14481448
#define EXT4_ENC_UTF8_12_1 1
14491449

1450+
/* Types of ext4 journal triggers */
1451+
enum ext4_journal_trigger_type {
1452+
EXT4_JTR_NONE /* This must be the last entry for indexing to work! */
1453+
};
1454+
1455+
#define EXT4_JOURNAL_TRIGGER_COUNT EXT4_JTR_NONE
1456+
1457+
struct ext4_journal_trigger {
1458+
struct jbd2_buffer_trigger_type tr_triggers;
1459+
struct super_block *sb;
1460+
};
1461+
1462+
static inline struct ext4_journal_trigger *EXT4_TRIGGER(
1463+
struct jbd2_buffer_trigger_type *trigger)
1464+
{
1465+
return container_of(trigger, struct ext4_journal_trigger, tr_triggers);
1466+
}
1467+
14501468
/*
14511469
* fourth extended-fs super-block data in memory
14521470
*/
@@ -1628,6 +1646,9 @@ struct ext4_sb_info {
16281646
struct mb_cache *s_ea_inode_cache;
16291647
spinlock_t s_es_lock ____cacheline_aligned_in_smp;
16301648

1649+
/* Journal triggers for checksum computation */
1650+
struct ext4_journal_trigger s_journal_triggers[EXT4_JOURNAL_TRIGGER_COUNT];
1651+
16311652
/* Ratelimit ext4 messages. */
16321653
struct ratelimit_state s_err_ratelimit_state;
16331654
struct ratelimit_state s_warning_ratelimit_state;
@@ -2923,13 +2944,14 @@ int ext4_get_block(struct inode *inode, sector_t iblock,
29232944
int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
29242945
struct buffer_head *bh, int create);
29252946
int ext4_walk_page_buffers(handle_t *handle,
2947+
struct inode *inode,
29262948
struct buffer_head *head,
29272949
unsigned from,
29282950
unsigned to,
29292951
int *partial,
2930-
int (*fn)(handle_t *handle,
2952+
int (*fn)(handle_t *handle, struct inode *inode,
29312953
struct buffer_head *bh));
2932-
int do_journal_get_write_access(handle_t *handle,
2954+
int do_journal_get_write_access(handle_t *handle, struct inode *inode,
29332955
struct buffer_head *bh);
29342956
#define FALL_BACK_TO_NONDELALLOC 1
29352957
#define CONVERT_INLINE_DATA 2

fs/ext4/ext4_jbd2.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,11 @@ static void ext4_check_bdev_write_error(struct super_block *sb)
218218
}
219219

220220
int __ext4_journal_get_write_access(const char *where, unsigned int line,
221-
handle_t *handle, struct buffer_head *bh)
221+
handle_t *handle, struct super_block *sb,
222+
struct buffer_head *bh,
223+
enum ext4_journal_trigger_type trigger_type)
222224
{
223-
int err = 0;
225+
int err;
224226

225227
might_sleep();
226228

@@ -229,11 +231,18 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
229231

230232
if (ext4_handle_valid(handle)) {
231233
err = jbd2_journal_get_write_access(handle, bh);
232-
if (err)
234+
if (err) {
233235
ext4_journal_abort_handle(where, line, __func__, bh,
234236
handle, err);
237+
return err;
238+
}
235239
}
236-
return err;
240+
if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
241+
return 0;
242+
BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
243+
jbd2_journal_set_triggers(bh,
244+
&EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
245+
return 0;
237246
}
238247

239248
/*
@@ -301,17 +310,27 @@ int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
301310
}
302311

303312
int __ext4_journal_get_create_access(const char *where, unsigned int line,
304-
handle_t *handle, struct buffer_head *bh)
313+
handle_t *handle, struct super_block *sb,
314+
struct buffer_head *bh,
315+
enum ext4_journal_trigger_type trigger_type)
305316
{
306-
int err = 0;
317+
int err;
307318

308-
if (ext4_handle_valid(handle)) {
309-
err = jbd2_journal_get_create_access(handle, bh);
310-
if (err)
311-
ext4_journal_abort_handle(where, line, __func__,
312-
bh, handle, err);
319+
if (!ext4_handle_valid(handle))
320+
return 0;
321+
322+
err = jbd2_journal_get_create_access(handle, bh);
323+
if (err) {
324+
ext4_journal_abort_handle(where, line, __func__, bh, handle,
325+
err);
326+
return err;
313327
}
314-
return err;
328+
if (trigger_type == EXT4_JTR_NONE || !ext4_has_metadata_csum(sb))
329+
return 0;
330+
BUG_ON(trigger_type >= EXT4_JOURNAL_TRIGGER_COUNT);
331+
jbd2_journal_set_triggers(bh,
332+
&EXT4_SB(sb)->s_journal_triggers[trigger_type].tr_triggers);
333+
return 0;
315334
}
316335

317336
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,

fs/ext4/ext4_jbd2.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,26 +231,32 @@ int ext4_expand_extra_isize(struct inode *inode,
231231
* Wrapper functions with which ext4 calls into JBD.
232232
*/
233233
int __ext4_journal_get_write_access(const char *where, unsigned int line,
234-
handle_t *handle, struct buffer_head *bh);
234+
handle_t *handle, struct super_block *sb,
235+
struct buffer_head *bh,
236+
enum ext4_journal_trigger_type trigger_type);
235237

236238
int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
237239
int is_metadata, struct inode *inode,
238240
struct buffer_head *bh, ext4_fsblk_t blocknr);
239241

240242
int __ext4_journal_get_create_access(const char *where, unsigned int line,
241-
handle_t *handle, struct buffer_head *bh);
243+
handle_t *handle, struct super_block *sb,
244+
struct buffer_head *bh,
245+
enum ext4_journal_trigger_type trigger_type);
242246

243247
int __ext4_handle_dirty_metadata(const char *where, unsigned int line,
244248
handle_t *handle, struct inode *inode,
245249
struct buffer_head *bh);
246250

247-
#define ext4_journal_get_write_access(handle, bh) \
248-
__ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh))
251+
#define ext4_journal_get_write_access(handle, sb, bh, trigger_type) \
252+
__ext4_journal_get_write_access(__func__, __LINE__, (handle), (sb), \
253+
(bh), (trigger_type))
249254
#define ext4_forget(handle, is_metadata, inode, bh, block_nr) \
250255
__ext4_forget(__func__, __LINE__, (handle), (is_metadata), (inode), \
251256
(bh), (block_nr))
252-
#define ext4_journal_get_create_access(handle, bh) \
253-
__ext4_journal_get_create_access(__func__, __LINE__, (handle), (bh))
257+
#define ext4_journal_get_create_access(handle, sb, bh, trigger_type) \
258+
__ext4_journal_get_create_access(__func__, __LINE__, (handle), (sb), \
259+
(bh), (trigger_type))
254260
#define ext4_handle_dirty_metadata(handle, inode, bh) \
255261
__ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \
256262
(bh))

fs/ext4/extents.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ static int ext4_ext_get_access(handle_t *handle, struct inode *inode,
139139
if (path->p_bh) {
140140
/* path points to block */
141141
BUFFER_TRACE(path->p_bh, "get_write_access");
142-
return ext4_journal_get_write_access(handle, path->p_bh);
142+
return ext4_journal_get_write_access(handle, inode->i_sb,
143+
path->p_bh, EXT4_JTR_NONE);
143144
}
144145
/* path points to leaf/index in inode body */
145146
/* we use in-core data, no need to protect them */
@@ -1082,7 +1083,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
10821083
}
10831084
lock_buffer(bh);
10841085

1085-
err = ext4_journal_get_create_access(handle, bh);
1086+
err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
1087+
EXT4_JTR_NONE);
10861088
if (err)
10871089
goto cleanup;
10881090

@@ -1160,7 +1162,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
11601162
}
11611163
lock_buffer(bh);
11621164

1163-
err = ext4_journal_get_create_access(handle, bh);
1165+
err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
1166+
EXT4_JTR_NONE);
11641167
if (err)
11651168
goto cleanup;
11661169

@@ -1286,7 +1289,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode,
12861289
return -ENOMEM;
12871290
lock_buffer(bh);
12881291

1289-
err = ext4_journal_get_create_access(handle, bh);
1292+
err = ext4_journal_get_create_access(handle, inode->i_sb, bh,
1293+
EXT4_JTR_NONE);
12901294
if (err) {
12911295
unlock_buffer(bh);
12921296
goto out;

fs/ext4/file.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,8 @@ static int ext4_sample_last_mounted(struct super_block *sb,
822822
if (IS_ERR(handle))
823823
goto out;
824824
BUFFER_TRACE(sbi->s_sbh, "get_write_access");
825-
err = ext4_journal_get_write_access(handle, sbi->s_sbh);
825+
err = ext4_journal_get_write_access(handle, sb, sbi->s_sbh,
826+
EXT4_JTR_NONE);
826827
if (err)
827828
goto out_journal;
828829
lock_buffer(sbi->s_sbh);

fs/ext4/ialloc.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,17 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
300300
}
301301

302302
BUFFER_TRACE(bitmap_bh, "get_write_access");
303-
fatal = ext4_journal_get_write_access(handle, bitmap_bh);
303+
fatal = ext4_journal_get_write_access(handle, sb, bitmap_bh,
304+
EXT4_JTR_NONE);
304305
if (fatal)
305306
goto error_return;
306307

307308
fatal = -ESRCH;
308309
gdp = ext4_get_group_desc(sb, block_group, &bh2);
309310
if (gdp) {
310311
BUFFER_TRACE(bh2, "get_write_access");
311-
fatal = ext4_journal_get_write_access(handle, bh2);
312+
fatal = ext4_journal_get_write_access(handle, sb, bh2,
313+
EXT4_JTR_NONE);
312314
}
313315
ext4_lock_group(sb, block_group);
314316
cleared = ext4_test_and_clear_bit(bit, bitmap_bh->b_data);
@@ -1085,7 +1087,8 @@ struct inode *__ext4_new_inode(struct user_namespace *mnt_userns,
10851087
}
10861088
}
10871089
BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
1088-
err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
1090+
err = ext4_journal_get_write_access(handle, sb, inode_bitmap_bh,
1091+
EXT4_JTR_NONE);
10891092
if (err) {
10901093
ext4_std_error(sb, err);
10911094
goto out;
@@ -1127,7 +1130,8 @@ struct inode *__ext4_new_inode(struct user_namespace *mnt_userns,
11271130
}
11281131

11291132
BUFFER_TRACE(group_desc_bh, "get_write_access");
1130-
err = ext4_journal_get_write_access(handle, group_desc_bh);
1133+
err = ext4_journal_get_write_access(handle, sb, group_desc_bh,
1134+
EXT4_JTR_NONE);
11311135
if (err) {
11321136
ext4_std_error(sb, err);
11331137
goto out;
@@ -1144,7 +1148,8 @@ struct inode *__ext4_new_inode(struct user_namespace *mnt_userns,
11441148
goto out;
11451149
}
11461150
BUFFER_TRACE(block_bitmap_bh, "get block bitmap access");
1147-
err = ext4_journal_get_write_access(handle, block_bitmap_bh);
1151+
err = ext4_journal_get_write_access(handle, sb, block_bitmap_bh,
1152+
EXT4_JTR_NONE);
11481153
if (err) {
11491154
brelse(block_bitmap_bh);
11501155
ext4_std_error(sb, err);
@@ -1583,8 +1588,8 @@ int ext4_init_inode_table(struct super_block *sb, ext4_group_t group,
15831588
num = sbi->s_itb_per_group - used_blks;
15841589

15851590
BUFFER_TRACE(group_desc_bh, "get_write_access");
1586-
ret = ext4_journal_get_write_access(handle,
1587-
group_desc_bh);
1591+
ret = ext4_journal_get_write_access(handle, sb, group_desc_bh,
1592+
EXT4_JTR_NONE);
15881593
if (ret)
15891594
goto err_out;
15901595

fs/ext4/indirect.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ static int ext4_alloc_branch(handle_t *handle,
354354
}
355355
lock_buffer(bh);
356356
BUFFER_TRACE(bh, "call get_create_access");
357-
err = ext4_journal_get_create_access(handle, bh);
357+
err = ext4_journal_get_create_access(handle, ar->inode->i_sb,
358+
bh, EXT4_JTR_NONE);
358359
if (err) {
359360
unlock_buffer(bh);
360361
goto failed;
@@ -429,7 +430,8 @@ static int ext4_splice_branch(handle_t *handle,
429430
*/
430431
if (where->bh) {
431432
BUFFER_TRACE(where->bh, "get_write_access");
432-
err = ext4_journal_get_write_access(handle, where->bh);
433+
err = ext4_journal_get_write_access(handle, ar->inode->i_sb,
434+
where->bh, EXT4_JTR_NONE);
433435
if (err)
434436
goto err_out;
435437
}
@@ -728,7 +730,8 @@ static int ext4_ind_truncate_ensure_credits(handle_t *handle,
728730
return ret;
729731
if (bh) {
730732
BUFFER_TRACE(bh, "retaking write access");
731-
ret = ext4_journal_get_write_access(handle, bh);
733+
ret = ext4_journal_get_write_access(handle, inode->i_sb, bh,
734+
EXT4_JTR_NONE);
732735
if (unlikely(ret))
733736
return ret;
734737
}
@@ -916,7 +919,8 @@ static void ext4_free_data(handle_t *handle, struct inode *inode,
916919

917920
if (this_bh) { /* For indirect block */
918921
BUFFER_TRACE(this_bh, "get_write_access");
919-
err = ext4_journal_get_write_access(handle, this_bh);
922+
err = ext4_journal_get_write_access(handle, inode->i_sb,
923+
this_bh, EXT4_JTR_NONE);
920924
/* Important: if we can't update the indirect pointers
921925
* to the blocks, we can't free them. */
922926
if (err)
@@ -1079,7 +1083,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
10791083
*/
10801084
BUFFER_TRACE(parent_bh, "get_write_access");
10811085
if (!ext4_journal_get_write_access(handle,
1082-
parent_bh)){
1086+
inode->i_sb, parent_bh,
1087+
EXT4_JTR_NONE)) {
10831088
*p = 0;
10841089
BUFFER_TRACE(parent_bh,
10851090
"call ext4_handle_dirty_metadata");

0 commit comments

Comments
 (0)