aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2014-08-27 18:40:07 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-08-28 22:22:29 -0400
commitdb9ee220361de03ee86388f9ea5e529eaad5323c (patch)
tree1f5047f2f588e814901be723a989adde97ae5093 /include
parent022eaa7517017efe4f6538750c2b59a804dc7df7 (diff)
jbd2: fix descriptor block size handling errors with journal_csum
It turns out that there are some serious problems with the on-disk format of journal checksum v2. The foremost is that the function to calculate descriptor tag size returns sizes that are too big. This causes alignment issues on some architectures and is compounded by the fact that some parts of jbd2 use the structure size (incorrectly) to determine the presence of a 64bit journal instead of checking the feature flags. Therefore, introduce journal checksum v3, which enlarges the descriptor block tag format to allow for full 32-bit checksums of journal blocks, fix the journal tag function to return the correct sizes, and fix the jbd2 recovery code to use feature flags to determine 64bitness. Add a few function helpers so we don't have to open-code quite so many pieces. Switching to a 16-byte block size was found to increase journal size overhead by a maximum of 0.1%, to convert a 32-bit journal with no checksumming to a 32-bit journal with checksum v3 enabled. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reported-by: TR Reardon <thomas_reardon@hotmail.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@vger.kernel.org
Diffstat (limited to 'include')
-rw-r--r--include/linux/jbd2.h30
1 files changed, 25 insertions, 5 deletions
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 */
164struct commit_header { 168struct 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 */
186typedef 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
182typedef struct journal_block_tag_s 194typedef 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 */
194struct jbd2_journal_block_tail { 203struct 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)
1296extern int jbd2_journal_blocks_per_page(struct inode *inode); 1307extern int jbd2_journal_blocks_per_page(struct inode *inode);
1297extern size_t journal_tag_bytes(journal_t *journal); 1308extern size_t journal_tag_bytes(journal_t *journal);
1298 1309
1310static 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.