diff options
-rw-r--r-- | fs/ext4/super.c | 5 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 21 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 56 | ||||
-rw-r--r-- | fs/jbd2/recovery.c | 26 | ||||
-rw-r--r-- | fs/jbd2/revoke.c | 6 | ||||
-rw-r--r-- | include/linux/jbd2.h | 30 |
6 files changed, 95 insertions, 49 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 32b43ad154b9..0b28b36e7915 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -3181,9 +3181,9 @@ static int set_journal_csum_feature_set(struct super_block *sb) | |||
3181 | 3181 | ||
3182 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 3182 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, |
3183 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { | 3183 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { |
3184 | /* journal checksum v2 */ | 3184 | /* journal checksum v3 */ |
3185 | compat = 0; | 3185 | compat = 0; |
3186 | incompat = JBD2_FEATURE_INCOMPAT_CSUM_V2; | 3186 | incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3; |
3187 | } else { | 3187 | } else { |
3188 | /* journal checksum v1 */ | 3188 | /* journal checksum v1 */ |
3189 | compat = JBD2_FEATURE_COMPAT_CHECKSUM; | 3189 | compat = JBD2_FEATURE_COMPAT_CHECKSUM; |
@@ -3205,6 +3205,7 @@ static int set_journal_csum_feature_set(struct super_block *sb) | |||
3205 | jbd2_journal_clear_features(sbi->s_journal, | 3205 | jbd2_journal_clear_features(sbi->s_journal, |
3206 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | 3206 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, |
3207 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | | 3207 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | |
3208 | JBD2_FEATURE_INCOMPAT_CSUM_V3 | | ||
3208 | JBD2_FEATURE_INCOMPAT_CSUM_V2); | 3209 | JBD2_FEATURE_INCOMPAT_CSUM_V2); |
3209 | } | 3210 | } |
3210 | 3211 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 6fac74349856..b73e0215baa7 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -97,7 +97,7 @@ static void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh) | |||
97 | struct commit_header *h; | 97 | struct commit_header *h; |
98 | __u32 csum; | 98 | __u32 csum; |
99 | 99 | ||
100 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 100 | if (!jbd2_journal_has_csum_v2or3(j)) |
101 | return; | 101 | return; |
102 | 102 | ||
103 | h = (struct commit_header *)(bh->b_data); | 103 | h = (struct commit_header *)(bh->b_data); |
@@ -313,11 +313,11 @@ static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh) | |||
313 | return checksum; | 313 | return checksum; |
314 | } | 314 | } |
315 | 315 | ||
316 | static void write_tag_block(int tag_bytes, journal_block_tag_t *tag, | 316 | static void write_tag_block(journal_t *j, journal_block_tag_t *tag, |
317 | unsigned long long block) | 317 | unsigned long long block) |
318 | { | 318 | { |
319 | tag->t_blocknr = cpu_to_be32(block & (u32)~0); | 319 | tag->t_blocknr = cpu_to_be32(block & (u32)~0); |
320 | if (tag_bytes > JBD2_TAG_SIZE32) | 320 | if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_64BIT)) |
321 | tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); | 321 | tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1); |
322 | } | 322 | } |
323 | 323 | ||
@@ -327,7 +327,7 @@ static void jbd2_descr_block_csum_set(journal_t *j, | |||
327 | struct jbd2_journal_block_tail *tail; | 327 | struct jbd2_journal_block_tail *tail; |
328 | __u32 csum; | 328 | __u32 csum; |
329 | 329 | ||
330 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 330 | if (!jbd2_journal_has_csum_v2or3(j)) |
331 | return; | 331 | return; |
332 | 332 | ||
333 | tail = (struct jbd2_journal_block_tail *)(bh->b_data + j->j_blocksize - | 333 | tail = (struct jbd2_journal_block_tail *)(bh->b_data + j->j_blocksize - |
@@ -340,12 +340,13 @@ static void jbd2_descr_block_csum_set(journal_t *j, | |||
340 | static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, | 340 | static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, |
341 | struct buffer_head *bh, __u32 sequence) | 341 | struct buffer_head *bh, __u32 sequence) |
342 | { | 342 | { |
343 | journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; | ||
343 | struct page *page = bh->b_page; | 344 | struct page *page = bh->b_page; |
344 | __u8 *addr; | 345 | __u8 *addr; |
345 | __u32 csum32; | 346 | __u32 csum32; |
346 | __be32 seq; | 347 | __be32 seq; |
347 | 348 | ||
348 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 349 | if (!jbd2_journal_has_csum_v2or3(j)) |
349 | return; | 350 | return; |
350 | 351 | ||
351 | seq = cpu_to_be32(sequence); | 352 | seq = cpu_to_be32(sequence); |
@@ -355,8 +356,10 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, | |||
355 | bh->b_size); | 356 | bh->b_size); |
356 | kunmap_atomic(addr); | 357 | kunmap_atomic(addr); |
357 | 358 | ||
358 | /* We only have space to store the lower 16 bits of the crc32c. */ | 359 | if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) |
359 | tag->t_checksum = cpu_to_be16(csum32); | 360 | tag3->t_checksum = cpu_to_be32(csum32); |
361 | else | ||
362 | tag->t_checksum = cpu_to_be16(csum32); | ||
360 | } | 363 | } |
361 | /* | 364 | /* |
362 | * jbd2_journal_commit_transaction | 365 | * jbd2_journal_commit_transaction |
@@ -396,7 +399,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
396 | LIST_HEAD(io_bufs); | 399 | LIST_HEAD(io_bufs); |
397 | LIST_HEAD(log_bufs); | 400 | LIST_HEAD(log_bufs); |
398 | 401 | ||
399 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 402 | if (jbd2_journal_has_csum_v2or3(journal)) |
400 | csum_size = sizeof(struct jbd2_journal_block_tail); | 403 | csum_size = sizeof(struct jbd2_journal_block_tail); |
401 | 404 | ||
402 | /* | 405 | /* |
@@ -690,7 +693,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
690 | tag_flag |= JBD2_FLAG_SAME_UUID; | 693 | tag_flag |= JBD2_FLAG_SAME_UUID; |
691 | 694 | ||
692 | tag = (journal_block_tag_t *) tagp; | 695 | tag = (journal_block_tag_t *) tagp; |
693 | write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr); | 696 | write_tag_block(journal, tag, jh2bh(jh)->b_blocknr); |
694 | tag->t_flags = cpu_to_be16(tag_flag); | 697 | tag->t_flags = cpu_to_be16(tag_flag); |
695 | jbd2_block_tag_csum_set(journal, tag, wbuf[bufs], | 698 | jbd2_block_tag_csum_set(journal, tag, wbuf[bufs], |
696 | commit_transaction->t_tid); | 699 | commit_transaction->t_tid); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 67b8e303946c..19d74d86d99c 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -124,7 +124,7 @@ EXPORT_SYMBOL(__jbd2_debug); | |||
124 | /* Checksumming functions */ | 124 | /* Checksumming functions */ |
125 | static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) | 125 | static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb) |
126 | { | 126 | { |
127 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 127 | if (!jbd2_journal_has_csum_v2or3(j)) |
128 | return 1; | 128 | return 1; |
129 | 129 | ||
130 | return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; | 130 | return sb->s_checksum_type == JBD2_CRC32C_CHKSUM; |
@@ -145,7 +145,7 @@ static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb) | |||
145 | 145 | ||
146 | static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) | 146 | static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) |
147 | { | 147 | { |
148 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 148 | if (!jbd2_journal_has_csum_v2or3(j)) |
149 | return 1; | 149 | return 1; |
150 | 150 | ||
151 | return sb->s_checksum == jbd2_superblock_csum(j, sb); | 151 | return sb->s_checksum == jbd2_superblock_csum(j, sb); |
@@ -153,7 +153,7 @@ static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb) | |||
153 | 153 | ||
154 | static void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb) | 154 | static void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb) |
155 | { | 155 | { |
156 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 156 | if (!jbd2_journal_has_csum_v2or3(j)) |
157 | return; | 157 | return; |
158 | 158 | ||
159 | sb->s_checksum = jbd2_superblock_csum(j, sb); | 159 | sb->s_checksum = jbd2_superblock_csum(j, sb); |
@@ -1522,21 +1522,29 @@ static int journal_get_superblock(journal_t *journal) | |||
1522 | goto out; | 1522 | goto out; |
1523 | } | 1523 | } |
1524 | 1524 | ||
1525 | if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) && | 1525 | if (jbd2_journal_has_csum_v2or3(journal) && |
1526 | JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { | 1526 | JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) { |
1527 | /* Can't have checksum v1 and v2 on at the same time! */ | 1527 | /* Can't have checksum v1 and v2 on at the same time! */ |
1528 | printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 " | 1528 | printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 " |
1529 | "at the same time!\n"); | 1529 | "at the same time!\n"); |
1530 | goto out; | 1530 | goto out; |
1531 | } | 1531 | } |
1532 | 1532 | ||
1533 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) && | ||
1534 | JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) { | ||
1535 | /* Can't have checksum v2 and v3 at the same time! */ | ||
1536 | printk(KERN_ERR "JBD2: Can't enable checksumming v2 and v3 " | ||
1537 | "at the same time!\n"); | ||
1538 | goto out; | ||
1539 | } | ||
1540 | |||
1533 | if (!jbd2_verify_csum_type(journal, sb)) { | 1541 | if (!jbd2_verify_csum_type(journal, sb)) { |
1534 | printk(KERN_ERR "JBD2: Unknown checksum type\n"); | 1542 | printk(KERN_ERR "JBD2: Unknown checksum type\n"); |
1535 | goto out; | 1543 | goto out; |
1536 | } | 1544 | } |
1537 | 1545 | ||
1538 | /* Load the checksum driver */ | 1546 | /* Load the checksum driver */ |
1539 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) { | 1547 | if (jbd2_journal_has_csum_v2or3(journal)) { |
1540 | journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); | 1548 | journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); |
1541 | if (IS_ERR(journal->j_chksum_driver)) { | 1549 | if (IS_ERR(journal->j_chksum_driver)) { |
1542 | printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n"); | 1550 | printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n"); |
@@ -1553,7 +1561,7 @@ static int journal_get_superblock(journal_t *journal) | |||
1553 | } | 1561 | } |
1554 | 1562 | ||
1555 | /* Precompute checksum seed for all metadata */ | 1563 | /* Precompute checksum seed for all metadata */ |
1556 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 1564 | if (jbd2_journal_has_csum_v2or3(journal)) |
1557 | journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid, | 1565 | journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid, |
1558 | sizeof(sb->s_uuid)); | 1566 | sizeof(sb->s_uuid)); |
1559 | 1567 | ||
@@ -1813,8 +1821,14 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
1813 | if (!jbd2_journal_check_available_features(journal, compat, ro, incompat)) | 1821 | if (!jbd2_journal_check_available_features(journal, compat, ro, incompat)) |
1814 | return 0; | 1822 | return 0; |
1815 | 1823 | ||
1816 | /* Asking for checksumming v2 and v1? Only give them v2. */ | 1824 | /* If enabling v2 checksums, turn on v3 instead */ |
1817 | if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2 && | 1825 | if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2) { |
1826 | incompat &= ~JBD2_FEATURE_INCOMPAT_CSUM_V2; | ||
1827 | incompat |= JBD2_FEATURE_INCOMPAT_CSUM_V3; | ||
1828 | } | ||
1829 | |||
1830 | /* Asking for checksumming v3 and v1? Only give them v3. */ | ||
1831 | if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V3 && | ||
1818 | compat & JBD2_FEATURE_COMPAT_CHECKSUM) | 1832 | compat & JBD2_FEATURE_COMPAT_CHECKSUM) |
1819 | compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM; | 1833 | compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM; |
1820 | 1834 | ||
@@ -1823,8 +1837,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
1823 | 1837 | ||
1824 | sb = journal->j_superblock; | 1838 | sb = journal->j_superblock; |
1825 | 1839 | ||
1826 | /* If enabling v2 checksums, update superblock */ | 1840 | /* If enabling v3 checksums, update superblock */ |
1827 | if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) { | 1841 | if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) { |
1828 | sb->s_checksum_type = JBD2_CRC32C_CHKSUM; | 1842 | sb->s_checksum_type = JBD2_CRC32C_CHKSUM; |
1829 | sb->s_feature_compat &= | 1843 | sb->s_feature_compat &= |
1830 | ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); | 1844 | ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); |
@@ -1842,8 +1856,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
1842 | } | 1856 | } |
1843 | 1857 | ||
1844 | /* Precompute checksum seed for all metadata */ | 1858 | /* Precompute checksum seed for all metadata */ |
1845 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 1859 | if (jbd2_journal_has_csum_v2or3(journal)) |
1846 | JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
1847 | journal->j_csum_seed = jbd2_chksum(journal, ~0, | 1860 | journal->j_csum_seed = jbd2_chksum(journal, ~0, |
1848 | sb->s_uuid, | 1861 | sb->s_uuid, |
1849 | sizeof(sb->s_uuid)); | 1862 | sizeof(sb->s_uuid)); |
@@ -1852,7 +1865,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
1852 | /* If enabling v1 checksums, downgrade superblock */ | 1865 | /* If enabling v1 checksums, downgrade superblock */ |
1853 | if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM)) | 1866 | if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM)) |
1854 | sb->s_feature_incompat &= | 1867 | sb->s_feature_incompat &= |
1855 | ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2); | 1868 | ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2 | |
1869 | JBD2_FEATURE_INCOMPAT_CSUM_V3); | ||
1856 | 1870 | ||
1857 | sb->s_feature_compat |= cpu_to_be32(compat); | 1871 | sb->s_feature_compat |= cpu_to_be32(compat); |
1858 | sb->s_feature_ro_compat |= cpu_to_be32(ro); | 1872 | sb->s_feature_ro_compat |= cpu_to_be32(ro); |
@@ -2165,16 +2179,20 @@ int jbd2_journal_blocks_per_page(struct inode *inode) | |||
2165 | */ | 2179 | */ |
2166 | size_t journal_tag_bytes(journal_t *journal) | 2180 | size_t journal_tag_bytes(journal_t *journal) |
2167 | { | 2181 | { |
2168 | journal_block_tag_t tag; | 2182 | size_t sz; |
2169 | size_t x = 0; | 2183 | |
2184 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) | ||
2185 | return sizeof(journal_block_tag3_t); | ||
2186 | |||
2187 | sz = sizeof(journal_block_tag_t); | ||
2170 | 2188 | ||
2171 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 2189 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) |
2172 | x += sizeof(tag.t_checksum); | 2190 | sz += sizeof(__u16); |
2173 | 2191 | ||
2174 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) | 2192 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) |
2175 | return x + JBD2_TAG_SIZE64; | 2193 | return sz; |
2176 | else | 2194 | else |
2177 | return x + JBD2_TAG_SIZE32; | 2195 | return sz - sizeof(__u32); |
2178 | } | 2196 | } |
2179 | 2197 | ||
2180 | /* | 2198 | /* |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 00e9703d7dc6..9b329b55ffe3 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
@@ -181,7 +181,7 @@ static int jbd2_descr_block_csum_verify(journal_t *j, | |||
181 | __be32 provided; | 181 | __be32 provided; |
182 | __u32 calculated; | 182 | __u32 calculated; |
183 | 183 | ||
184 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 184 | if (!jbd2_journal_has_csum_v2or3(j)) |
185 | return 1; | 185 | return 1; |
186 | 186 | ||
187 | tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize - | 187 | tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize - |
@@ -205,7 +205,7 @@ static int count_tags(journal_t *journal, struct buffer_head *bh) | |||
205 | int nr = 0, size = journal->j_blocksize; | 205 | int nr = 0, size = journal->j_blocksize; |
206 | int tag_bytes = journal_tag_bytes(journal); | 206 | int tag_bytes = journal_tag_bytes(journal); |
207 | 207 | ||
208 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 208 | if (jbd2_journal_has_csum_v2or3(journal)) |
209 | size -= sizeof(struct jbd2_journal_block_tail); | 209 | size -= sizeof(struct jbd2_journal_block_tail); |
210 | 210 | ||
211 | tagp = &bh->b_data[sizeof(journal_header_t)]; | 211 | tagp = &bh->b_data[sizeof(journal_header_t)]; |
@@ -338,10 +338,11 @@ int jbd2_journal_skip_recovery(journal_t *journal) | |||
338 | return err; | 338 | return err; |
339 | } | 339 | } |
340 | 340 | ||
341 | static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag) | 341 | static inline unsigned long long read_tag_block(journal_t *journal, |
342 | journal_block_tag_t *tag) | ||
342 | { | 343 | { |
343 | unsigned long long block = be32_to_cpu(tag->t_blocknr); | 344 | unsigned long long block = be32_to_cpu(tag->t_blocknr); |
344 | if (tag_bytes > JBD2_TAG_SIZE32) | 345 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) |
345 | block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32; | 346 | block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32; |
346 | return block; | 347 | return block; |
347 | } | 348 | } |
@@ -384,7 +385,7 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) | |||
384 | __be32 provided; | 385 | __be32 provided; |
385 | __u32 calculated; | 386 | __u32 calculated; |
386 | 387 | ||
387 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 388 | if (!jbd2_journal_has_csum_v2or3(j)) |
388 | return 1; | 389 | return 1; |
389 | 390 | ||
390 | h = buf; | 391 | h = buf; |
@@ -399,17 +400,21 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf) | |||
399 | static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, | 400 | static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, |
400 | void *buf, __u32 sequence) | 401 | void *buf, __u32 sequence) |
401 | { | 402 | { |
403 | journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; | ||
402 | __u32 csum32; | 404 | __u32 csum32; |
403 | __be32 seq; | 405 | __be32 seq; |
404 | 406 | ||
405 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 407 | if (!jbd2_journal_has_csum_v2or3(j)) |
406 | return 1; | 408 | return 1; |
407 | 409 | ||
408 | seq = cpu_to_be32(sequence); | 410 | seq = cpu_to_be32(sequence); |
409 | csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); | 411 | csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); |
410 | csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize); | 412 | csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize); |
411 | 413 | ||
412 | return tag->t_checksum == cpu_to_be16(csum32); | 414 | if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3)) |
415 | return tag3->t_checksum == cpu_to_be32(csum32); | ||
416 | else | ||
417 | return tag->t_checksum == cpu_to_be16(csum32); | ||
413 | } | 418 | } |
414 | 419 | ||
415 | static int do_one_pass(journal_t *journal, | 420 | static int do_one_pass(journal_t *journal, |
@@ -513,8 +518,7 @@ static int do_one_pass(journal_t *journal, | |||
513 | switch(blocktype) { | 518 | switch(blocktype) { |
514 | case JBD2_DESCRIPTOR_BLOCK: | 519 | case JBD2_DESCRIPTOR_BLOCK: |
515 | /* Verify checksum first */ | 520 | /* Verify checksum first */ |
516 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 521 | if (jbd2_journal_has_csum_v2or3(journal)) |
517 | JBD2_FEATURE_INCOMPAT_CSUM_V2)) | ||
518 | descr_csum_size = | 522 | descr_csum_size = |
519 | sizeof(struct jbd2_journal_block_tail); | 523 | sizeof(struct jbd2_journal_block_tail); |
520 | if (descr_csum_size > 0 && | 524 | if (descr_csum_size > 0 && |
@@ -575,7 +579,7 @@ static int do_one_pass(journal_t *journal, | |||
575 | unsigned long long blocknr; | 579 | unsigned long long blocknr; |
576 | 580 | ||
577 | J_ASSERT(obh != NULL); | 581 | J_ASSERT(obh != NULL); |
578 | blocknr = read_tag_block(tag_bytes, | 582 | blocknr = read_tag_block(journal, |
579 | tag); | 583 | tag); |
580 | 584 | ||
581 | /* If the block has been | 585 | /* If the block has been |
@@ -814,7 +818,7 @@ static int jbd2_revoke_block_csum_verify(journal_t *j, | |||
814 | __be32 provided; | 818 | __be32 provided; |
815 | __u32 calculated; | 819 | __u32 calculated; |
816 | 820 | ||
817 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 821 | if (!jbd2_journal_has_csum_v2or3(j)) |
818 | return 1; | 822 | return 1; |
819 | 823 | ||
820 | tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize - | 824 | tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize - |
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 198c9c10276d..d5e95a175c92 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
@@ -91,8 +91,8 @@ | |||
91 | #include <linux/list.h> | 91 | #include <linux/list.h> |
92 | #include <linux/init.h> | 92 | #include <linux/init.h> |
93 | #include <linux/bio.h> | 93 | #include <linux/bio.h> |
94 | #endif | ||
95 | #include <linux/log2.h> | 94 | #include <linux/log2.h> |
95 | #endif | ||
96 | 96 | ||
97 | static struct kmem_cache *jbd2_revoke_record_cache; | 97 | static struct kmem_cache *jbd2_revoke_record_cache; |
98 | static struct kmem_cache *jbd2_revoke_table_cache; | 98 | static struct kmem_cache *jbd2_revoke_table_cache; |
@@ -597,7 +597,7 @@ static void write_one_revoke_record(journal_t *journal, | |||
597 | offset = *offsetp; | 597 | offset = *offsetp; |
598 | 598 | ||
599 | /* Do we need to leave space at the end for a checksum? */ | 599 | /* Do we need to leave space at the end for a checksum? */ |
600 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 600 | if (jbd2_journal_has_csum_v2or3(journal)) |
601 | csum_size = sizeof(struct jbd2_journal_revoke_tail); | 601 | csum_size = sizeof(struct jbd2_journal_revoke_tail); |
602 | 602 | ||
603 | /* Make sure we have a descriptor with space left for the record */ | 603 | /* Make sure we have a descriptor with space left for the record */ |
@@ -644,7 +644,7 @@ static void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh) | |||
644 | struct jbd2_journal_revoke_tail *tail; | 644 | struct jbd2_journal_revoke_tail *tail; |
645 | __u32 csum; | 645 | __u32 csum; |
646 | 646 | ||
647 | if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2)) | 647 | if (!jbd2_journal_has_csum_v2or3(j)) |
648 | return; | 648 | return; |
649 | 649 | ||
650 | tail = (struct jbd2_journal_revoke_tail *)(bh->b_data + j->j_blocksize - | 650 | tail = (struct jbd2_journal_revoke_tail *)(bh->b_data + j->j_blocksize - |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index d5b50a19463c..0dae71e9971c 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -159,7 +159,11 @@ typedef struct journal_header_s | |||
159 | * journal_block_tag (in the descriptor). The other h_chksum* fields are | 159 | * journal_block_tag (in the descriptor). The other h_chksum* fields are |
160 | * not used. | 160 | * not used. |
161 | * | 161 | * |
162 | * Checksum v1 and v2 are mutually exclusive features. | 162 | * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses |
163 | * journal_block_tag3_t to store a full 32-bit checksum. Everything else | ||
164 | * is the same as v2. | ||
165 | * | ||
166 | * Checksum v1, v2, and v3 are mutually exclusive features. | ||
163 | */ | 167 | */ |
164 | struct commit_header { | 168 | struct commit_header { |
165 | __be32 h_magic; | 169 | __be32 h_magic; |
@@ -179,6 +183,14 @@ struct commit_header { | |||
179 | * raw struct shouldn't be used for pointer math or sizeof() - use | 183 | * raw struct shouldn't be used for pointer math or sizeof() - use |
180 | * journal_tag_bytes(journal) instead to compute this. | 184 | * journal_tag_bytes(journal) instead to compute this. |
181 | */ | 185 | */ |
186 | typedef struct journal_block_tag3_s | ||
187 | { | ||
188 | __be32 t_blocknr; /* The on-disk block number */ | ||
189 | __be32 t_flags; /* See below */ | ||
190 | __be32 t_blocknr_high; /* most-significant high 32bits. */ | ||
191 | __be32 t_checksum; /* crc32c(uuid+seq+block) */ | ||
192 | } journal_block_tag3_t; | ||
193 | |||
182 | typedef struct journal_block_tag_s | 194 | typedef struct journal_block_tag_s |
183 | { | 195 | { |
184 | __be32 t_blocknr; /* The on-disk block number */ | 196 | __be32 t_blocknr; /* The on-disk block number */ |
@@ -187,9 +199,6 @@ typedef struct journal_block_tag_s | |||
187 | __be32 t_blocknr_high; /* most-significant high 32bits. */ | 199 | __be32 t_blocknr_high; /* most-significant high 32bits. */ |
188 | } journal_block_tag_t; | 200 | } journal_block_tag_t; |
189 | 201 | ||
190 | #define JBD2_TAG_SIZE32 (offsetof(journal_block_tag_t, t_blocknr_high)) | ||
191 | #define JBD2_TAG_SIZE64 (sizeof(journal_block_tag_t)) | ||
192 | |||
193 | /* Tail of descriptor block, for checksumming */ | 202 | /* Tail of descriptor block, for checksumming */ |
194 | struct jbd2_journal_block_tail { | 203 | struct jbd2_journal_block_tail { |
195 | __be32 t_checksum; /* crc32c(uuid+descr_block) */ | 204 | __be32 t_checksum; /* crc32c(uuid+descr_block) */ |
@@ -284,6 +293,7 @@ typedef struct journal_superblock_s | |||
284 | #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 | 293 | #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 |
285 | #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 | 294 | #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 |
286 | #define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 | 295 | #define JBD2_FEATURE_INCOMPAT_CSUM_V2 0x00000008 |
296 | #define JBD2_FEATURE_INCOMPAT_CSUM_V3 0x00000010 | ||
287 | 297 | ||
288 | /* Features known to this kernel version: */ | 298 | /* Features known to this kernel version: */ |
289 | #define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM | 299 | #define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM |
@@ -291,7 +301,8 @@ typedef struct journal_superblock_s | |||
291 | #define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \ | 301 | #define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \ |
292 | JBD2_FEATURE_INCOMPAT_64BIT | \ | 302 | JBD2_FEATURE_INCOMPAT_64BIT | \ |
293 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | \ | 303 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | \ |
294 | JBD2_FEATURE_INCOMPAT_CSUM_V2) | 304 | JBD2_FEATURE_INCOMPAT_CSUM_V2 | \ |
305 | JBD2_FEATURE_INCOMPAT_CSUM_V3) | ||
295 | 306 | ||
296 | #ifdef __KERNEL__ | 307 | #ifdef __KERNEL__ |
297 | 308 | ||
@@ -1296,6 +1307,15 @@ static inline int tid_geq(tid_t x, tid_t y) | |||
1296 | extern int jbd2_journal_blocks_per_page(struct inode *inode); | 1307 | extern int jbd2_journal_blocks_per_page(struct inode *inode); |
1297 | extern size_t journal_tag_bytes(journal_t *journal); | 1308 | extern size_t journal_tag_bytes(journal_t *journal); |
1298 | 1309 | ||
1310 | static inline int jbd2_journal_has_csum_v2or3(journal_t *journal) | ||
1311 | { | ||
1312 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) || | ||
1313 | JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) | ||
1314 | return 1; | ||
1315 | |||
1316 | return 0; | ||
1317 | } | ||
1318 | |||
1299 | /* | 1319 | /* |
1300 | * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for | 1320 | * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for |
1301 | * transaction control blocks. | 1321 | * transaction control blocks. |