Commit 0ebb78e8 authored by unknown's avatar unknown

Many files:

  Merge InnoDB-3.23.52c
ha_innobase.cc:
  Test the ref length sanity also in the production version


sql/ha_innobase.cc:
  Test the ref length sanity also in the production version
innobase/btr/btr0cur.c:
  Merge InnoDB-3.23.52c
innobase/buf/buf0buf.c:
  Merge InnoDB-3.23.52c
innobase/buf/buf0lru.c:
  Merge InnoDB-3.23.52c
innobase/ha/ha0ha.c:
  Merge InnoDB-3.23.52c
innobase/log/log0recv.c:
  Merge InnoDB-3.23.52c
innobase/mtr/mtr0log.c:
  Merge InnoDB-3.23.52c
innobase/os/os0file.c:
  Merge InnoDB-3.23.52c
innobase/page/page0cur.c:
  Merge InnoDB-3.23.52c
innobase/include/btr0btr.h:
  Merge InnoDB-3.23.52c
innobase/include/dyn0dyn.h:
  Merge InnoDB-3.23.52c
innobase/include/log0recv.h:
  Merge InnoDB-3.23.52c
innobase/include/buf0buf.ic:
  Merge InnoDB-3.23.52c
innobase/include/log0log.ic:
  Merge InnoDB-3.23.52c
parent dd764d99
...@@ -808,7 +808,7 @@ btr_cur_optimistic_insert( ...@@ -808,7 +808,7 @@ btr_cur_optimistic_insert(
if (!dtuple_check_typed_no_assert(entry)) { if (!dtuple_check_typed_no_assert(entry)) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error in a tuple to insert into table %s index %s\n", "InnoDB: Error in a tuple to insert into table %lu index %s\n",
index->table_name, index->name); index->table_name, index->name);
} }
...@@ -1213,6 +1213,8 @@ btr_cur_parse_update_in_place( ...@@ -1213,6 +1213,8 @@ btr_cur_parse_update_in_place(
rec_offset = mach_read_from_2(ptr); rec_offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
ut_a(rec_offset <= UNIV_PAGE_SIZE);
heap = mem_heap_create(256); heap = mem_heap_create(256);
ptr = row_upd_index_parse(ptr, end_ptr, heap, &update); ptr = row_upd_index_parse(ptr, end_ptr, heap, &update);
...@@ -1977,6 +1979,8 @@ btr_cur_parse_del_mark_set_clust_rec( ...@@ -1977,6 +1979,8 @@ btr_cur_parse_del_mark_set_clust_rec(
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
ut_a(offset <= UNIV_PAGE_SIZE);
if (page) { if (page) {
rec = page + offset; rec = page + offset;
...@@ -2127,6 +2131,8 @@ btr_cur_parse_del_mark_set_sec_rec( ...@@ -2127,6 +2131,8 @@ btr_cur_parse_del_mark_set_sec_rec(
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
ut_a(offset <= UNIV_PAGE_SIZE);
if (page) { if (page) {
rec = page + offset; rec = page + offset;
......
...@@ -286,7 +286,7 @@ buf_page_print( ...@@ -286,7 +286,7 @@ buf_page_print(
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: Page dump in ascii and hex (%lu bytes):\n%s", " InnoDB: Page dump in ascii and hex (%lu bytes):\n%s",
(unsigned long) UNIV_PAGE_SIZE, buf); (ulint)UNIV_PAGE_SIZE, buf);
fprintf(stderr, "InnoDB: End of page dump\n"); fprintf(stderr, "InnoDB: End of page dump\n");
mem_free(buf); mem_free(buf);
......
...@@ -204,6 +204,44 @@ buf_LRU_get_free_block(void) ...@@ -204,6 +204,44 @@ buf_LRU_get_free_block(void)
loop: loop:
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
if (UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index!\n"
"InnoDB: We intentionally generate a seg fault to print a stack trace\n"
"InnoDB: on Linux!\n");
ut_a(0);
} else if (UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
/* Over 80 % of the buffer pool is occupied by lock heaps
or the adaptive hash index. This may be a memory leak! */
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks. Starting InnoDB\n"
"InnoDB: Monitor to print diagnostics, including lock heap and hash index\n"
"InnoDB: sizes.\n");
srv_print_innodb_monitor = TRUE;
} else if (UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
/* Switch off the InnoDB Monitor; this is a simple way
to stop the monitor if the situation becomes less urgent,
but may also surprise users! */
srv_print_innodb_monitor = FALSE;
}
if (buf_pool->LRU_flush_ended > 0) { if (buf_pool->LRU_flush_ended > 0) {
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
......
...@@ -298,6 +298,7 @@ ha_print_info( ...@@ -298,6 +298,7 @@ ha_print_info(
ulint cells = 0; ulint cells = 0;
ulint len = 0; ulint len = 0;
ulint max_len = 0; ulint max_len = 0;
ulint n_bufs;
ulint i; ulint i;
if (buf_end - buf < 200) { if (buf_end - buf < 200) {
...@@ -339,7 +340,16 @@ ha_print_info( ...@@ -339,7 +340,16 @@ ha_print_info(
"Hash table size %lu, used cells %lu", hash_get_n_cells(table), cells); "Hash table size %lu, used cells %lu", hash_get_n_cells(table), cells);
if (table->heaps == NULL && table->heap != NULL) { if (table->heaps == NULL && table->heap != NULL) {
buf += sprintf(buf,
", node heap has %lu buffer(s)\n", UT_LIST_GET_LEN(table->heap->base)); /* This calculation is intended for the adaptive hash
index: how many buffer frames we have reserved? */
n_bufs = UT_LIST_GET_LEN(table->heap->base) - 1;
if (table->heap->free_block) {
n_bufs++;
}
buf += sprintf(buf, ", node heap has %lu buffer(s)\n", n_bufs);
} }
} }
...@@ -313,14 +313,6 @@ btr_discard_page( ...@@ -313,14 +313,6 @@ btr_discard_page(
btr_cur_t* cursor, /* in: cursor on the page to discard: not on btr_cur_t* cursor, /* in: cursor on the page to discard: not on
the root page */ the root page */
mtr_t* mtr); /* in: mtr */ mtr_t* mtr); /* in: mtr */
/************************************************************************
Declares the latching order level for the page latch in the debug version. */
void
btr_declare_page_latch(
/*===================*/
page_t* page, /* in: page */
ibool leaf); /* in: TRUE if a leaf */
/******************************************************************** /********************************************************************
Parses the redo log record for setting an index record as the predefined Parses the redo log record for setting an index record as the predefined
minimum record. */ minimum record. */
......
...@@ -211,8 +211,15 @@ buf_block_align( ...@@ -211,8 +211,15 @@ buf_block_align(
block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero)) block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
>> UNIV_PAGE_SIZE_SHIFT); >> UNIV_PAGE_SIZE_SHIFT);
ut_a(block >= buf_pool->blocks); if (block < buf_pool->blocks
ut_a(block < buf_pool->blocks + buf_pool->max_size); || block >= buf_pool->blocks + buf_pool->max_size) {
fprintf(stderr,
"InnoDB: Error: trying to access a stray pointer %lx\n"
"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
(ulint)frame_zero, buf_pool->max_size);
ut_a(0);
}
return(block); return(block);
} }
...@@ -238,8 +245,15 @@ buf_block_align_low( ...@@ -238,8 +245,15 @@ buf_block_align_low(
block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero)) block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
>> UNIV_PAGE_SIZE_SHIFT); >> UNIV_PAGE_SIZE_SHIFT);
ut_a(block >= buf_pool->blocks); if (block < buf_pool->blocks
ut_a(block < buf_pool->blocks + buf_pool->max_size); || block >= buf_pool->blocks + buf_pool->max_size) {
fprintf(stderr,
"InnoDB: Error: trying to access a stray pointer %lx\n"
"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
(ulint)frame_zero, buf_pool->max_size);
ut_a(0);
}
return(block); return(block);
} }
...@@ -259,10 +273,17 @@ buf_frame_align( ...@@ -259,10 +273,17 @@ buf_frame_align(
frame = ut_align_down(ptr, UNIV_PAGE_SIZE); frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
ut_a((ulint)frame if (((ulint)frame
>= (ulint)(buf_pool_get_nth_block(buf_pool, 0)->frame)); < (ulint)(buf_pool->frame_zero))
ut_a((ulint)frame <= (ulint)(buf_pool_get_nth_block(buf_pool, || ((ulint)frame > (ulint)(buf_pool_get_nth_block(buf_pool,
buf_pool->max_size - 1)->frame)); buf_pool->max_size - 1)->frame))) {
fprintf(stderr,
"InnoDB: Error: trying to access a stray pointer %lx\n"
"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
(ulint)(buf_pool->frame_zero), buf_pool->max_size);
ut_a(0);
}
return(frame); return(frame);
} }
......
...@@ -125,14 +125,6 @@ dyn_block_get_data( ...@@ -125,14 +125,6 @@ dyn_block_get_data(
/*===============*/ /*===============*/
/* out: pointer to data */ /* out: pointer to data */
dyn_block_t* block); /* in: dyn array block */ dyn_block_t* block); /* in: dyn array block */
/************************************************************************
Gets the next block in a dyn array. */
dyn_block_t*
dyn_block_get_next(
/*===============*/
/* out: pointer to next, NULL if end of list */
dyn_block_t* block); /* in: dyn array block */
/************************************************************ /************************************************************
Pushes n bytes to a dyn array. */ Pushes n bytes to a dyn array. */
UNIV_INLINE UNIV_INLINE
......
...@@ -207,7 +207,7 @@ log_block_calc_checksum( ...@@ -207,7 +207,7 @@ log_block_calc_checksum(
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) { for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
sum = sum & 0x7FFFFFFF; sum = sum & 0x7FFFFFFF;
sum += ((ulint)(*(block + i))) << sh; sum += (((ulint)(*(block + i))) << sh) + (ulint)(*(block + i));
sh++; sh++;
if (sh > 24) { if (sh > 24) {
sh = 0; sh = 0;
......
...@@ -316,7 +316,8 @@ struct recv_sys_struct{ ...@@ -316,7 +316,8 @@ struct recv_sys_struct{
ibool found_corrupt_log; ibool found_corrupt_log;
/* this is set to TRUE if we during log /* this is set to TRUE if we during log
scan find a corrupt log block, or a corrupt scan find a corrupt log block, or a corrupt
log record */ log record, or there is a log parsing
buffer overflow */
log_group_t* archive_group; log_group_t* archive_group;
/* in archive recovery: the log group whose /* in archive recovery: the log group whose
archive is read */ archive is read */
......
...@@ -58,13 +58,17 @@ yet: the variable name is misleading */ ...@@ -58,13 +58,17 @@ yet: the variable name is misleading */
ibool recv_no_ibuf_operations = FALSE; ibool recv_no_ibuf_operations = FALSE;
/* the following counter is used to decide when to print info on /* The following counter is used to decide when to print info on
log scan */ log scan */
ulint recv_scan_print_counter = 0; ulint recv_scan_print_counter = 0;
ibool recv_is_from_backup = FALSE; ibool recv_is_from_backup = FALSE;
ibool recv_is_making_a_backup = FALSE; ibool recv_is_making_a_backup = FALSE;
ulint recv_previous_parsed_rec_type = 999999;
ulint recv_previous_parsed_rec_offset = 0;
ulint recv_previous_parsed_rec_is_multi = 0;
/************************************************************ /************************************************************
Creates the recovery system. */ Creates the recovery system. */
...@@ -695,7 +699,7 @@ byte* ...@@ -695,7 +699,7 @@ byte*
recv_parse_or_apply_log_rec_body( recv_parse_or_apply_log_rec_body(
/*=============================*/ /*=============================*/
/* out: log record end, NULL if not a complete /* out: log record end, NULL if not a complete
record, or a corrupt record */ record */
byte type, /* in: type */ byte type, /* in: type */
byte* ptr, /* in: pointer to a buffer */ byte* ptr, /* in: pointer to a buffer */
byte* end_ptr,/* in: pointer to the buffer end */ byte* end_ptr,/* in: pointer to the buffer end */
...@@ -771,15 +775,6 @@ recv_parse_or_apply_log_rec_body( ...@@ -771,15 +775,6 @@ recv_parse_or_apply_log_rec_body(
} else { } else {
new_ptr = NULL; new_ptr = NULL;
fprintf(stderr,
"InnoDB: WARNING: the log file may have been corrupt and it\n"
"InnoDB: is possible that the log scan did not proceed\n"
"InnoDB: far enough in recovery. Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: Corrupt log record type %lu\n, lsn %lu %lu\n",
(ulint)type, ut_dulint_get_high(recv_sys->recovered_lsn),
ut_dulint_get_low(recv_sys->recovered_lsn));
recv_sys->found_corrupt_log = TRUE; recv_sys->found_corrupt_log = TRUE;
} }
...@@ -1651,7 +1646,7 @@ ulint ...@@ -1651,7 +1646,7 @@ ulint
recv_parse_log_rec( recv_parse_log_rec(
/*===============*/ /*===============*/
/* out: length of the record, or 0 if the record was /* out: length of the record, or 0 if the record was
not complete or it was corrupt */ not complete */
byte* ptr, /* in: pointer to a buffer */ byte* ptr, /* in: pointer to a buffer */
byte* end_ptr,/* in: pointer to the buffer end */ byte* end_ptr,/* in: pointer to the buffer end */
byte* type, /* out: type */ byte* type, /* out: type */
...@@ -1691,16 +1686,6 @@ recv_parse_log_rec( ...@@ -1691,16 +1686,6 @@ recv_parse_log_rec(
/* Check that space id and page_no are sensible */ /* Check that space id and page_no are sensible */
if (*space != 0 || *page_no > 0x8FFFFFFF) { if (*space != 0 || *page_no > 0x8FFFFFFF) {
fprintf(stderr,
"InnoDB: WARNING: the log file may have been corrupt and it\n"
"InnoDB: is possible that the log scan did not proceed\n"
"InnoDB: far enough in recovery. Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: Corrupt log record type %lu, space id %lu, page no %lu\n",
"InnoDB: lsn %lu %lu\n",
(ulint)(*type), *space, *page_no,
ut_dulint_get_high(recv_sys->recovered_lsn),
ut_dulint_get_low(recv_sys->recovered_lsn));
recv_sys->found_corrupt_log = TRUE; recv_sys->found_corrupt_log = TRUE;
...@@ -1766,6 +1751,63 @@ recv_check_incomplete_log_recs( ...@@ -1766,6 +1751,63 @@ recv_check_incomplete_log_recs(
} }
} }
/***********************************************************
Prints diagnostic info of corrupt log. */
static
void
recv_report_corrupt_log(
/*====================*/
byte* ptr, /* in: pointer to corrupt log record */
byte type, /* in: type of the record */
ulint space, /* in: space id, this may also be garbage */
ulint page_no)/* in: page number, this may also be garbage */
{
char* err_buf;
fprintf(stderr,
"InnoDB: ############### CORRUPT LOG RECORD FOUND\n"
"InnoDB: Log record type %lu, space id %lu, page number %lu\n"
"InnoDB: Log parsing proceeded successfully up to %lu %lu\n",
(ulint)type, space, page_no,
ut_dulint_get_high(recv_sys->recovered_lsn),
ut_dulint_get_low(recv_sys->recovered_lsn));
err_buf = ut_malloc(1000000);
fprintf(stderr,
"InnoDB: Previous log record type %lu, is multi %lu\n"
"InnoDB: Recv offset %lu, prev %lu\n",
recv_previous_parsed_rec_type,
recv_previous_parsed_rec_is_multi,
ptr - recv_sys->buf,
recv_previous_parsed_rec_offset);
if ((ulint)(ptr - recv_sys->buf + 100)
> recv_previous_parsed_rec_offset
&& (ulint)(ptr - recv_sys->buf + 100
- recv_previous_parsed_rec_offset)
< 200000) {
ut_sprintf_buf(err_buf,
recv_sys->buf + recv_previous_parsed_rec_offset - 100,
ptr - recv_sys->buf + 200 -
recv_previous_parsed_rec_offset);
fprintf(stderr,
"InnoDB: Hex dump of corrupt log starting 100 bytes before the start\n"
"InnoDB: of the previous log rec,\n"
"InnoDB: and ending 100 bytes after the start of the corrupt rec:\n%s\n",
err_buf);
}
ut_free(err_buf);
fprintf(stderr,
"InnoDB: WARNING: the log file may have been corrupt and it\n"
"InnoDB: is possible that the log scan did not proceed\n"
"InnoDB: far enough in recovery! Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n");
}
/*********************************************************** /***********************************************************
Parses log records from a buffer and stores them to a hash table to wait Parses log records from a buffer and stores them to a hash table to wait
merging to file pages. */ merging to file pages. */
...@@ -1773,8 +1815,7 @@ static ...@@ -1773,8 +1815,7 @@ static
ibool ibool
recv_parse_log_recs( recv_parse_log_recs(
/*================*/ /*================*/
/* out: TRUE if the hash table of parsed log /* out: currently always returns FALSE */
records became full */
ibool store_to_hash) /* in: TRUE if the records should be stored ibool store_to_hash) /* in: TRUE if the records should be stored
to the hash table; this is set to FALSE if just to the hash table; this is set to FALSE if just
debug checking is needed */ debug checking is needed */
...@@ -1791,7 +1832,6 @@ recv_parse_log_recs( ...@@ -1791,7 +1832,6 @@ recv_parse_log_recs(
ulint page_no; ulint page_no;
byte* body; byte* body;
ulint n_recs; ulint n_recs;
char err_buf[2500];
ut_ad(mutex_own(&(log_sys->mutex))); ut_ad(mutex_own(&(log_sys->mutex)));
ut_ad(!ut_dulint_is_zero(recv_sys->parse_start_lsn)); ut_ad(!ut_dulint_is_zero(recv_sys->parse_start_lsn));
...@@ -1814,17 +1854,11 @@ loop: ...@@ -1814,17 +1854,11 @@ loop:
len = recv_parse_log_rec(ptr, end_ptr, &type, &space, len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
&page_no, &body); &page_no, &body);
if (len == 0) { if (len == 0 || recv_sys->found_corrupt_log) {
if (recv_sys->found_corrupt_log) { if (recv_sys->found_corrupt_log) {
ut_sprintf_buf(err_buf, recv_report_corrupt_log(ptr,
recv_sys->buf + ut_calc_align_down( type, space, page_no);
recv_sys->recovered_offset,
OS_FILE_LOG_BLOCK_SIZE) - 8,
OS_FILE_LOG_BLOCK_SIZE + 16);
fprintf(stderr,
"InnoDB: hex dump of a corrupt log segment: %s\n", err_buf);
} }
return(FALSE); return(FALSE);
...@@ -1841,6 +1875,10 @@ loop: ...@@ -1841,6 +1875,10 @@ loop:
return(FALSE); return(FALSE);
} }
recv_previous_parsed_rec_type = (ulint)type;
recv_previous_parsed_rec_offset = recv_sys->recovered_offset;
recv_previous_parsed_rec_is_multi = 0;
recv_sys->recovered_offset += len; recv_sys->recovered_offset += len;
recv_sys->recovered_lsn = new_recovered_lsn; recv_sys->recovered_lsn = new_recovered_lsn;
...@@ -1879,22 +1917,22 @@ loop: ...@@ -1879,22 +1917,22 @@ loop:
for (;;) { for (;;) {
len = recv_parse_log_rec(ptr, end_ptr, &type, &space, len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
&page_no, &body); &page_no, &body);
if (len == 0) { if (len == 0 || recv_sys->found_corrupt_log) {
if (recv_sys->found_corrupt_log) { if (recv_sys->found_corrupt_log) {
ut_sprintf_buf(err_buf,
recv_sys->buf + ut_calc_align_down(
recv_sys->recovered_offset,
OS_FILE_LOG_BLOCK_SIZE) - 8,
OS_FILE_LOG_BLOCK_SIZE + 16);
fprintf(stderr, recv_report_corrupt_log(ptr,
"InnoDB: hex dump of a corrupt log segment: %s\n", err_buf); type, space, page_no);
} }
return(FALSE); return(FALSE);
} }
recv_previous_parsed_rec_type = (ulint)type;
recv_previous_parsed_rec_offset
= recv_sys->recovered_offset + total_len;
recv_previous_parsed_rec_is_multi = 1;
if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) { if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) {
/* In debug checking, update a replicate page /* In debug checking, update a replicate page
according to the log record */ according to the log record */
...@@ -1946,6 +1984,12 @@ loop: ...@@ -1946,6 +1984,12 @@ loop:
old_lsn = recv_sys->recovered_lsn; old_lsn = recv_sys->recovered_lsn;
len = recv_parse_log_rec(ptr, end_ptr, &type, &space, len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
&page_no, &body); &page_no, &body);
if (recv_sys->found_corrupt_log) {
recv_report_corrupt_log(ptr,
type, space, page_no);
}
ut_a(len != 0); ut_a(len != 0);
ut_a(0 == ((ulint)*ptr & MLOG_SINGLE_REC_FLAG)); ut_a(0 == ((ulint)*ptr & MLOG_SINGLE_REC_FLAG));
...@@ -2206,11 +2250,14 @@ recv_scan_log_recs( ...@@ -2206,11 +2250,14 @@ recv_scan_log_recs(
>= RECV_PARSING_BUF_SIZE) { >= RECV_PARSING_BUF_SIZE) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: log parsing buffer overflow. Recovery may have failed!\n"); "InnoDB: Error: log parsing buffer overflow. Recovery may have failed!\n");
finished = TRUE;
recv_sys->found_corrupt_log = TRUE;
} else if (!recv_sys->found_corrupt_log) {
more_data = recv_sys_add_to_parsing_buf(
log_block, scanned_lsn);
} }
more_data = recv_sys_add_to_parsing_buf(log_block,
scanned_lsn);
recv_sys->scanned_lsn = scanned_lsn; recv_sys->scanned_lsn = scanned_lsn;
recv_sys->scanned_checkpoint_no = recv_sys->scanned_checkpoint_no =
log_block_get_checkpoint_no(log_block); log_block_get_checkpoint_no(log_block);
...@@ -2240,7 +2287,7 @@ recv_scan_log_recs( ...@@ -2240,7 +2287,7 @@ recv_scan_log_recs(
} }
} }
if (more_data) { if (more_data && !recv_sys->found_corrupt_log) {
/* Try to parse more log records */ /* Try to parse more log records */
recv_parse_log_recs(store_to_hash); recv_parse_log_recs(store_to_hash);
...@@ -2617,6 +2664,17 @@ recv_recovery_from_checkpoint_finish(void) ...@@ -2617,6 +2664,17 @@ recv_recovery_from_checkpoint_finish(void)
trx_sys_print_mysql_binlog_offset(); trx_sys_print_mysql_binlog_offset();
} }
if (recv_sys->found_corrupt_log) {
fprintf(stderr,
"InnoDB: WARNING: the log file may have been corrupt and it\n"
"InnoDB: is possible that the log scan or parsing did not proceed\n"
"InnoDB: far enough in recovery. Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: It may be safest to recover your InnoDB database from\n"
"InnoDB: a backup!\n");
}
/* Free the resources of the recovery system */ /* Free the resources of the recovery system */
recv_recovery_on = FALSE; recv_recovery_on = FALSE;
......
...@@ -14,6 +14,7 @@ Created 12/7/1995 Heikki Tuuri ...@@ -14,6 +14,7 @@ Created 12/7/1995 Heikki Tuuri
#include "buf0buf.h" #include "buf0buf.h"
#include "dict0boot.h" #include "dict0boot.h"
#include "log0recv.h"
/************************************************************ /************************************************************
Catenates n bytes to the mtr log. */ Catenates n bytes to the mtr log. */
...@@ -121,7 +122,7 @@ byte* ...@@ -121,7 +122,7 @@ byte*
mlog_parse_nbytes( mlog_parse_nbytes(
/*==============*/ /*==============*/
/* out: parsed record end, NULL if not a complete /* out: parsed record end, NULL if not a complete
record */ record or a corrupt record */
ulint type, /* in: log record type: MLOG_1BYTE, ... */ ulint type, /* in: log record type: MLOG_1BYTE, ... */
byte* ptr, /* in: buffer */ byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */ byte* end_ptr,/* in: buffer end */
...@@ -141,6 +142,12 @@ mlog_parse_nbytes( ...@@ -141,6 +142,12 @@ mlog_parse_nbytes(
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
if (offset >= UNIV_PAGE_SIZE) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
if (type == MLOG_8BYTES) { if (type == MLOG_8BYTES) {
ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval); ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval);
...@@ -163,13 +170,33 @@ mlog_parse_nbytes( ...@@ -163,13 +170,33 @@ mlog_parse_nbytes(
return(NULL); return(NULL);
} }
if (type == MLOG_1BYTE) {
if (val > 0xFF) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
} else if (type == MLOG_2BYTES) {
if (val > 0xFFFF) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
} else {
if (type != MLOG_4BYTES) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
}
if (page) { if (page) {
if (type == MLOG_1BYTE) { if (type == MLOG_1BYTE) {
mach_write_to_1(page + offset, val); mach_write_to_1(page + offset, val);
} else if (type == MLOG_2BYTES) { } else if (type == MLOG_2BYTES) {
mach_write_to_2(page + offset, val); mach_write_to_2(page + offset, val);
} else { } else {
ut_ad(type == MLOG_4BYTES); ut_a(type == MLOG_4BYTES);
mach_write_to_4(page + offset, val); mach_write_to_4(page + offset, val);
} }
} }
...@@ -338,7 +365,11 @@ mlog_parse_string( ...@@ -338,7 +365,11 @@ mlog_parse_string(
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
ut_a(offset < UNIV_PAGE_SIZE); if (offset >= UNIV_PAGE_SIZE) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
len = mach_read_from_2(ptr); len = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
......
...@@ -22,7 +22,7 @@ Created 10/21/1995 Heikki Tuuri ...@@ -22,7 +22,7 @@ Created 10/21/1995 Heikki Tuuri
#endif #endif
/* This specifies the file permissions InnoDB uses when it craetes files in /* This specifies the file permissions InnoDB uses when it creates files in
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
my_umask */ my_umask */
......
...@@ -13,6 +13,7 @@ Created 10/4/1994 Heikki Tuuri ...@@ -13,6 +13,7 @@ Created 10/4/1994 Heikki Tuuri
#include "rem0cmp.h" #include "rem0cmp.h"
#include "mtr0log.h" #include "mtr0log.h"
#include "log0recv.h"
ulint page_cur_short_succ = 0; ulint page_cur_short_succ = 0;
...@@ -481,6 +482,9 @@ page_cur_insert_rec_write_log( ...@@ -481,6 +482,9 @@ page_cur_insert_rec_write_log(
/* Write the mismatch index */ /* Write the mismatch index */
log_ptr += mach_write_compressed(log_ptr, i); log_ptr += mach_write_compressed(log_ptr, i);
ut_a(i < UNIV_PAGE_SIZE);
ut_a(extra_size < UNIV_PAGE_SIZE);
} }
/* Write to the log the inserted index record end segment which /* Write to the log the inserted index record end segment which
...@@ -534,6 +538,13 @@ page_cur_parse_insert_rec( ...@@ -534,6 +538,13 @@ page_cur_parse_insert_rec(
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
if (offset >= UNIV_PAGE_SIZE) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
ptr += 2; ptr += 2;
} }
...@@ -547,6 +558,12 @@ page_cur_parse_insert_rec( ...@@ -547,6 +558,12 @@ page_cur_parse_insert_rec(
extra_info_yes = end_seg_len & 0x1; extra_info_yes = end_seg_len & 0x1;
end_seg_len = end_seg_len / 2; end_seg_len = end_seg_len / 2;
if (end_seg_len >= UNIV_PAGE_SIZE) {
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
if (extra_info_yes) { if (extra_info_yes) {
/* Read the info bits */ /* Read the info bits */
...@@ -565,12 +582,16 @@ page_cur_parse_insert_rec( ...@@ -565,12 +582,16 @@ page_cur_parse_insert_rec(
return(NULL); return(NULL);
} }
ut_a(origin_offset < UNIV_PAGE_SIZE);
ptr = mach_parse_compressed(ptr, end_ptr, &mismatch_index); ptr = mach_parse_compressed(ptr, end_ptr, &mismatch_index);
if (ptr == NULL) { if (ptr == NULL) {
return(NULL); return(NULL);
} }
ut_a(mismatch_index < UNIV_PAGE_SIZE);
} }
if (end_ptr < ptr + end_seg_len) { if (end_ptr < ptr + end_seg_len) {
...@@ -607,7 +628,6 @@ page_cur_parse_insert_rec( ...@@ -607,7 +628,6 @@ page_cur_parse_insert_rec(
/* Build the inserted record to buf */ /* Build the inserted record to buf */
ut_a(mismatch_index < UNIV_PAGE_SIZE); ut_a(mismatch_index < UNIV_PAGE_SIZE);
ut_a(end_seg_len < UNIV_PAGE_SIZE);
ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index); ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index);
ut_memcpy(buf + mismatch_index, ptr, end_seg_len); ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
...@@ -1009,6 +1029,8 @@ page_cur_parse_delete_rec( ...@@ -1009,6 +1029,8 @@ page_cur_parse_delete_rec(
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
ut_a(offset <= UNIV_PAGE_SIZE);
if (page) { if (page) {
page_cur_position(page + offset, &cursor); page_cur_position(page + offset, &cursor);
......
...@@ -2474,7 +2474,7 @@ ha_innobase::position( ...@@ -2474,7 +2474,7 @@ ha_innobase::position(
that len is always fixed for this table. The following assertion that len is always fixed for this table. The following assertion
checks this. */ checks this. */
DBUG_ASSERT(len == ref_length); ut_a(len == ref_length);
} }
/********************************************************************* /*********************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment