diff options
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]; |
