The JBD2 naming cleanups patch was missing a definition of JBD2_POISON_FREE
[ext4-patch-queue.git] / ext4-journal_chksum-2.6.20.patch
blobb0480fcf2239f0de82370f33f60ddfa5b534543d
1 ext4: Add the journal checksum feature
3 From: Girish Shilamkar <girish@clusterfs.com>
5 The journal checksum feature adds two new flags i.e
6 JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT and JBD2_FEATURE_COMPAT_CHECKSUM.
8 JBD2_FEATURE_CHECKSUM flag indicates that the commit block contains the
9 checksum for the blocks described by the descriptor blocks.
10 Due to checksums, writing of the commit record no longer needs to be
11 synchronous. Now commit record can be sent to disk without waiting for
12 descriptor blocks to be written to disk. This behavior is controlled
13 using JBD2_FEATURE_ASYNC_COMMIT flag. Older kernels/e2fsck should not be
14 able to recover the journal with _ASYNC_COMMIT hence it is made
15 incompat.
16 The commit header has been extended to hold the checksum along with the
17 type of the checksum.
19 For recovery in pass scan checksums are verified to ensure the sanity
20 and completeness(in case of _ASYNC_COMMIT) of every transaction.
22 Signed-off-by: Andreas Dilger <adilger@clusterfs.com>
23 Signed-off-by: Girish Shilamkar <girish@clusterfs.com>
24 Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
25 Signed-off-by: Mingming Cao <cmm@us.ibm.com>
26 ---
28 fs/ext4/super.c | 25 ++++++
29 fs/jbd2/commit.c | 175 ++++++++++++++++++++++++++++++++++++------------
30 fs/jbd2/journal.c | 28 +++++++
31 fs/jbd2/recovery.c | 125 ++++++++++++++++++++++++++++++++--
32 include/linux/ext4_fs.h | 3
33 include/linux/jbd2.h | 37 +++++++++-
34 6 files changed, 338 insertions(+), 55 deletions(-)
37 Index: linux-2.6.23-rc6/fs/ext4/super.c
38 ===================================================================
39 --- linux-2.6.23-rc6.orig/fs/ext4/super.c 2007-09-20 17:25:46.000000000 -0700
40 +++ linux-2.6.23-rc6/fs/ext4/super.c 2007-09-20 17:25:49.000000000 -0700
41 @@ -733,6 +733,7 @@ enum {
42 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
43 Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
44 Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
45 + Opt_journal_checksum, Opt_journal_async_commit,
46 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
47 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
48 Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
49 @@ -772,6 +773,8 @@ static match_table_t tokens = {
50 {Opt_journal_update, "journal=update"},
51 {Opt_journal_inum, "journal=%u"},
52 {Opt_journal_dev, "journal_dev=%u"},
53 + {Opt_journal_checksum, "journal_checksum"},
54 + {Opt_journal_async_commit, "journal_async_commit"},
55 {Opt_abort, "abort"},
56 {Opt_data_journal, "data=journal"},
57 {Opt_data_ordered, "data=ordered"},
58 @@ -959,6 +962,13 @@ static int parse_options (char *options,
59 return 0;
60 *journal_devnum = option;
61 break;
62 + case Opt_journal_checksum:
63 + set_opt (sbi->s_mount_opt, JOURNAL_CHECKSUM);
64 + break;
65 + case Opt_journal_async_commit:
66 + set_opt (sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT);
67 + set_opt (sbi->s_mount_opt, JOURNAL_CHECKSUM);
68 + break;
69 case Opt_noload:
70 set_opt (sbi->s_mount_opt, NOLOAD);
71 break;
72 @@ -1875,6 +1885,21 @@ static int ext4_fill_super (struct super
73 goto failed_mount4;
76 + if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
77 + jbd2_journal_set_features(sbi->s_journal,
78 + JBD2_FEATURE_COMPAT_CHECKSUM, 0,
79 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
80 + } else if (test_opt(sb, JOURNAL_CHECKSUM)) {
81 + jbd2_journal_set_features(sbi->s_journal,
82 + JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
83 + jbd2_journal_clear_features(sbi->s_journal, 0, 0,
84 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
85 + } else {
86 + jbd2_journal_clear_features(sbi->s_journal,
87 + JBD2_FEATURE_COMPAT_CHECKSUM, 0,
88 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
89 + }
91 /* We have now updated the journal if required, so we can
92 * validate the data journaling mode. */
93 switch (test_opt(sb, DATA_FLAGS)) {
94 Index: linux-2.6.23-rc6/fs/jbd2/commit.c
95 ===================================================================
96 --- linux-2.6.23-rc6.orig/fs/jbd2/commit.c 2007-09-19 11:37:41.000000000 -0700
97 +++ linux-2.6.23-rc6/fs/jbd2/commit.c 2007-09-20 17:25:49.000000000 -0700
98 @@ -20,6 +20,7 @@
99 #include <linux/slab.h>
100 #include <linux/mm.h>
101 #include <linux/pagemap.h>
102 +#include <linux/crc32.h>
105 * Default IO end handler for temporary BJ_IO buffer_heads.
106 @@ -92,15 +93,18 @@ static int inverted_lock(journal_t *jour
107 return 1;
110 -/* Done it all: now write the commit record. We should have
112 + * Done it all: now submit the commit record. We should have
113 * cleaned up our previous buffers by now, so if we are in abort
114 * mode we can now just skip the rest of the journal write
115 * entirely.
117 * Returns 1 if the journal needs to be aborted or 0 on success
119 -static int journal_write_commit_record(journal_t *journal,
120 - transaction_t *commit_transaction)
121 +static int journal_submit_commit_record(journal_t *journal,
122 + transaction_t *commit_transaction,
123 + struct buffer_head **cbh,
124 + __u32 crc32_sum)
126 struct journal_head *descriptor;
127 struct buffer_head *bh;
128 @@ -116,21 +120,36 @@ static int journal_write_commit_record(j
130 bh = jh2bh(descriptor);
132 - /* AKPM: buglet - add `i' to tmp! */
133 for (i = 0; i < bh->b_size; i += 512) {
134 - journal_header_t *tmp = (journal_header_t*)bh->b_data;
135 + struct commit_header *tmp =
136 + (struct commit_header *)(bh->b_data + i);
137 tmp->h_magic = cpu_to_be32(JBD2_MAGIC_NUMBER);
138 tmp->h_blocktype = cpu_to_be32(JBD2_COMMIT_BLOCK);
139 tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
141 + if (JBD2_HAS_COMPAT_FEATURE(journal,
142 + JBD2_FEATURE_COMPAT_CHECKSUM)) {
143 + tmp->h_chksum_type = JBD2_CRC32_CHKSUM;
144 + tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE;
145 + tmp->h_chksum[0] = cpu_to_be32(crc32_sum);
149 - JBUFFER_TRACE(descriptor, "write commit block");
150 + JBUFFER_TRACE(descriptor, "submit commit block");
151 + lock_buffer(bh);
153 set_buffer_dirty(bh);
154 - if (journal->j_flags & JBD2_BARRIER) {
155 + set_buffer_uptodate(bh);
156 + bh->b_end_io = journal_end_buffer_io_sync;
158 + if (journal->j_flags & JBD2_BARRIER &&
159 + !JBD2_HAS_COMPAT_FEATURE(journal,
160 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
161 set_buffer_ordered(bh);
162 barrier_done = 1;
164 - ret = sync_dirty_buffer(bh);
165 + ret = submit_bh(WRITE, bh);
167 /* is it possible for another commit to fail at roughly
168 * the same time as this one? If so, we don't want to
169 * trust the barrier flag in the super, but instead want
170 @@ -151,14 +170,72 @@ static int journal_write_commit_record(j
171 clear_buffer_ordered(bh);
172 set_buffer_uptodate(bh);
173 set_buffer_dirty(bh);
174 - ret = sync_dirty_buffer(bh);
175 + ret = submit_bh(WRITE, bh);
177 - put_bh(bh); /* One for getblk() */
178 - jbd2_journal_put_journal_head(descriptor);
179 + *cbh = bh;
180 + return ret;
184 + * This function along with journal_submit_commit_record
185 + * allows to write the commit record asynchronously.
186 + */
187 +static int journal_wait_on_commit_record(struct buffer_head *bh)
189 + int ret = 0;
191 - return (ret == -EIO);
192 + if (buffer_locked(bh))
193 + wait_on_buffer(bh);
195 + if (unlikely(!buffer_uptodate(bh)))
196 + ret = -EIO;
197 + put_bh(bh); /* One for getblk() */
198 + jbd2_journal_put_journal_head(bh2jh(bh));
200 + return ret;
204 + * Wait for all submitted IO to complete.
205 + */
206 +static int journal_wait_on_locked_list(journal_t *journal,
207 + transaction_t *commit_transaction)
209 + int ret = 0;
210 + struct journal_head *jh;
212 + while (commit_transaction->t_locked_list) {
213 + struct buffer_head *bh;
215 + jh = commit_transaction->t_locked_list->b_tprev;
216 + bh = jh2bh(jh);
217 + get_bh(bh);
218 + if (buffer_locked(bh)) {
219 + spin_unlock(&journal->j_list_lock);
220 + wait_on_buffer(bh);
221 + if (unlikely(!buffer_uptodate(bh)))
222 + ret = -EIO;
223 + spin_lock(&journal->j_list_lock);
225 + if (!inverted_lock(journal, bh)) {
226 + put_bh(bh);
227 + spin_lock(&journal->j_list_lock);
228 + continue;
230 + if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) {
231 + __jbd2_journal_unfile_buffer(jh);
232 + jbd_unlock_bh_state(bh);
233 + jbd2_journal_remove_journal_head(bh);
234 + put_bh(bh);
235 + } else {
236 + jbd_unlock_bh_state(bh);
238 + put_bh(bh);
239 + cond_resched_lock(&journal->j_list_lock);
241 + return ret;
244 static void journal_do_submit_data(struct buffer_head **wbuf, int bufs)
246 int i;
247 @@ -305,6 +382,8 @@ void jbd2_journal_commit_transaction(jou
248 int tag_flag;
249 int i;
250 int tag_bytes = journal_tag_bytes(journal);
251 + struct buffer_head *cbh = NULL; /* For transactional checksums */
252 + __u32 crc32_sum = ~0;
255 * First job: lock down the current transaction and wait for
256 @@ -440,38 +519,15 @@ void jbd2_journal_commit_transaction(jou
257 journal_submit_data_buffers(journal, commit_transaction);
260 - * Wait for all previously submitted IO to complete.
261 + * Wait for all previously submitted IO to complete if commit
262 + * record is to be written synchronously.
264 spin_lock(&journal->j_list_lock);
265 - while (commit_transaction->t_locked_list) {
266 - struct buffer_head *bh;
267 + if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
268 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT))
269 + err = journal_wait_on_locked_list(journal,
270 + commit_transaction);
272 - jh = commit_transaction->t_locked_list->b_tprev;
273 - bh = jh2bh(jh);
274 - get_bh(bh);
275 - if (buffer_locked(bh)) {
276 - spin_unlock(&journal->j_list_lock);
277 - wait_on_buffer(bh);
278 - if (unlikely(!buffer_uptodate(bh)))
279 - err = -EIO;
280 - spin_lock(&journal->j_list_lock);
282 - if (!inverted_lock(journal, bh)) {
283 - put_bh(bh);
284 - spin_lock(&journal->j_list_lock);
285 - continue;
287 - if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) {
288 - __jbd2_journal_unfile_buffer(jh);
289 - jbd_unlock_bh_state(bh);
290 - jbd2_journal_remove_journal_head(bh);
291 - put_bh(bh);
292 - } else {
293 - jbd_unlock_bh_state(bh);
295 - put_bh(bh);
296 - cond_resched_lock(&journal->j_list_lock);
298 spin_unlock(&journal->j_list_lock);
300 if (err)
301 @@ -639,6 +695,16 @@ void jbd2_journal_commit_transaction(jou
302 start_journal_io:
303 for (i = 0; i < bufs; i++) {
304 struct buffer_head *bh = wbuf[i];
305 + /*
306 + * Compute checksum.
307 + */
308 + if (JBD2_HAS_COMPAT_FEATURE(journal,
309 + JBD2_FEATURE_COMPAT_CHECKSUM)) {
310 + crc32_sum = crc32_be(crc32_sum,
311 + (void *)bh->b_data,
312 + bh->b_size);
315 lock_buffer(bh);
316 clear_buffer_dirty(bh);
317 set_buffer_uptodate(bh);
318 @@ -654,6 +720,23 @@ start_journal_io:
322 + /* Done it all: now write the commit record asynchronously. */
324 + if (JBD2_HAS_INCOMPAT_FEATURE(journal,
325 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
326 + err = journal_submit_commit_record(journal, commit_transaction,
327 + &cbh, crc32_sum);
328 + if (err)
329 + __jbd2_journal_abort_hard(journal);
331 + spin_lock(&journal->j_list_lock);
332 + err = journal_wait_on_locked_list(journal,
333 + commit_transaction);
334 + spin_unlock(&journal->j_list_lock);
335 + if (err)
336 + __jbd2_journal_abort_hard(journal);
339 /* Lo and behold: we have just managed to send a transaction to
340 the log. Before we can commit it, wait for the IO so far to
341 complete. Control buffers being written are on the
342 @@ -753,8 +836,14 @@ wait_for_iobuf:
344 jbd_debug(3, "JBD: commit phase 6\n");
346 - if (journal_write_commit_record(journal, commit_transaction))
347 - err = -EIO;
348 + if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
349 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
350 + err = journal_submit_commit_record(journal, commit_transaction,
351 + &cbh, crc32_sum);
352 + if (err)
353 + __jbd2_journal_abort_hard(journal);
355 + err = journal_wait_on_commit_record(cbh);
357 if (err)
358 __jbd2_journal_abort_hard(journal);
359 Index: linux-2.6.23-rc6/fs/jbd2/journal.c
360 ===================================================================
361 --- linux-2.6.23-rc6.orig/fs/jbd2/journal.c 2007-09-19 14:23:45.000000000 -0700
362 +++ linux-2.6.23-rc6/fs/jbd2/journal.c 2007-09-20 17:25:49.000000000 -0700
363 @@ -65,6 +65,7 @@ EXPORT_SYMBOL(jbd2_journal_update_format
364 EXPORT_SYMBOL(jbd2_journal_check_used_features);
365 EXPORT_SYMBOL(jbd2_journal_check_available_features);
366 EXPORT_SYMBOL(jbd2_journal_set_features);
367 +EXPORT_SYMBOL(jbd2_journal_clear_features);
368 EXPORT_SYMBOL(jbd2_journal_create);
369 EXPORT_SYMBOL(jbd2_journal_load);
370 EXPORT_SYMBOL(jbd2_journal_destroy);
371 @@ -1265,6 +1266,33 @@ int jbd2_journal_set_features (journal_t
372 return 1;
375 +/**
376 + * int jbd2_journal_clear_features () - Clear a given journal feature in the superblock
377 + * @journal: Journal to act on.
378 + * @compat: bitmask of compatible features
379 + * @ro: bitmask of features that force read-only mount
380 + * @incompat: bitmask of incompatible features
382 + * Clear a given journal feature as present on the
383 + * superblock. Returns true if the requested features could be reset.
385 + */
386 +int jbd2_journal_clear_features (journal_t *journal, unsigned long compat,
387 + unsigned long ro, unsigned long incompat)
389 + journal_superblock_t *sb;
391 + jbd_debug(1, "Clear features 0x%lx/0x%lx/0x%lx\n",
392 + compat, ro, incompat);
394 + sb = journal->j_superblock;
396 + sb->s_feature_compat &= ~cpu_to_be32(compat);
397 + sb->s_feature_ro_compat &= ~cpu_to_be32(ro);
398 + sb->s_feature_incompat &= ~cpu_to_be32(incompat);
400 + return 1;
404 * int jbd2_journal_update_format () - Update on-disk journal structure.
405 Index: linux-2.6.23-rc6/fs/jbd2/recovery.c
406 ===================================================================
407 --- linux-2.6.23-rc6.orig/fs/jbd2/recovery.c 2007-09-19 11:37:35.000000000 -0700
408 +++ linux-2.6.23-rc6/fs/jbd2/recovery.c 2007-09-20 17:25:49.000000000 -0700
409 @@ -21,6 +21,7 @@
410 #include <linux/jbd2.h>
411 #include <linux/errno.h>
412 #include <linux/slab.h>
413 +#include <linux/crc32.h>
414 #endif
417 @@ -316,6 +317,37 @@ static inline unsigned long long read_ta
418 return block;
422 + * cal_chksums calculates the checksums for the blocks described in the
423 + * descriptor block.
424 + */
425 +static int cal_chksums(journal_t *journal, struct buffer_head *bh,
426 + unsigned long *next_log_block, __u32 *crc32_sum)
428 + int i, num_blks, err;
429 + unsigned long io_block;
430 + struct buffer_head *obh;
432 + num_blks = count_tags(journal, bh);
433 + /* Calculate checksum of the descriptor block. */
434 + *crc32_sum = crc32_be(*crc32_sum, (void *)bh->b_data, bh->b_size);
436 + for (i = 0; i < num_blks; i++) {
437 + io_block = (*next_log_block)++;
438 + wrap(journal, *next_log_block);
439 + err = jread(&obh, journal, io_block);
440 + if (err) {
441 + printk(KERN_ERR "JBD: IO error %d recovering block "
442 + "%ld in log\n", err, io_block);
443 + return 1;
444 + } else {
445 + *crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data,
446 + obh->b_size);
449 + return 0;
452 static int do_one_pass(journal_t *journal,
453 struct recovery_info *info, enum passtype pass)
455 @@ -328,6 +360,7 @@ static int do_one_pass(journal_t *journa
456 unsigned int sequence;
457 int blocktype;
458 int tag_bytes = journal_tag_bytes(journal);
459 + __u32 crc32_sum = ~0; /* Transactional Checksums */
461 /* Precompute the maximum metadata descriptors in a descriptor block */
462 int MAX_BLOCKS_PER_DESC;
463 @@ -419,9 +452,23 @@ static int do_one_pass(journal_t *journa
464 switch(blocktype) {
465 case JBD2_DESCRIPTOR_BLOCK:
466 /* If it is a valid descriptor block, replay it
467 - * in pass REPLAY; otherwise, just skip over the
468 - * blocks it describes. */
469 + * in pass REPLAY; if journal_checksums enabled, then
470 + * calculate checksums in PASS_SCAN, otherwise,
471 + * just skip over the blocks it describes. */
472 if (pass != PASS_REPLAY) {
473 + if (pass == PASS_SCAN &&
474 + JBD2_HAS_COMPAT_FEATURE(journal,
475 + JBD2_FEATURE_COMPAT_CHECKSUM) &&
476 + !info->end_transaction) {
477 + if (cal_chksums(journal, bh,
478 + &next_log_block,
479 + &crc32_sum)) {
480 + brelse(bh);
481 + break;
483 + brelse(bh);
484 + continue;
486 next_log_block += count_tags(journal, bh);
487 wrap(journal, next_log_block);
488 brelse(bh);
489 @@ -516,9 +563,72 @@ static int do_one_pass(journal_t *journa
490 continue;
492 case JBD2_COMMIT_BLOCK:
493 - /* Found an expected commit block: not much to
494 - * do other than move on to the next sequence
495 + /* How to differentiate between interrupted commit
496 + * and journal corruption ?
498 + * {nth transaction}
499 + * Checksum Verification Failed
500 + * |
501 + * ____________________
502 + * | |
503 + * async_commit sync_commit
504 + * | |
505 + * | GO TO NEXT "Journal Corruption"
506 + * | TRANSACTION
507 + * |
508 + * {(n+1)th transanction}
509 + * |
510 + * _______|______________
511 + * | |
512 + * Commit block found Commit block not found
513 + * | |
514 + * "Journal Corruption" |
515 + * _____________|_________
516 + * | |
517 + * nth trans corrupt OR nth trans
518 + * and (n+1)th interrupted interrupted
519 + * before commit block
520 + * could reach the disk.
521 + * (Cannot find the difference in above
522 + * mentioned conditions. Hence assume
523 + * "Interrupted Commit".)
524 + */
526 + /* Found an expected commit block: if checksums
527 + * are present verify them in PASS_SCAN; else not
528 + * much to do other than move on to the next sequence
529 * number. */
530 + if (pass == PASS_SCAN &&
531 + JBD2_HAS_COMPAT_FEATURE(journal,
532 + JBD2_FEATURE_COMPAT_CHECKSUM)) {
533 + struct commit_header *cbh =
534 + (struct commit_header *)bh->b_data;
535 + unsigned found_chksum =
536 + be32_to_cpu(cbh->h_chksum[0]);
538 + if (info->end_transaction) {
539 + printk(KERN_ERR "JBD: Transaction %u "
540 + "found to be corrupt.\n",
541 + next_commit_ID - 1);
542 + brelse(bh);
543 + break;
546 + if (crc32_sum != found_chksum) {
547 + info->end_transaction = next_commit_ID;
549 + if (!JBD2_HAS_COMPAT_FEATURE(journal,
550 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)){
551 + printk(KERN_ERR
552 + "JBD: Transaction %u "
553 + "found to be corrupt.\n",
554 + next_commit_ID);
555 + brelse(bh);
556 + break;
559 + crc32_sum = ~0;
561 brelse(bh);
562 next_commit_ID++;
563 continue;
564 @@ -554,9 +664,10 @@ static int do_one_pass(journal_t *journa
565 * transaction marks the end of the valid log.
568 - if (pass == PASS_SCAN)
569 - info->end_transaction = next_commit_ID;
570 - else {
571 + if (pass == PASS_SCAN) {
572 + if (!info->end_transaction)
573 + info->end_transaction = next_commit_ID;
574 + } else {
575 /* It's really bad news if different passes end up at
576 * different places (but possible due to IO errors). */
577 if (info->end_transaction != next_commit_ID) {
578 Index: linux-2.6.23-rc6/include/linux/ext4_fs.h
579 ===================================================================
580 --- linux-2.6.23-rc6.orig/include/linux/ext4_fs.h 2007-09-20 17:25:46.000000000 -0700
581 +++ linux-2.6.23-rc6/include/linux/ext4_fs.h 2007-09-20 17:25:49.000000000 -0700
582 @@ -488,7 +488,8 @@ do { \
583 #define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */
584 #define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */
585 #define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */
587 +#define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */
588 +#define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */
589 /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
590 #ifndef _LINUX_EXT2_FS_H
591 #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt
592 Index: linux-2.6.23-rc6/include/linux/jbd2.h
593 ===================================================================
594 --- linux-2.6.23-rc6.orig/include/linux/jbd2.h 2007-09-19 11:37:41.000000000 -0700
595 +++ linux-2.6.23-rc6/include/linux/jbd2.h 2007-09-20 17:25:49.000000000 -0700
596 @@ -149,6 +149,29 @@ typedef struct journal_header_s
597 __be32 h_sequence;
598 } journal_header_t;
601 + * Checksum types.
602 + */
603 +#define JBD2_CRC32_CHKSUM 1
604 +#define JBD2_MD5_CHKSUM 2
605 +#define JBD2_SHA1_CHKSUM 3
607 +#define JBD2_CRC32_CHKSUM_SIZE 4
609 +#define JBD2_CHECKSUM_BYTES (32 / sizeof(u32))
611 + * Commit block header for storing transactional checksums:
612 + */
613 +struct commit_header
615 + __be32 h_magic;
616 + __be32 h_blocktype;
617 + __be32 h_sequence;
618 + unsigned char h_chksum_type;
619 + unsigned char h_chksum_size;
620 + unsigned char h_padding[2];
621 + __be32 h_chksum[JBD2_CHECKSUM_BYTES];
625 * The block tag: used to describe a single buffer in the journal.
626 @@ -242,14 +265,18 @@ typedef struct journal_superblock_s
627 ((j)->j_format_version >= 2 && \
628 ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask))))
630 -#define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001
631 -#define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002
632 +#define JBD2_FEATURE_COMPAT_CHECKSUM 0x00000001
634 +#define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001
635 +#define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002
636 +#define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004
638 /* Features known to this kernel version: */
639 -#define JBD2_KNOWN_COMPAT_FEATURES 0
640 +#define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM
641 #define JBD2_KNOWN_ROCOMPAT_FEATURES 0
642 #define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \
643 - JBD2_FEATURE_INCOMPAT_64BIT)
644 + JBD2_FEATURE_INCOMPAT_64BIT | \
645 + JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)
647 #ifdef __KERNEL__
649 @@ -932,6 +959,8 @@ extern int jbd2_journal_check_availab
650 (journal_t *, unsigned long, unsigned long, unsigned long);
651 extern int jbd2_journal_set_features
652 (journal_t *, unsigned long, unsigned long, unsigned long);
653 +extern int jbd2_journal_clear_features
654 + (journal_t *, unsigned long, unsigned long, unsigned long);
655 extern int jbd2_journal_create (journal_t *);
656 extern int jbd2_journal_load (journal_t *journal);
657 extern void jbd2_journal_destroy (journal_t *);