Commit 8dba7dc0 authored by heikki@donna.mysql.fi's avatar heikki@donna.mysql.fi
Browse files

log0recv.c Add checksum to written pages to check that they are also read in unchanged

buf0buf.h	Add checksum to written pages to check that they are also read in unchanged
buf0flu.c	Add checksum to written pages to check that they are also read in unchanged
buf0buf.c	Add checksum to written pages to check that they are also read in unchanged
parent 03cb1cce
Loading
Loading
Loading
Loading
+46 −10
Original line number Diff line number Diff line
@@ -205,6 +205,27 @@ ibool buf_debug_prints = FALSE; /* If this is set TRUE,
					the program prints info whenever
					read-ahead or flush occurs */

/************************************************************************
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value
on 32-bit and 64-bit architectures. */

ulint
buf_calc_page_checksum(
/*===================*/
		       /* out: checksum */
	byte*    page) /* in: buffer page */
{
  ulint checksum;

  checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
  + ut_fold_binary(page + FIL_PAGE_DATA, UNIV_PAGE_SIZE - FIL_PAGE_DATA
		   - FIL_PAGE_END_LSN);
  checksum = checksum & 0xFFFFFFFF;

  return(checksum);
}

/************************************************************************
Initializes a buffer control block when the buf_pool is created. */
static
@@ -1171,12 +1192,36 @@ buf_page_io_complete(
	dulint		id;
	dict_index_t*	index;
	ulint		io_type;
	ulint           checksum;

	ut_ad(block);

	io_type = block->io_fix;

	if (io_type == BUF_IO_READ) {
		checksum = buf_calc_page_checksum(block->frame);

		/* From version 3.23.38 up we store the page checksum
		   to the 4 upper bytes of the page end lsn field */

		if ((mach_read_from_4(block->frame + FIL_PAGE_LSN + 4)
		    != mach_read_from_4(block->frame + UNIV_PAGE_SIZE
					- FIL_PAGE_END_LSN + 4))
		    || (checksum != mach_read_from_4(block->frame
                                        + UNIV_PAGE_SIZE
					- FIL_PAGE_END_LSN)
			&& mach_read_from_4(block->frame + FIL_PAGE_LSN)
			    != mach_read_from_4(block->frame
                                        + UNIV_PAGE_SIZE
						- FIL_PAGE_END_LSN))) {
		  fprintf(stderr,
			  "InnoDB: Database page corruption or a failed\n"
			  "InnoDB: file read of page %lu.\n", block->offset);
		  fprintf(stderr,
			  "InnoDB: You may have to recover from a backup.\n");
		  exit(1);
		}

		if (recv_recovery_is_on()) {
			recv_recover_page(TRUE, block->frame, block->space,
								block->offset);
@@ -1208,17 +1253,8 @@ buf_page_io_complete(
		ut_ad(buf_pool->n_pend_reads > 0);
		buf_pool->n_pend_reads--;
		buf_pool->n_pages_read++;
/*		
		if (0 != ut_dulint_cmp(
				mach_read_from_8(block->frame + FIL_PAGE_LSN),
				mach_read_from_8(block->frame + UNIV_PAGE_SIZE
						- FIL_PAGE_END_LSN))) {

			printf("DB error: file page corrupted!\n");

			ut_error;
		}
*/
		rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ);
		rw_lock_x_unlock_gen(&(block->read_lock), BUF_IO_READ);

+6 −0
Original line number Diff line number Diff line
@@ -222,6 +222,12 @@ buf_flush_write_block_low(
	mach_write_to_8(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
						block->newest_modification);

	/* We overwrite the first 4 bytes of the end lsn field to store
	a page checksum */

	mach_write_to_4(block->frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN,
			buf_calc_page_checksum(block->frame));

	fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
		FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
		 			(void*)block->frame, (void*)block);
+10 −0
Original line number Diff line number Diff line
@@ -342,6 +342,16 @@ buf_frame_get_modify_clock(
/*=======================*/
				/* out: value */
	buf_frame_t*	frame);	/* in: pointer to a frame */
/************************************************************************
Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value
on 32-bit and 64-bit architectures. */

ulint
buf_calc_page_checksum(
/*===================*/
		       /* out: checksum */
	byte*   page); /* in: buffer page */
/**************************************************************************
Gets the page number of a pointer pointing within a buffer frame containing
a file page. */
+0 −6
Original line number Diff line number Diff line
@@ -882,12 +882,6 @@ recv_recover_page(
		recv = UT_LIST_GET_NEXT(rec_list, recv);
	}

	/* If the following assert fails, the file page is incompletely
	written, and a recovery from a backup is required */
	
	ut_a(0 == ut_dulint_cmp(mach_read_from_8(page + FIL_PAGE_LSN),
				mach_read_from_8(page + UNIV_PAGE_SIZE
							- FIL_PAGE_END_LSN)));
	mutex_enter(&(recv_sys->mutex));
	
	recv_addr->state = RECV_PROCESSED;