diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 13:12:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-01 13:12:15 -0400 |
commit | 4edebed86690eb8db9af3ab85baf4a34e73266cc (patch) | |
tree | 8ab144b08f490f239fa62be52470860c9311664d /fs/jbd2/commit.c | |
parent | 51eab603f5c86dd1eae4c525df3e7f7eeab401d6 (diff) | |
parent | 5e44f8c374dc4f8eadf61cd18b2c0d46bc87c1b7 (diff) |
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull Ext4 updates from Theodore Ts'o:
"The major new feature added in this update is Darrick J Wong's
metadata checksum feature, which adds crc32 checksums to ext4's
metadata fields.
There is also the usual set of cleanups and bug fixes."
* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (44 commits)
ext4: hole-punch use truncate_pagecache_range
jbd2: use kmem_cache_zalloc wrapper instead of flag
ext4: remove mb_groups before tearing down the buddy_cache
ext4: add ext4_mb_unload_buddy in the error path
ext4: don't trash state flags in EXT4_IOC_SETFLAGS
ext4: let getattr report the right blocks in delalloc+bigalloc
ext4: add missing save_error_info() to ext4_error()
ext4: add debugging trigger for ext4_error()
ext4: protect group inode free counting with group lock
ext4: use consistent ssize_t type in ext4_file_write()
ext4: fix format flag in ext4_ext_binsearch_idx()
ext4: cleanup in ext4_discard_allocated_blocks()
ext4: return ENOMEM when mounts fail due to lack of memory
ext4: remove redundundant "(char *) bh->b_data" casts
ext4: disallow hard-linked directory in ext4_lookup
ext4: fix potential integer overflow in alloc_flex_gd()
ext4: remove needs_recovery in ext4_mb_init()
ext4: force ro mount if ext4_setup_super() fails
ext4: fix potential NULL dereference in ext4_free_inodes_counts()
ext4/jbd2: add metadata checksumming to the list of supported features
...
Diffstat (limited to 'fs/jbd2/commit.c')
-rw-r--r-- | fs/jbd2/commit.c | 70 |
1 files changed, 67 insertions, 3 deletions
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 | ||
88 | static 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 | ||
323 | static 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 | |||
341 | static 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); | ||
656 | start_journal_io: | 720 | start_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]; |