aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jbd2')
-rw-r--r--fs/jbd2/Kconfig2
-rw-r--r--fs/jbd2/commit.c70
-rw-r--r--fs/jbd2/journal.c132
-rw-r--r--fs/jbd2/recovery.c126
-rw-r--r--fs/jbd2/revoke.c27
-rw-r--r--fs/jbd2/transaction.c4
6 files changed, 349 insertions, 12 deletions
diff --git a/fs/jbd2/Kconfig b/fs/jbd2/Kconfig
index f32f346f4b0a..69a48c2944da 100644
--- a/fs/jbd2/Kconfig
+++ b/fs/jbd2/Kconfig
@@ -1,6 +1,8 @@
1config JBD2 1config JBD2
2 tristate 2 tristate
3 select CRC32 3 select CRC32
4 select CRYPTO
5 select CRYPTO_CRC32C
4 help 6 help
5 This is a generic journaling layer for block devices that support 7 This is a generic journaling layer for block devices that support
6 both 32-bit and 64-bit block numbers. It is currently used by 8 both 32-bit and 64-bit block numbers. It is currently used by
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 840f70f50792..216f4299f65e 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -85,6 +85,24 @@ nope:
85 __brelse(bh); 85 __brelse(bh);
86} 86}
87 87
88static void jbd2_commit_block_csum_set(journal_t *j,
89 struct journal_head *descriptor)
90{
91 struct commit_header *h;
92 __u32 csum;
93
94 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
95 return;
96
97 h = (struct commit_header *)(jh2bh(descriptor)->b_data);
98 h->h_chksum_type = 0;
99 h->h_chksum_size = 0;
100 h->h_chksum[0] = 0;
101 csum = jbd2_chksum(j, j->j_csum_seed, jh2bh(descriptor)->b_data,
102 j->j_blocksize);
103 h->h_chksum[0] = cpu_to_be32(csum);
104}
105
88/* 106/*
89 * Done it all: now submit the commit record. We should have 107 * Done it all: now submit the commit record. We should have
90 * cleaned up our previous buffers by now, so if we are in abort 108 * cleaned up our previous buffers by now, so if we are in abort
@@ -128,6 +146,7 @@ static int journal_submit_commit_record(journal_t *journal,
128 tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE; 146 tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE;
129 tmp->h_chksum[0] = cpu_to_be32(crc32_sum); 147 tmp->h_chksum[0] = cpu_to_be32(crc32_sum);
130 } 148 }
149 jbd2_commit_block_csum_set(journal, descriptor);
131 150
132 JBUFFER_TRACE(descriptor, "submit commit block"); 151 JBUFFER_TRACE(descriptor, "submit commit block");
133 lock_buffer(bh); 152 lock_buffer(bh);
@@ -301,6 +320,44 @@ static void write_tag_block(int tag_bytes, journal_block_tag_t *tag,
301 tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); 320 tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1);
302} 321}
303 322
323static void jbd2_descr_block_csum_set(journal_t *j,
324 struct journal_head *descriptor)
325{
326 struct jbd2_journal_block_tail *tail;
327 __u32 csum;
328
329 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
330 return;
331
332 tail = (struct jbd2_journal_block_tail *)
333 (jh2bh(descriptor)->b_data + j->j_blocksize -
334 sizeof(struct jbd2_journal_block_tail));
335 tail->t_checksum = 0;
336 csum = jbd2_chksum(j, j->j_csum_seed, jh2bh(descriptor)->b_data,
337 j->j_blocksize);
338 tail->t_checksum = cpu_to_be32(csum);
339}
340
341static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
342 struct buffer_head *bh, __u32 sequence)
343{
344 struct page *page = bh->b_page;
345 __u8 *addr;
346 __u32 csum;
347
348 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
349 return;
350
351 sequence = cpu_to_be32(sequence);
352 addr = kmap_atomic(page, KM_USER0);
353 csum = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&sequence,
354 sizeof(sequence));
355 csum = jbd2_chksum(j, csum, addr + offset_in_page(bh->b_data),
356 bh->b_size);
357 kunmap_atomic(addr, KM_USER0);
358
359 tag->t_checksum = cpu_to_be32(csum);
360}
304/* 361/*
305 * jbd2_journal_commit_transaction 362 * jbd2_journal_commit_transaction
306 * 363 *
@@ -334,6 +391,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
334 unsigned long first_block; 391 unsigned long first_block;
335 tid_t first_tid; 392 tid_t first_tid;
336 int update_tail; 393 int update_tail;
394 int csum_size = 0;
395
396 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
397 csum_size = sizeof(struct jbd2_journal_block_tail);
337 398
338 /* 399 /*
339 * First job: lock down the current transaction and wait for 400 * First job: lock down the current transaction and wait for
@@ -627,7 +688,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
627 688
628 tag = (journal_block_tag_t *) tagp; 689 tag = (journal_block_tag_t *) tagp;
629 write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr); 690 write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr);
630 tag->t_flags = cpu_to_be32(tag_flag); 691 tag->t_flags = cpu_to_be16(tag_flag);
692 jbd2_block_tag_csum_set(journal, tag, jh2bh(new_jh),
693 commit_transaction->t_tid);
631 tagp += tag_bytes; 694 tagp += tag_bytes;
632 space_left -= tag_bytes; 695 space_left -= tag_bytes;
633 696
@@ -643,7 +706,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
643 706
644 if (bufs == journal->j_wbufsize || 707 if (bufs == journal->j_wbufsize ||
645 commit_transaction->t_buffers == NULL || 708 commit_transaction->t_buffers == NULL ||
646 space_left < tag_bytes + 16) { 709 space_left < tag_bytes + 16 + csum_size) {
647 710
648 jbd_debug(4, "JBD2: Submit %d IOs\n", bufs); 711 jbd_debug(4, "JBD2: Submit %d IOs\n", bufs);
649 712
@@ -651,8 +714,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
651 submitting the IOs. "tag" still points to 714 submitting the IOs. "tag" still points to
652 the last tag we set up. */ 715 the last tag we set up. */
653 716
654 tag->t_flags |= cpu_to_be32(JBD2_FLAG_LAST_TAG); 717 tag->t_flags |= cpu_to_be16(JBD2_FLAG_LAST_TAG);
655 718
719 jbd2_descr_block_csum_set(journal, descriptor);
656start_journal_io: 720start_journal_io:
657 for (i = 0; i < bufs; i++) { 721 for (i = 0; i < bufs; i++) {
658 struct buffer_head *bh = wbuf[i]; 722 struct buffer_head *bh = wbuf[i];
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 1afb701622b0..e9a3c4c85594 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -97,6 +97,43 @@ EXPORT_SYMBOL(jbd2_inode_cache);
97static void __journal_abort_soft (journal_t *journal, int errno); 97static void __journal_abort_soft (journal_t *journal, int errno);
98static int jbd2_journal_create_slab(size_t slab_size); 98static int jbd2_journal_create_slab(size_t slab_size);
99 99
100/* Checksumming functions */
101int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
102{
103 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
104 return 1;
105
106 return sb->s_checksum_type == JBD2_CRC32C_CHKSUM;
107}
108
109static __u32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
110{
111 __u32 csum, old_csum;
112
113 old_csum = sb->s_checksum;
114 sb->s_checksum = 0;
115 csum = jbd2_chksum(j, ~0, (char *)sb, sizeof(journal_superblock_t));
116 sb->s_checksum = old_csum;
117
118 return cpu_to_be32(csum);
119}
120
121int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
122{
123 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
124 return 1;
125
126 return sb->s_checksum == jbd2_superblock_csum(j, sb);
127}
128
129void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
130{
131 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
132 return;
133
134 sb->s_checksum = jbd2_superblock_csum(j, sb);
135}
136
100/* 137/*
101 * Helper function used to manage commit timeouts 138 * Helper function used to manage commit timeouts
102 */ 139 */
@@ -1348,6 +1385,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)
1348 jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", 1385 jbd_debug(1, "JBD2: updating superblock error (errno %d)\n",
1349 journal->j_errno); 1386 journal->j_errno);
1350 sb->s_errno = cpu_to_be32(journal->j_errno); 1387 sb->s_errno = cpu_to_be32(journal->j_errno);
1388 jbd2_superblock_csum_set(journal, sb);
1351 read_unlock(&journal->j_state_lock); 1389 read_unlock(&journal->j_state_lock);
1352 1390
1353 jbd2_write_superblock(journal, WRITE_SYNC); 1391 jbd2_write_superblock(journal, WRITE_SYNC);
@@ -1376,6 +1414,9 @@ static int journal_get_superblock(journal_t *journal)
1376 } 1414 }
1377 } 1415 }
1378 1416
1417 if (buffer_verified(bh))
1418 return 0;
1419
1379 sb = journal->j_superblock; 1420 sb = journal->j_superblock;
1380 1421
1381 err = -EINVAL; 1422 err = -EINVAL;
@@ -1413,6 +1454,43 @@ static int journal_get_superblock(journal_t *journal)
1413 goto out; 1454 goto out;
1414 } 1455 }
1415 1456
1457 if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
1458 JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
1459 /* Can't have checksum v1 and v2 on at the same time! */
1460 printk(KERN_ERR "JBD: Can't enable checksumming v1 and v2 "
1461 "at the same time!\n");
1462 goto out;
1463 }
1464
1465 if (!jbd2_verify_csum_type(journal, sb)) {
1466 printk(KERN_ERR "JBD: Unknown checksum type\n");
1467 goto out;
1468 }
1469
1470 /* Load the checksum driver */
1471 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
1472 journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
1473 if (IS_ERR(journal->j_chksum_driver)) {
1474 printk(KERN_ERR "JBD: Cannot load crc32c driver.\n");
1475 err = PTR_ERR(journal->j_chksum_driver);
1476 journal->j_chksum_driver = NULL;
1477 goto out;
1478 }
1479 }
1480
1481 /* Check superblock checksum */
1482 if (!jbd2_superblock_csum_verify(journal, sb)) {
1483 printk(KERN_ERR "JBD: journal checksum error\n");
1484 goto out;
1485 }
1486
1487 /* Precompute checksum seed for all metadata */
1488 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
1489 journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
1490 sizeof(sb->s_uuid));
1491
1492 set_buffer_verified(bh);
1493
1416 return 0; 1494 return 0;
1417 1495
1418out: 1496out:
@@ -1564,6 +1642,8 @@ int jbd2_journal_destroy(journal_t *journal)
1564 iput(journal->j_inode); 1642 iput(journal->j_inode);
1565 if (journal->j_revoke) 1643 if (journal->j_revoke)
1566 jbd2_journal_destroy_revoke(journal); 1644 jbd2_journal_destroy_revoke(journal);
1645 if (journal->j_chksum_driver)
1646 crypto_free_shash(journal->j_chksum_driver);
1567 kfree(journal->j_wbuf); 1647 kfree(journal->j_wbuf);
1568 kfree(journal); 1648 kfree(journal);
1569 1649
@@ -1653,6 +1733,10 @@ int jbd2_journal_check_available_features (journal_t *journal, unsigned long com
1653int jbd2_journal_set_features (journal_t *journal, unsigned long compat, 1733int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
1654 unsigned long ro, unsigned long incompat) 1734 unsigned long ro, unsigned long incompat)
1655{ 1735{
1736#define INCOMPAT_FEATURE_ON(f) \
1737 ((incompat & (f)) && !(sb->s_feature_incompat & cpu_to_be32(f)))
1738#define COMPAT_FEATURE_ON(f) \
1739 ((compat & (f)) && !(sb->s_feature_compat & cpu_to_be32(f)))
1656 journal_superblock_t *sb; 1740 journal_superblock_t *sb;
1657 1741
1658 if (jbd2_journal_check_used_features(journal, compat, ro, incompat)) 1742 if (jbd2_journal_check_used_features(journal, compat, ro, incompat))
@@ -1661,16 +1745,54 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
1661 if (!jbd2_journal_check_available_features(journal, compat, ro, incompat)) 1745 if (!jbd2_journal_check_available_features(journal, compat, ro, incompat))
1662 return 0; 1746 return 0;
1663 1747
1748 /* Asking for checksumming v2 and v1? Only give them v2. */
1749 if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2 &&
1750 compat & JBD2_FEATURE_COMPAT_CHECKSUM)
1751 compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM;
1752
1664 jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n", 1753 jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n",
1665 compat, ro, incompat); 1754 compat, ro, incompat);
1666 1755
1667 sb = journal->j_superblock; 1756 sb = journal->j_superblock;
1668 1757
1758 /* If enabling v2 checksums, update superblock */
1759 if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
1760 sb->s_checksum_type = JBD2_CRC32C_CHKSUM;
1761 sb->s_feature_compat &=
1762 ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
1763
1764 /* Load the checksum driver */
1765 if (journal->j_chksum_driver == NULL) {
1766 journal->j_chksum_driver = crypto_alloc_shash("crc32c",
1767 0, 0);
1768 if (IS_ERR(journal->j_chksum_driver)) {
1769 printk(KERN_ERR "JBD: Cannot load crc32c "
1770 "driver.\n");
1771 journal->j_chksum_driver = NULL;
1772 return 0;
1773 }
1774 }
1775
1776 /* Precompute checksum seed for all metadata */
1777 if (JBD2_HAS_INCOMPAT_FEATURE(journal,
1778 JBD2_FEATURE_INCOMPAT_CSUM_V2))
1779 journal->j_csum_seed = jbd2_chksum(journal, ~0,
1780 sb->s_uuid,
1781 sizeof(sb->s_uuid));
1782 }
1783
1784 /* If enabling v1 checksums, downgrade superblock */
1785 if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM))
1786 sb->s_feature_incompat &=
1787 ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2);
1788
1669 sb->s_feature_compat |= cpu_to_be32(compat); 1789 sb->s_feature_compat |= cpu_to_be32(compat);
1670 sb->s_feature_ro_compat |= cpu_to_be32(ro); 1790 sb->s_feature_ro_compat |= cpu_to_be32(ro);
1671 sb->s_feature_incompat |= cpu_to_be32(incompat); 1791 sb->s_feature_incompat |= cpu_to_be32(incompat);
1672 1792
1673 return 1; 1793 return 1;
1794#undef COMPAT_FEATURE_ON
1795#undef INCOMPAT_FEATURE_ON
1674} 1796}
1675 1797
1676/* 1798/*
@@ -1975,10 +2097,16 @@ int jbd2_journal_blocks_per_page(struct inode *inode)
1975 */ 2097 */
1976size_t journal_tag_bytes(journal_t *journal) 2098size_t journal_tag_bytes(journal_t *journal)
1977{ 2099{
2100 journal_block_tag_t tag;
2101 size_t x = 0;
2102
2103 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
2104 x += sizeof(tag.t_checksum);
2105
1978 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) 2106 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
1979 return JBD2_TAG_SIZE64; 2107 return x + JBD2_TAG_SIZE64;
1980 else 2108 else
1981 return JBD2_TAG_SIZE32; 2109 return x + JBD2_TAG_SIZE32;
1982} 2110}
1983 2111
1984/* 2112/*
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index c1a03354a22f..0131e4362534 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -174,6 +174,25 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
174 return 0; 174 return 0;
175} 175}
176 176
177static int jbd2_descr_block_csum_verify(journal_t *j,
178 void *buf)
179{
180 struct jbd2_journal_block_tail *tail;
181 __u32 provided, calculated;
182
183 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
184 return 1;
185
186 tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize -
187 sizeof(struct jbd2_journal_block_tail));
188 provided = tail->t_checksum;
189 tail->t_checksum = 0;
190 calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
191 tail->t_checksum = provided;
192
193 provided = be32_to_cpu(provided);
194 return provided == calculated;
195}
177 196
178/* 197/*
179 * Count the number of in-use tags in a journal descriptor block. 198 * Count the number of in-use tags in a journal descriptor block.
@@ -186,6 +205,9 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
186 int nr = 0, size = journal->j_blocksize; 205 int nr = 0, size = journal->j_blocksize;
187 int tag_bytes = journal_tag_bytes(journal); 206 int tag_bytes = journal_tag_bytes(journal);
188 207
208 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
209 size -= sizeof(struct jbd2_journal_block_tail);
210
189 tagp = &bh->b_data[sizeof(journal_header_t)]; 211 tagp = &bh->b_data[sizeof(journal_header_t)];
190 212
191 while ((tagp - bh->b_data + tag_bytes) <= size) { 213 while ((tagp - bh->b_data + tag_bytes) <= size) {
@@ -193,10 +215,10 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
193 215
194 nr++; 216 nr++;
195 tagp += tag_bytes; 217 tagp += tag_bytes;
196 if (!(tag->t_flags & cpu_to_be32(JBD2_FLAG_SAME_UUID))) 218 if (!(tag->t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID)))
197 tagp += 16; 219 tagp += 16;
198 220
199 if (tag->t_flags & cpu_to_be32(JBD2_FLAG_LAST_TAG)) 221 if (tag->t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG))
200 break; 222 break;
201 } 223 }
202 224
@@ -353,6 +375,41 @@ static int calc_chksums(journal_t *journal, struct buffer_head *bh,
353 return 0; 375 return 0;
354} 376}
355 377
378static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
379{
380 struct commit_header *h;
381 __u32 provided, calculated;
382
383 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
384 return 1;
385
386 h = buf;
387 provided = h->h_chksum[0];
388 h->h_chksum[0] = 0;
389 calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
390 h->h_chksum[0] = provided;
391
392 provided = be32_to_cpu(provided);
393 return provided == calculated;
394}
395
396static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
397 void *buf, __u32 sequence)
398{
399 __u32 provided, calculated;
400
401 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
402 return 1;
403
404 sequence = cpu_to_be32(sequence);
405 calculated = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&sequence,
406 sizeof(sequence));
407 calculated = jbd2_chksum(j, calculated, buf, j->j_blocksize);
408 provided = be32_to_cpu(tag->t_checksum);
409
410 return provided == cpu_to_be32(calculated);
411}
412
356static int do_one_pass(journal_t *journal, 413static int do_one_pass(journal_t *journal,
357 struct recovery_info *info, enum passtype pass) 414 struct recovery_info *info, enum passtype pass)
358{ 415{
@@ -366,6 +423,7 @@ static int do_one_pass(journal_t *journal,
366 int blocktype; 423 int blocktype;
367 int tag_bytes = journal_tag_bytes(journal); 424 int tag_bytes = journal_tag_bytes(journal);
368 __u32 crc32_sum = ~0; /* Transactional Checksums */ 425 __u32 crc32_sum = ~0; /* Transactional Checksums */
426 int descr_csum_size = 0;
369 427
370 /* 428 /*
371 * First thing is to establish what we expect to find in the log 429 * First thing is to establish what we expect to find in the log
@@ -451,6 +509,18 @@ static int do_one_pass(journal_t *journal,
451 509
452 switch(blocktype) { 510 switch(blocktype) {
453 case JBD2_DESCRIPTOR_BLOCK: 511 case JBD2_DESCRIPTOR_BLOCK:
512 /* Verify checksum first */
513 if (JBD2_HAS_INCOMPAT_FEATURE(journal,
514 JBD2_FEATURE_INCOMPAT_CSUM_V2))
515 descr_csum_size =
516 sizeof(struct jbd2_journal_block_tail);
517 if (descr_csum_size > 0 &&
518 !jbd2_descr_block_csum_verify(journal,
519 bh->b_data)) {
520 err = -EIO;
521 goto failed;
522 }
523
454 /* If it is a valid descriptor block, replay it 524 /* If it is a valid descriptor block, replay it
455 * in pass REPLAY; if journal_checksums enabled, then 525 * in pass REPLAY; if journal_checksums enabled, then
456 * calculate checksums in PASS_SCAN, otherwise, 526 * calculate checksums in PASS_SCAN, otherwise,
@@ -481,11 +551,11 @@ static int do_one_pass(journal_t *journal,
481 551
482 tagp = &bh->b_data[sizeof(journal_header_t)]; 552 tagp = &bh->b_data[sizeof(journal_header_t)];
483 while ((tagp - bh->b_data + tag_bytes) 553 while ((tagp - bh->b_data + tag_bytes)
484 <= journal->j_blocksize) { 554 <= journal->j_blocksize - descr_csum_size) {
485 unsigned long io_block; 555 unsigned long io_block;
486 556
487 tag = (journal_block_tag_t *) tagp; 557 tag = (journal_block_tag_t *) tagp;
488 flags = be32_to_cpu(tag->t_flags); 558 flags = be16_to_cpu(tag->t_flags);
489 559
490 io_block = next_log_block++; 560 io_block = next_log_block++;
491 wrap(journal, next_log_block); 561 wrap(journal, next_log_block);
@@ -516,6 +586,19 @@ static int do_one_pass(journal_t *journal,
516 goto skip_write; 586 goto skip_write;
517 } 587 }
518 588
589 /* Look for block corruption */
590 if (!jbd2_block_tag_csum_verify(
591 journal, tag, obh->b_data,
592 be32_to_cpu(tmp->h_sequence))) {
593 brelse(obh);
594 success = -EIO;
595 printk(KERN_ERR "JBD: Invalid "
596 "checksum recovering "
597 "block %llu in log\n",
598 blocknr);
599 continue;
600 }
601
519 /* Find a buffer for the new 602 /* Find a buffer for the new
520 * data being restored */ 603 * data being restored */
521 nbh = __getblk(journal->j_fs_dev, 604 nbh = __getblk(journal->j_fs_dev,
@@ -650,6 +733,19 @@ static int do_one_pass(journal_t *journal,
650 } 733 }
651 crc32_sum = ~0; 734 crc32_sum = ~0;
652 } 735 }
736 if (pass == PASS_SCAN &&
737 !jbd2_commit_block_csum_verify(journal,
738 bh->b_data)) {
739 info->end_transaction = next_commit_ID;
740
741 if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
742 JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
743 journal->j_failed_commit =
744 next_commit_ID;
745 brelse(bh);
746 break;
747 }
748 }
653 brelse(bh); 749 brelse(bh);
654 next_commit_ID++; 750 next_commit_ID++;
655 continue; 751 continue;
@@ -706,6 +802,25 @@ static int do_one_pass(journal_t *journal,
706 return err; 802 return err;
707} 803}
708 804
805static int jbd2_revoke_block_csum_verify(journal_t *j,
806 void *buf)
807{
808 struct jbd2_journal_revoke_tail *tail;
809 __u32 provided, calculated;
810
811 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
812 return 1;
813
814 tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize -
815 sizeof(struct jbd2_journal_revoke_tail));
816 provided = tail->r_checksum;
817 tail->r_checksum = 0;
818 calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
819 tail->r_checksum = provided;
820
821 provided = be32_to_cpu(provided);
822 return provided == calculated;
823}
709 824
710/* Scan a revoke record, marking all blocks mentioned as revoked. */ 825/* Scan a revoke record, marking all blocks mentioned as revoked. */
711 826
@@ -720,6 +835,9 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
720 offset = sizeof(jbd2_journal_revoke_header_t); 835 offset = sizeof(jbd2_journal_revoke_header_t);
721 max = be32_to_cpu(header->r_count); 836 max = be32_to_cpu(header->r_count);
722 837
838 if (!jbd2_revoke_block_csum_verify(journal, header))
839 return -EINVAL;
840
723 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) 841 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
724 record_len = 8; 842 record_len = 8;
725 843
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 6973705d6a3d..f30b80b4ce8b 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -578,6 +578,7 @@ static void write_one_revoke_record(journal_t *journal,
578 struct jbd2_revoke_record_s *record, 578 struct jbd2_revoke_record_s *record,
579 int write_op) 579 int write_op)
580{ 580{
581 int csum_size = 0;
581 struct journal_head *descriptor; 582 struct journal_head *descriptor;
582 int offset; 583 int offset;
583 journal_header_t *header; 584 journal_header_t *header;
@@ -592,9 +593,13 @@ static void write_one_revoke_record(journal_t *journal,
592 descriptor = *descriptorp; 593 descriptor = *descriptorp;
593 offset = *offsetp; 594 offset = *offsetp;
594 595
596 /* Do we need to leave space at the end for a checksum? */
597 if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
598 csum_size = sizeof(struct jbd2_journal_revoke_tail);
599
595 /* Make sure we have a descriptor with space left for the record */ 600 /* Make sure we have a descriptor with space left for the record */
596 if (descriptor) { 601 if (descriptor) {
597 if (offset == journal->j_blocksize) { 602 if (offset >= journal->j_blocksize - csum_size) {
598 flush_descriptor(journal, descriptor, offset, write_op); 603 flush_descriptor(journal, descriptor, offset, write_op);
599 descriptor = NULL; 604 descriptor = NULL;
600 } 605 }
@@ -631,6 +636,24 @@ static void write_one_revoke_record(journal_t *journal,
631 *offsetp = offset; 636 *offsetp = offset;
632} 637}
633 638
639static void jbd2_revoke_csum_set(journal_t *j,
640 struct journal_head *descriptor)
641{
642 struct jbd2_journal_revoke_tail *tail;
643 __u32 csum;
644
645 if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
646 return;
647
648 tail = (struct jbd2_journal_revoke_tail *)
649 (jh2bh(descriptor)->b_data + j->j_blocksize -
650 sizeof(struct jbd2_journal_revoke_tail));
651 tail->r_checksum = 0;
652 csum = jbd2_chksum(j, j->j_csum_seed, jh2bh(descriptor)->b_data,
653 j->j_blocksize);
654 tail->r_checksum = cpu_to_be32(csum);
655}
656
634/* 657/*
635 * Flush a revoke descriptor out to the journal. If we are aborting, 658 * Flush a revoke descriptor out to the journal. If we are aborting,
636 * this is a noop; otherwise we are generating a buffer which needs to 659 * this is a noop; otherwise we are generating a buffer which needs to
@@ -652,6 +675,8 @@ static void flush_descriptor(journal_t *journal,
652 675
653 header = (jbd2_journal_revoke_header_t *) jh2bh(descriptor)->b_data; 676 header = (jbd2_journal_revoke_header_t *) jh2bh(descriptor)->b_data;
654 header->r_count = cpu_to_be32(offset); 677 header->r_count = cpu_to_be32(offset);
678 jbd2_revoke_csum_set(journal, descriptor);
679
655 set_buffer_jwrite(bh); 680 set_buffer_jwrite(bh);
656 BUFFER_TRACE(bh, "write"); 681 BUFFER_TRACE(bh, "write");
657 set_buffer_dirty(bh); 682 set_buffer_dirty(bh);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index ddcd3549c6c2..fb1ab9533b67 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -162,8 +162,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
162 162
163alloc_transaction: 163alloc_transaction:
164 if (!journal->j_running_transaction) { 164 if (!journal->j_running_transaction) {
165 new_transaction = kmem_cache_alloc(transaction_cache, 165 new_transaction = kmem_cache_zalloc(transaction_cache,
166 gfp_mask | __GFP_ZERO); 166 gfp_mask);
167 if (!new_transaction) { 167 if (!new_transaction) {
168 /* 168 /*
169 * If __GFP_FS is not present, then we may be 169 * If __GFP_FS is not present, then we may be