/* * calc_chksums calculates the checksums for the blocks described in the * descriptor block. */ static int calc_chksums(journal_t *journal, struct buffer_head *bh, unsigned long long *next_log_block, __u32 *crc32_sum) { int i, num_blks, err; unsigned long long io_block; struct buffer_head *obh; num_blks = count_tags(journal, bh); /* Calculate checksum of the descriptor block. */ *crc32_sum = ext2fs_crc32_be(*crc32_sum, (void *)bh->b_data, bh->b_size); for (i = 0; i < num_blks; i++) { io_block = (*next_log_block)++; wrap(journal, *next_log_block); err = jread(&obh, journal, io_block); if (err) { printk(KERN_ERR "JBD: IO error %d recovering block " "%llu in log\n", err, io_block); return 1; } else { *crc32_sum = ext2fs_crc32_be(*crc32_sum, (void *)obh->b_data, obh->b_size); } brelse(obh); } return 0; }
static errcode_t journal_commit_trans(journal_transaction_t *trans) { struct buffer_head *bh, *cbh = NULL; struct commit_header *commit; #ifdef HAVE_SYS_TIME_H struct timeval tv; #endif errcode_t err; JOURNAL_CHECK_TRANS_MAGIC(trans); if ((trans->flags & J_TRANS_COMMITTED) || !(trans->flags & J_TRANS_OPEN)) return EXT2_ET_INVALID_ARGUMENT; bh = getblk(trans->journal->j_dev, 0, trans->journal->j_blocksize); if (bh == NULL) return ENOMEM; /* write the descriptor block header */ commit = (struct commit_header *)bh->b_data; commit->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER); commit->h_blocktype = ext2fs_cpu_to_be32(JFS_COMMIT_BLOCK); commit->h_sequence = ext2fs_cpu_to_be32(trans->tid); if (JFS_HAS_COMPAT_FEATURE(trans->journal, JFS_FEATURE_COMPAT_CHECKSUM)) { __u32 csum_v1 = ~0; blk64_t cblk; cbh = getblk(trans->journal->j_dev, 0, trans->journal->j_blocksize); if (cbh == NULL) { err = ENOMEM; goto error; } for (cblk = trans->start; cblk < trans->block; cblk++) { err = journal_bmap(trans->journal, cblk, &cbh->b_blocknr); if (err) goto error; mark_buffer_uptodate(cbh, 0); ll_rw_block(READ, 1, &cbh); err = cbh->b_err; if (err) goto error; csum_v1 = ext2fs_crc32_be(csum_v1, (unsigned char const *)cbh->b_data, cbh->b_size); } commit->h_chksum_type = JFS_CRC32_CHKSUM; commit->h_chksum_size = JFS_CRC32_CHKSUM_SIZE; commit->h_chksum[0] = ext2fs_cpu_to_be32(csum_v1); } else { commit->h_chksum_type = 0; commit->h_chksum_size = 0; commit->h_chksum[0] = 0; } #ifdef HAVE_SYS_TIME_H gettimeofday(&tv, NULL); commit->h_commit_sec = ext2fs_cpu_to_be32(tv.tv_sec); commit->h_commit_nsec = ext2fs_cpu_to_be32(tv.tv_usec * 1000); #else commit->h_commit_sec = 0; commit->h_commit_nsec = 0; #endif /* Write block */ jbd2_commit_block_csum_set(trans->journal, bh); err = journal_bmap(trans->journal, trans->block, &bh->b_blocknr); if (err) goto error; dbg_printf("Writing commit block at %llu:%llu\n", trans->block, bh->b_blocknr); mark_buffer_dirty(bh); ll_rw_block(WRITE, 1, &bh); err = bh->b_err; if (err) goto error; trans->flags |= J_TRANS_COMMITTED; trans->flags &= ~J_TRANS_OPEN; trans->block++; trans->fs->super->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER; ext2fs_mark_super_dirty(trans->fs); error: if (cbh) brelse(cbh); brelse(bh); return err; }