]> git.pld-linux.org Git - packages/mysql.git/blame - innodb_pass_corrupt_table.patch
- up to 5.5.17
[packages/mysql.git] / innodb_pass_corrupt_table.patch
CommitLineData
b4e1fa2c
AM
1# name : innodb_pass_corrupt_table.patch
2# introduced : 11 or before
3# maintainer : Yasufumi
4#
5#!!! notice !!!
6# Any small change to this file in the main branch
7# should be done or reviewed by the maintainer!
db82db79
AM
8--- a/storage/innobase/btr/btr0btr.c
9+++ b/storage/innobase/btr/btr0btr.c
734d6226 10@@ -692,6 +692,12 @@
b4e1fa2c 11
734d6226
AM
12 block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
13 index, mtr);
b4e1fa2c
AM
14+
15+ if (srv_pass_corrupt_table && !block) {
16+ return(0);
17+ }
18+ ut_a(block);
19+
20 ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
21 == dict_table_is_comp(index->table));
22 #ifdef UNIV_BTR_DEBUG
734d6226 23@@ -978,6 +984,12 @@
b4e1fa2c
AM
24
25 root = btr_root_get(index, &mtr);
26
27+ if (srv_pass_corrupt_table && !root) {
28+ mtr_commit(&mtr);
29+ return(0);
30+ }
31+ ut_a(root);
32+
33 if (flag == BTR_N_LEAF_PAGES) {
34 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
35
734d6226 36@@ -1437,6 +1449,13 @@
b4e1fa2c 37
734d6226
AM
38 root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
39 NULL, &mtr);
b4e1fa2c
AM
40+
41+ if (srv_pass_corrupt_table && !root) {
42+ mtr_commit(&mtr);
43+ return;
44+ }
45+ ut_a(root);
734d6226 46+
b4e1fa2c
AM
47 #ifdef UNIV_BTR_DEBUG
48 ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
49 + root, space));
734d6226 50@@ -1460,6 +1479,12 @@
b4e1fa2c 51
734d6226
AM
52 root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
53 NULL, &mtr);
b4e1fa2c
AM
54+
55+ if (srv_pass_corrupt_table && !root) {
56+ mtr_commit(&mtr);
57+ return;
58+ }
59+ ut_a(root);
60 #ifdef UNIV_BTR_DEBUG
61 ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
62 + root, space));
734d6226
AM
63@@ -1493,6 +1518,11 @@
64 block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
65 NULL, mtr);
b4e1fa2c
AM
66
67+ if (srv_pass_corrupt_table && !block) {
68+ return;
69+ }
70+ ut_a(block);
71+
72 btr_search_drop_page_hash_index(block);
73
74 header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
db82db79
AM
75--- a/storage/innobase/btr/btr0cur.c
76+++ b/storage/innobase/btr/btr0cur.c
734d6226 77@@ -251,6 +251,11 @@
b4e1fa2c 78 mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
734d6226
AM
79 get_block = btr_block_get(
80 space, zip_size, page_no, mode, cursor->index, mtr);
b4e1fa2c
AM
81+
82+ if (srv_pass_corrupt_table && !get_block) {
83+ return;
84+ }
85+ ut_a(get_block);
86 #ifdef UNIV_BTR_DEBUG
87 ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
88 #endif /* UNIV_BTR_DEBUG */
734d6226
AM
89@@ -264,6 +269,11 @@
90 get_block = btr_block_get(
91 space, zip_size, left_page_no,
92 RW_X_LATCH, cursor->index, mtr);
b4e1fa2c
AM
93+
94+ if (srv_pass_corrupt_table && !get_block) {
95+ return;
96+ }
97+ ut_a(get_block);
98 #ifdef UNIV_BTR_DEBUG
99 ut_a(page_is_comp(get_block->frame)
100 == page_is_comp(page));
734d6226
AM
101@@ -276,6 +286,11 @@
102 get_block = btr_block_get(
103 space, zip_size, page_no,
104 RW_X_LATCH, cursor->index, mtr);
b4e1fa2c
AM
105+
106+ if (srv_pass_corrupt_table && !get_block) {
107+ return;
108+ }
109+ ut_a(get_block);
110 #ifdef UNIV_BTR_DEBUG
111 ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
112 #endif /* UNIV_BTR_DEBUG */
734d6226
AM
113@@ -287,6 +302,11 @@
114 get_block = btr_block_get(
115 space, zip_size, right_page_no,
116 RW_X_LATCH, cursor->index, mtr);
b4e1fa2c
AM
117+
118+ if (srv_pass_corrupt_table && !get_block) {
119+ return;
120+ }
121+ ut_a(get_block);
122 #ifdef UNIV_BTR_DEBUG
123 ut_a(page_is_comp(get_block->frame)
124 == page_is_comp(page));
734d6226
AM
125@@ -309,6 +329,11 @@
126 space, zip_size,
127 left_page_no, mode, cursor->index, mtr);
b4e1fa2c
AM
128 cursor->left_block = get_block;
129+
130+ if (srv_pass_corrupt_table && !get_block) {
131+ return;
132+ }
133+ ut_a(get_block);
134 #ifdef UNIV_BTR_DEBUG
135 ut_a(page_is_comp(get_block->frame)
136 == page_is_comp(page));
734d6226 137@@ -320,6 +345,11 @@
b4e1fa2c 138
734d6226
AM
139 get_block = btr_block_get(
140 space, zip_size, page_no, mode, cursor->index, mtr);
b4e1fa2c
AM
141+
142+ if (srv_pass_corrupt_table && !get_block) {
143+ return;
144+ }
145+ ut_a(get_block);
146 #ifdef UNIV_BTR_DEBUG
147 ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
148 #endif /* UNIV_BTR_DEBUG */
734d6226 149@@ -592,6 +622,19 @@
b4e1fa2c
AM
150 file, line, mtr);
151
152 if (block == NULL) {
153+ if (srv_pass_corrupt_table
154+ && buf_mode != BUF_GET_IF_IN_POOL
155+ && buf_mode != BUF_GET_IF_IN_POOL_OR_WATCH) {
156+ page_cursor->block = 0;
157+ page_cursor->rec = 0;
158+ if (estimate) {
159+ cursor->path_arr->nth_rec = ULINT_UNDEFINED;
160+ }
161+ goto func_exit;
162+ }
163+ ut_a(buf_mode == BUF_GET_IF_IN_POOL
164+ || buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH);
165+
166 /* This must be a search to perform an insert/delete
167 mark/ delete; try using the insert/delete buffer */
168
734d6226 169@@ -666,6 +709,16 @@
b4e1fa2c
AM
170 block->check_index_page_at_flush = TRUE;
171 page = buf_block_get_frame(block);
172
173+ if (srv_pass_corrupt_table && !page) {
174+ page_cursor->block = 0;
175+ page_cursor->rec = 0;
176+ if (estimate) {
177+ cursor->path_arr->nth_rec = ULINT_UNDEFINED;
178+ }
179+ goto func_exit;
180+ }
181+ ut_a(page);
182+
183 if (rw_latch != RW_NO_LATCH) {
184 #ifdef UNIV_ZIP_DEBUG
185 const page_zip_des_t* page_zip
734d6226 186@@ -872,6 +925,17 @@
b4e1fa2c
AM
187 RW_NO_LATCH, NULL, BUF_GET,
188 file, line, mtr);
189 page = buf_block_get_frame(block);
190+
191+ if (srv_pass_corrupt_table && !page) {
192+ page_cursor->block = 0;
193+ page_cursor->rec = 0;
194+ if (estimate) {
195+ cursor->path_arr->nth_rec = ULINT_UNDEFINED;
196+ }
197+ break;
198+ }
199+ ut_a(page);
200+
201 ut_ad(index->id == btr_page_get_index_id(page));
202
203 block->check_index_page_at_flush = TRUE;
734d6226 204@@ -992,6 +1056,14 @@
b4e1fa2c
AM
205 RW_NO_LATCH, NULL, BUF_GET,
206 file, line, mtr);
207 page = buf_block_get_frame(block);
208+
209+ if (srv_pass_corrupt_table && !page) {
210+ page_cursor->block = 0;
211+ page_cursor->rec = 0;
212+ break;
213+ }
214+ ut_a(page);
215+
216 ut_ad(index->id == btr_page_get_index_id(page));
217
218 if (height == ULINT_UNDEFINED) {
734d6226 219@@ -1205,6 +1277,12 @@
b4e1fa2c
AM
220 *big_rec = NULL;
221
222 block = btr_cur_get_block(cursor);
223+
224+ if (srv_pass_corrupt_table && !block) {
225+ return(DB_CORRUPTION);
226+ }
227+ ut_a(block);
228+
229 page = buf_block_get_frame(block);
230 index = cursor->index;
231 zip_size = buf_block_get_zip_size(block);
734d6226 232@@ -2937,6 +3015,11 @@
b4e1fa2c
AM
233
234 block = btr_cur_get_block(cursor);
235
236+ if (srv_pass_corrupt_table && !block) {
237+ return(DB_CORRUPTION);
238+ }
239+ ut_a(block);
240+
241 ut_ad(page_is_leaf(buf_block_get_frame(block)));
242
243 rec = btr_cur_get_rec(cursor);
734d6226 244@@ -3650,6 +3733,11 @@
b4e1fa2c
AM
245
246 page = btr_cur_get_page(&cursor);
247
248+ if (srv_pass_corrupt_table && !page) {
249+ break;
250+ }
251+ ut_a(page);
252+
df1b5770
AM
253 rec = page_rec_get_next(page_get_infimum_rec(page));
254
255 if (!page_rec_is_supremum(rec)) {
db82db79
AM
256--- a/storage/innobase/btr/btr0pcur.c
257+++ b/storage/innobase/btr/btr0pcur.c
b4e1fa2c
AM
258@@ -32,7 +32,7 @@
259 #include "ut0byte.h"
260 #include "rem0cmp.h"
261 #include "trx0trx.h"
262-
263+#include "srv0srv.h"
264 /**************************************************************//**
265 Allocates memory for a persistent cursor object and initializes the cursor.
266 @return own: persistent cursor */
267@@ -102,6 +102,12 @@
268 ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
269
270 block = btr_pcur_get_block(cursor);
271+
272+ if (srv_pass_corrupt_table && !block) {
273+ return;
274+ }
275+ ut_a(block);
276+
277 index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
278
279 page_cursor = btr_pcur_get_page_cur(cursor);
734d6226
AM
280@@ -395,6 +401,15 @@
281 cursor->latch_mode,
282 btr_pcur_get_btr_cur(cursor)->index, mtr);
b4e1fa2c
AM
283 next_page = buf_block_get_frame(next_block);
284+
285+ if (srv_pass_corrupt_table && !next_page) {
286+ btr_leaf_page_release(btr_pcur_get_block(cursor),
287+ cursor->latch_mode, mtr);
288+ btr_pcur_get_page_cur(cursor)->block = 0;
289+ btr_pcur_get_page_cur(cursor)->rec = 0;
290+ return;
291+ }
292+ ut_a(next_page);
293 #ifdef UNIV_BTR_DEBUG
294 ut_a(page_is_comp(next_page) == page_is_comp(page));
295 ut_a(btr_page_get_prev(next_page, mtr)
db82db79
AM
296--- a/storage/innobase/btr/btr0sea.c
297+++ b/storage/innobase/btr/btr0sea.c
b4e1fa2c
AM
298@@ -42,7 +42,7 @@
299 #include "btr0pcur.h"
300 #include "btr0btr.h"
301 #include "ha0ha.h"
302-
303+#include "srv0srv.h"
304 /** Flag: has the search system been enabled?
305 Protected by btr_search_latch and btr_search_enabled_mutex. */
306 UNIV_INTERN char btr_search_enabled = TRUE;
307@@ -607,6 +607,11 @@
308
309 block = btr_cur_get_block(cursor);
310
311+ if (srv_pass_corrupt_table && !block) {
312+ return;
313+ }
314+ ut_a(block);
315+
316 /* NOTE that the following two function calls do NOT protect
317 info or block->n_fields etc. with any semaphore, to save CPU time!
318 We cannot assume the fields are consistent when we return from
db82db79
AM
319--- a/storage/innobase/buf/buf0buf.c
320+++ b/storage/innobase/buf/buf0buf.c
b4e1fa2c
AM
321@@ -52,6 +52,7 @@
322 #include "log0recv.h"
323 #include "page0zip.h"
324 #include "trx0trx.h"
325+#include "srv0start.h"
326
327 /* prototypes for new functions added to ha_innodb.cc */
328 trx_t* innobase_get_trx();
734d6226 329@@ -1136,6 +1137,11 @@
b4e1fa2c
AM
330 ready = buf_flush_ready_for_replace(&block->page);
331 mutex_exit(&block->mutex);
332
333+ if (block->page.is_corrupt) {
334+ /* corrupt page may remain, it can be skipped */
335+ break;
336+ }
337+
338 if (!ready) {
339
340 return(block);
734d6226 341@@ -2007,6 +2013,13 @@
b4e1fa2c
AM
342 return(NULL);
343 }
344
adf0fb13 345+ if (srv_pass_corrupt_table <= 1) {
b4e1fa2c
AM
346+ if (bpage->is_corrupt) {
347+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
348+ return(NULL);
349+ }
350+ }
b4e1fa2c
AM
351+
352 block_mutex = buf_page_get_mutex_enter(bpage);
353
354 rw_lock_s_unlock(&buf_pool->page_hash_latch);
734d6226 355@@ -2587,6 +2600,13 @@
b4e1fa2c
AM
356 return(NULL);
357 }
358
adf0fb13 359+ if (srv_pass_corrupt_table <= 1) {
b4e1fa2c
AM
360+ if (block->page.is_corrupt) {
361+ mutex_exit(block_mutex);
362+ return(NULL);
363+ }
364+ }
b4e1fa2c
AM
365+
366 switch (buf_block_get_state(block)) {
367 buf_page_t* bpage;
368 ibool success;
734d6226 369@@ -3261,6 +3281,7 @@
b4e1fa2c
AM
370 bpage->newest_modification = 0;
371 bpage->oldest_modification = 0;
372 HASH_INVALIDATE(bpage, hash);
373+ bpage->is_corrupt = FALSE;
df1b5770 374 #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
b4e1fa2c 375 bpage->file_page_was_freed = FALSE;
df1b5770 376 #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
734d6226 377@@ -3899,6 +3920,7 @@
b4e1fa2c
AM
378 (ulong) bpage->offset);
379 }
380
381+ if (!srv_pass_corrupt_table || !bpage->is_corrupt) {
382 /* From version 3.23.38 up we store the page checksum
383 to the 4 first bytes of the page end lsn field */
384
734d6226 385@@ -3940,6 +3962,23 @@
d8778560 386 REFMAN "forcing-innodb-recovery.html\n"
b4e1fa2c
AM
387 "InnoDB: about forcing recovery.\n", stderr);
388
389+ if (srv_pass_corrupt_table && !trx_sys_sys_space(bpage->space)
390+ && bpage->space < SRV_LOG_SPACE_FIRST_ID) {
adf0fb13
AM
391+ trx_t* trx;
392+
b4e1fa2c
AM
393+ fprintf(stderr,
394+ "InnoDB: space %u will be treated as corrupt.\n",
395+ bpage->space);
396+ fil_space_set_corrupt(bpage->space);
adf0fb13
AM
397+
398+ trx = innobase_get_trx();
399+ if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) {
b4e1fa2c 400+ dict_table_set_corrupt_by_space(bpage->space, FALSE);
adf0fb13
AM
401+ } else {
402+ dict_table_set_corrupt_by_space(bpage->space, TRUE);
b4e1fa2c
AM
403+ }
404+ bpage->is_corrupt = TRUE;
405+ } else
406 if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
734d6226
AM
407 /* If page space id is larger than TRX_SYS_SPACE
408 (0), we will attempt to mark the corresponding
409@@ -3956,6 +3995,7 @@
410 }
b4e1fa2c
AM
411 }
412 }
413+ } /**/
414
415 if (recv_recovery_is_on()) {
416 /* Pages must be uncompressed for crash recovery. */
734d6226 417@@ -3965,8 +4005,11 @@
b4e1fa2c
AM
418
419 if (uncompressed && !recv_no_ibuf_operations) {
420 ibuf_merge_or_delete_for_page(
421+ /* Delete possible entries, if bpage is_corrupt */
422+ (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL :
423 (buf_block_t*) bpage, bpage->space,
424 bpage->offset, buf_page_get_zip_size(bpage),
425+ (srv_pass_corrupt_table && bpage->is_corrupt) ? FALSE :
426 TRUE);
427 }
428 }
db82db79
AM
429--- a/storage/innobase/buf/buf0rea.c
430+++ b/storage/innobase/buf/buf0rea.c
734d6226 431@@ -195,7 +195,14 @@
b4e1fa2c
AM
432 ((buf_block_t*) bpage)->frame, bpage, trx);
433 }
434 thd_wait_end(NULL);
435+
436+ if (srv_pass_corrupt_table) {
437+ if (*err != DB_SUCCESS) {
438+ bpage->is_corrupt = TRUE;
439+ }
440+ } else {
441 ut_a(*err == DB_SUCCESS);
442+ }
443
444 if (sync) {
445 /* The i/o is already completed when we arrive from
db82db79
AM
446--- a/storage/innobase/dict/dict0dict.c
447+++ b/storage/innobase/dict/dict0dict.c
734d6226 448@@ -55,6 +55,7 @@
b4e1fa2c 449 #include "m_ctype.h" /* my_isspace() */
d8778560 450 #include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
734d6226 451 #include "row0upd.h"
b4e1fa2c
AM
452+#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
453
454 #include <ctype.h>
455
adf0fb13 456@@ -750,7 +751,7 @@
b4e1fa2c
AM
457
458 mutex_exit(&(dict_sys->mutex));
459
460- if (table != NULL) {
461+ if (table != NULL && !table->is_corrupt) {
462 /* If table->ibd_file_missing == TRUE, this will
463 print an error message and return without doing
464 anything. */
adf0fb13 465@@ -1293,7 +1294,7 @@
b4e1fa2c
AM
466 + dict_sys->size) > srv_dict_size_limit ) {
467 prev_table = UT_LIST_GET_PREV(table_LRU, table);
468
469- if (table == self || table->n_mysql_handles_opened)
470+ if (table == self || table->n_mysql_handles_opened || table->is_corrupt)
471 goto next_loop;
472
473 cached_foreign_tables = 0;
734d6226 474@@ -4367,6 +4368,12 @@
b4e1fa2c
AM
475 heap = mem_heap_create(1000);
476
477 while (index) {
478+ if (table->is_corrupt) {
479+ ut_a(srv_pass_corrupt_table);
480+ mem_heap_free(heap);
481+ return(FALSE);
482+ }
483+
484 size = btr_get_size(index, BTR_TOTAL_SIZE);
485
486 index->stat_index_size = size;
734d6226 487@@ -4514,6 +4521,12 @@
b4e1fa2c
AM
488 heap = mem_heap_create(1000);
489
490 while (index) {
491+ if (table->is_corrupt) {
492+ ut_a(srv_pass_corrupt_table);
493+ mem_heap_free(heap);
494+ return;
495+ }
496+
497 /*===========================================*/
498 {
499 dict_table_t* sys_stats;
734d6226 500@@ -4706,6 +4719,13 @@
b4e1fa2c
AM
501 || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
502 && dict_index_is_clust(index)))) {
503 ulint size;
504+
505+ if (table->is_corrupt) {
506+ ut_a(srv_pass_corrupt_table);
adf0fb13 507+ dict_table_stats_unlock(table, RW_X_LATCH);
b4e1fa2c
AM
508+ return;
509+ }
510+
511 size = btr_get_size(index, BTR_TOTAL_SIZE);
512
513 index->stat_index_size = size;
734d6226
AM
514@@ -5685,4 +5705,42 @@
515
516 index->type |= DICT_CORRUPT;
b4e1fa2c
AM
517 }
518+
519+/*************************************************************************
520+set is_corrupt flag by space_id*/
521+
522+void
523+dict_table_set_corrupt_by_space(
524+/*============================*/
525+ ulint space_id,
526+ ibool need_mutex)
527+{
528+ dict_table_t* table;
529+ ibool found = FALSE;
530+
531+ ut_a(!trx_sys_sys_space(space_id) && space_id < SRV_LOG_SPACE_FIRST_ID);
532+
533+ if (need_mutex)
534+ mutex_enter(&(dict_sys->mutex));
535+
536+ table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
537+
538+ while (table) {
539+ if (table->space == space_id) {
540+ table->is_corrupt = TRUE;
541+ found = TRUE;
542+ }
543+
544+ table = UT_LIST_GET_NEXT(table_LRU, table);
545+ }
546+
547+ if (need_mutex)
548+ mutex_exit(&(dict_sys->mutex));
549+
550+ if (!found) {
551+ fprintf(stderr, "InnoDB: space to be marked as "
552+ "crashed was not found for id %lu.\n",
553+ (ulong) space_id);
554+ }
555+}
556 #endif /* !UNIV_HOTBACKUP */
db82db79
AM
557--- a/storage/innobase/dict/dict0mem.c
558+++ b/storage/innobase/dict/dict0mem.c
adf0fb13 559@@ -96,6 +96,8 @@
b4e1fa2c
AM
560 /* The number of transactions that are either waiting on the
561 AUTOINC lock or have been granted the lock. */
562 table->n_waiting_or_granted_auto_inc_locks = 0;
563+
564+ table->is_corrupt = FALSE;
565 #endif /* !UNIV_HOTBACKUP */
566
567 ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
db82db79
AM
568--- a/storage/innobase/fil/fil0fil.c
569+++ b/storage/innobase/fil/fil0fil.c
adf0fb13 570@@ -235,6 +235,7 @@
b4e1fa2c
AM
571 file we have written to */
572 ibool is_in_unflushed_spaces; /*!< TRUE if this space is
573 currently in unflushed_spaces */
574+ ibool is_corrupt;
575 UT_LIST_NODE_T(fil_space_t) space_list;
576 /*!< list of all spaces */
577 ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
db82db79 578@@ -1294,6 +1295,8 @@
b4e1fa2c
AM
579 ut_fold_string(name), space);
580 space->is_in_unflushed_spaces = FALSE;
581
582+ space->is_corrupt = FALSE;
583+
584 UT_LIST_ADD_LAST(space_list, fil_system->space_list, space);
585
586 mutex_exit(&fil_system->mutex);
db82db79 587@@ -5268,6 +5271,34 @@
b4e1fa2c
AM
588 ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
589 ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
590
adf0fb13 591+ if (srv_pass_corrupt_table == 1 && space->is_corrupt) {
b4e1fa2c
AM
592+ /* should ignore i/o for the crashed space */
593+ mutex_enter(&fil_system->mutex);
594+ fil_node_complete_io(node, fil_system, type);
595+ mutex_exit(&fil_system->mutex);
596+ if (mode == OS_AIO_NORMAL) {
597+ ut_a(space->purpose == FIL_TABLESPACE);
adf0fb13 598+ buf_page_io_complete(message);
b4e1fa2c
AM
599+ }
600+ if (type == OS_FILE_READ) {
601+ return(DB_TABLESPACE_DELETED);
602+ } else {
603+ return(DB_SUCCESS);
604+ }
605+ } else {
adf0fb13
AM
606+ if (srv_pass_corrupt_table > 1 && space->is_corrupt) {
607+ /* should ignore write i/o for the crashed space */
608+ if (type == OS_FILE_WRITE) {
609+ mutex_enter(&fil_system->mutex);
610+ fil_node_complete_io(node, fil_system, type);
611+ mutex_exit(&fil_system->mutex);
612+ if (mode == OS_AIO_NORMAL) {
613+ ut_a(space->purpose == FIL_TABLESPACE);
614+ buf_page_io_complete(message);
615+ }
616+ return(DB_SUCCESS);
617+ }
618+ }
b4e1fa2c
AM
619 #ifdef UNIV_HOTBACKUP
620 /* In ibbackup do normal i/o, not aio */
621 if (type == OS_FILE_READ) {
db82db79 622@@ -5282,6 +5313,8 @@
b4e1fa2c
AM
623 ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
624 offset_low, offset_high, len, node, message, trx);
625 #endif
626+ } /**/
627+
628 ut_a(ret);
629
630 if (mode == OS_AIO_SYNC) {
db82db79 631@@ -5782,3 +5815,46 @@
b4e1fa2c
AM
632 return 0;
633 }
634 }
635+
636+/*************************************************************************
637+functions to access is_corrupt flag of fil_space_t*/
638+
639+ibool
640+fil_space_is_corrupt(
641+/*=================*/
642+ ulint space_id)
643+{
644+ fil_space_t* space;
645+ ibool ret = FALSE;
646+
647+ mutex_enter(&fil_system->mutex);
648+
649+ space = fil_space_get_by_id(space_id);
650+
651+ if (space && space->is_corrupt) {
652+ ret = TRUE;
653+ }
654+
655+ mutex_exit(&fil_system->mutex);
656+
657+ return(ret);
658+}
659+
660+void
661+fil_space_set_corrupt(
662+/*==================*/
663+ ulint space_id)
664+{
665+ fil_space_t* space;
666+
667+ mutex_enter(&fil_system->mutex);
668+
669+ space = fil_space_get_by_id(space_id);
670+
671+ if (space) {
672+ space->is_corrupt = TRUE;
673+ }
674+
675+ mutex_exit(&fil_system->mutex);
676+}
677+
db82db79
AM
678--- a/storage/innobase/fsp/fsp0fsp.c
679+++ b/storage/innobase/fsp/fsp0fsp.c
b4e1fa2c
AM
680@@ -369,6 +369,12 @@
681 ut_ad(id || !zip_size);
682
683 block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr);
684+
685+ if (srv_pass_corrupt_table && !block) {
686+ return(0);
687+ }
688+ ut_a(block);
689+
690 header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
691 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
692
693@@ -787,6 +793,12 @@
694 fsp_header_t* sp_header;
695
696 block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
697+
698+ if (srv_pass_corrupt_table && !block) {
699+ return(0);
700+ }
701+ ut_a(block);
702+
703 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
704
705 sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
706@@ -1866,6 +1878,11 @@
707 {
708 fseg_inode_t* inode;
709
710+ if (srv_pass_corrupt_table && !page) {
711+ return(ULINT_UNDEFINED);
712+ }
713+ ut_a(page);
714+
715 for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
716
717 inode = fsp_seg_inode_page_get_nth_inode(
718@@ -1979,6 +1996,11 @@
719
720 page = buf_block_get_frame(block);
721
722+ if (srv_pass_corrupt_table && !page) {
723+ return(0);
724+ }
725+ ut_a(page);
726+
727 n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr);
728
729 ut_a(n != ULINT_UNDEFINED);
730@@ -2072,6 +2094,11 @@
731
732 inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
733
734+ if (srv_pass_corrupt_table && !inode) {
735+ return(0);
736+ }
737+ ut_a(inode);
738+
739 if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
740
741 inode = NULL;
742@@ -2098,7 +2125,7 @@
743 {
744 fseg_inode_t* inode
745 = fseg_inode_try_get(header, space, zip_size, mtr);
746- ut_a(inode);
747+ ut_a(srv_pass_corrupt_table || inode);
748 return(inode);
749 }
750
751@@ -3304,6 +3331,11 @@
752
753 descr = xdes_get_descriptor(space, zip_size, page, mtr);
754
755+ if (srv_pass_corrupt_table && !descr) {
756+ /* The page may be corrupt. pass it. */
757+ return;
758+ }
759+
760 ut_a(descr);
761 if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
762 fputs("InnoDB: Dump of the tablespace extent descriptor: ",
763@@ -3551,6 +3583,11 @@
764
765 descr = xdes_get_descriptor(space, zip_size, header_page, mtr);
766
767+ if (srv_pass_corrupt_table && !descr) {
768+ /* The page may be corrupt. pass it. */
769+ return(TRUE);
770+ }
771+
772 /* Check that the header resides on a page which has not been
773 freed yet */
774
775@@ -3635,6 +3672,12 @@
776
777 inode = fseg_inode_get(header, space, zip_size, mtr);
778
779+ if (srv_pass_corrupt_table && !inode) {
780+ /* ignore the corruption */
781+ return(TRUE);
782+ }
783+ ut_a(inode);
784+
785 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
786
787 if (descr != NULL) {
db82db79
AM
788--- a/storage/innobase/handler/ha_innodb.cc
789+++ b/storage/innobase/handler/ha_innodb.cc
734d6226 790@@ -4012,6 +4012,12 @@
b4e1fa2c
AM
791 DBUG_RETURN(1);
792 }
793
adf0fb13 794+ if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) {
b4e1fa2c
AM
795+ free_share(share);
796+
797+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
798+ }
799+
800 /* Create buffers for packing the fields of a record. Why
801 table->reclength did not work here? Obviously, because char
802 fields when packed actually became 1 byte longer, when we also
734d6226 803@@ -4039,6 +4045,19 @@
b4e1fa2c
AM
804 /* Get pointer to a table object in InnoDB dictionary cache */
805 ib_table = dict_table_get(norm_name, TRUE);
806
adf0fb13 807+ if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
b4e1fa2c
AM
808+ free_share(share);
809+ my_free(upd_buff);
810+
811+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
812+ }
813+
734d6226
AM
814+ share->ib_table = ib_table;
815+
816+
817+
818+
b4e1fa2c
AM
819+
820 if (NULL == ib_table) {
821 if (is_part && retries < 10) {
822 ++retries;
734d6226 823@@ -5188,6 +5207,10 @@
b4e1fa2c
AM
824
825 ha_statistic_increment(&SSV::ha_write_count);
826
827+ if (share->ib_table->is_corrupt) {
828+ DBUG_RETURN(HA_ERR_CRASHED);
829+ }
830+
831 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
832 table->timestamp_field->set_time();
833
734d6226 834@@ -5405,6 +5428,10 @@
b4e1fa2c
AM
835 func_exit:
836 innobase_active_small();
837
838+ if (share->ib_table->is_corrupt) {
839+ DBUG_RETURN(HA_ERR_CRASHED);
840+ }
841+
842 DBUG_RETURN(error_result);
843 }
844
734d6226 845@@ -5581,6 +5608,10 @@
b4e1fa2c
AM
846
847 ha_statistic_increment(&SSV::ha_update_count);
848
849+ if (share->ib_table->is_corrupt) {
850+ DBUG_RETURN(HA_ERR_CRASHED);
851+ }
852+
853 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
854 table->timestamp_field->set_time();
855
734d6226 856@@ -5670,6 +5701,10 @@
b4e1fa2c
AM
857
858 innobase_active_small();
859
860+ if (share->ib_table->is_corrupt) {
861+ DBUG_RETURN(HA_ERR_CRASHED);
862+ }
863+
864 DBUG_RETURN(error);
865 }
866
734d6226 867@@ -5691,6 +5726,10 @@
b4e1fa2c
AM
868
869 ha_statistic_increment(&SSV::ha_delete_count);
870
871+ if (share->ib_table->is_corrupt) {
872+ DBUG_RETURN(HA_ERR_CRASHED);
873+ }
874+
875 if (!prebuilt->upd_node) {
876 row_get_prebuilt_update_vector(prebuilt);
877 }
734d6226 878@@ -5717,6 +5756,10 @@
b4e1fa2c
AM
879
880 innobase_active_small();
881
882+ if (share->ib_table->is_corrupt) {
883+ DBUG_RETURN(HA_ERR_CRASHED);
884+ }
885+
886 DBUG_RETURN(error);
887 }
888
734d6226 889@@ -5956,6 +5999,10 @@
b4e1fa2c
AM
890
891 ha_statistic_increment(&SSV::ha_read_key_count);
892
adf0fb13 893+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
894+ DBUG_RETURN(HA_ERR_CRASHED);
895+ }
896+
897 index = prebuilt->index;
898
734d6226
AM
899 if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
900@@ -6023,6 +6070,10 @@
b4e1fa2c
AM
901 ret = DB_UNSUPPORTED;
902 }
903
adf0fb13 904+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
905+ DBUG_RETURN(HA_ERR_CRASHED);
906+ }
907+
908 switch (ret) {
909 case DB_SUCCESS:
910 error = 0;
734d6226 911@@ -6138,6 +6189,10 @@
b4e1fa2c
AM
912 {
913 DBUG_ENTER("change_active_index");
914
adf0fb13 915+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
916+ DBUG_RETURN(HA_ERR_CRASHED);
917+ }
918+
919 ut_ad(user_thd == ha_thd());
920 ut_a(prebuilt->trx == thd_to_trx(user_thd));
921
734d6226 922@@ -6251,6 +6306,10 @@
b4e1fa2c
AM
923
924 DBUG_ENTER("general_fetch");
925
adf0fb13 926+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
927+ DBUG_RETURN(HA_ERR_CRASHED);
928+ }
929+
930 ut_a(prebuilt->trx == thd_to_trx(user_thd));
931
932 innodb_srv_conc_enter_innodb(prebuilt->trx);
734d6226 933@@ -6260,6 +6319,10 @@
b4e1fa2c
AM
934
935 innodb_srv_conc_exit_innodb(prebuilt->trx);
936
adf0fb13 937+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
938+ DBUG_RETURN(HA_ERR_CRASHED);
939+ }
940+
941 switch (ret) {
942 case DB_SUCCESS:
943 error = 0;
734d6226 944@@ -7526,10 +7589,18 @@
b4e1fa2c
AM
945
946 update_thd(ha_thd());
947
948+ if (share->ib_table->is_corrupt) {
949+ DBUG_RETURN(HA_ERR_CRASHED);
950+ }
951+
952 /* Truncate the table in InnoDB */
953
954 error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
955
956+ if (share->ib_table->is_corrupt) {
957+ DBUG_RETURN(HA_ERR_CRASHED);
958+ }
959+
960 error = convert_error_code_to_mysql(error, prebuilt->table->flags,
961 NULL);
962
734d6226 963@@ -8034,6 +8105,16 @@
b4e1fa2c
AM
964 return(ranges + (double) rows / (double) total_rows * time_for_scan);
965 }
966
967+UNIV_INTERN
968+bool
969+ha_innobase::is_corrupt() const
970+{
971+ if (share->ib_table)
972+ return ((bool)share->ib_table->is_corrupt);
973+ else
974+ return (FALSE);
975+}
976+
977 /*********************************************************************//**
978 Calculates the key number used inside MySQL for an Innobase index. We will
979 first check the "index translation table" for a match of the index to get
734d6226 980@@ -8211,7 +8292,7 @@
b4e1fa2c
AM
981 ib_table = prebuilt->table;
982
983 if (flag & HA_STATUS_TIME) {
984- if (called_from_analyze || innobase_stats_on_metadata) {
985+ if ((called_from_analyze || innobase_stats_on_metadata) && !share->ib_table->is_corrupt) {
986 /* In sql_show we call with this flag: update
987 then statistics so that they are up-to-date */
988
734d6226 989@@ -8511,10 +8592,18 @@
b4e1fa2c
AM
990 THD* thd, /*!< in: connection thread handle */
991 HA_CHECK_OPT* check_opt) /*!< in: currently ignored */
992 {
993+ if (share->ib_table->is_corrupt) {
994+ return(HA_ADMIN_CORRUPT);
995+ }
996+
997 /* Simply call ::info() with all the flags */
998 info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
999 true /* called from analyze */);
1000
1001+ if (share->ib_table->is_corrupt) {
1002+ return(HA_ADMIN_CORRUPT);
1003+ }
1004+
1005 return(0);
1006 }
1007
734d6226 1008@@ -8747,6 +8836,10 @@
b4e1fa2c
AM
1009 my_error(ER_QUERY_INTERRUPTED, MYF(0));
1010 }
1011
1012+ if (share->ib_table->is_corrupt) {
1013+ return(HA_ADMIN_CORRUPT);
1014+ }
1015+
1016 DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
1017 }
1018
734d6226 1019@@ -9517,6 +9610,10 @@
b4e1fa2c
AM
1020
1021 update_thd(thd);
1022
1023+ if (share->ib_table->is_corrupt) {
1024+ DBUG_RETURN(HA_ERR_CRASHED);
1025+ }
1026+
1027 if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
1028 ut_print_timestamp(stderr);
1029 fprintf(stderr,
734d6226
AM
1030@@ -11941,6 +12038,26 @@
1031 "dump file (if present). Disabled by default.",
1032 NULL, NULL, FALSE);
b4e1fa2c 1033
a9ee80b9
ER
1034+const char *corrupt_table_action_names[]=
1035+{
1036+ "assert", /* 0 */
1037+ "warn", /* 1 */
adf0fb13 1038+ "salvage", /* 2 */
a9ee80b9
ER
1039+ NullS
1040+};
1041+TYPELIB corrupt_table_action_typelib=
1042+{
1043+ array_elements(corrupt_table_action_names) - 1, "corrupt_table_action_typelib",
1044+ corrupt_table_action_names, NULL
1045+};
1046+static MYSQL_SYSVAR_ENUM(corrupt_table_action, srv_pass_corrupt_table,
b4e1fa2c 1047+ PLUGIN_VAR_RQCMDARG,
a9ee80b9 1048+ "Warn corruptions of user tables as 'corrupt table' instead of not crashing itself, "
b4e1fa2c
AM
1049+ "when used with file_per_table. "
1050+ "All file io for the datafile after detected as corrupt are disabled, "
1051+ "except for the deletion.",
a9ee80b9 1052+ NULL, NULL, 0, &corrupt_table_action_typelib);
b4e1fa2c
AM
1053+
1054 static struct st_mysql_sys_var* innobase_system_variables[]= {
1055 MYSQL_SYSVAR(additional_mem_pool_size),
1056 MYSQL_SYSVAR(autoextend_increment),
734d6226 1057@@ -12031,6 +12148,7 @@
b4e1fa2c
AM
1058 MYSQL_SYSVAR(purge_threads),
1059 MYSQL_SYSVAR(purge_batch_size),
11822e22 1060 MYSQL_SYSVAR(rollback_segments),
a9ee80b9 1061+ MYSQL_SYSVAR(corrupt_table_action),
b4e1fa2c
AM
1062 NULL
1063 };
1064
db82db79
AM
1065--- a/storage/innobase/handler/ha_innodb.h
1066+++ b/storage/innobase/handler/ha_innodb.h
b4e1fa2c
AM
1067@@ -52,6 +52,7 @@
1068 innodb_idx_translate_t idx_trans_tbl; /*!< index translation
1069 table between MySQL and
1070 Innodb */
1071+ dict_table_t* ib_table;
1072 } INNOBASE_SHARE;
1073
1074
1075@@ -135,6 +136,7 @@
1076 int close(void);
1077 double scan_time();
1078 double read_time(uint index, uint ranges, ha_rows rows);
1079+ bool is_corrupt() const;
1080
1081 int write_row(uchar * buf);
1082 int update_row(const uchar * old_data, uchar * new_data);
db82db79
AM
1083--- a/storage/innobase/include/btr0btr.ic
1084+++ b/storage/innobase/include/btr0btr.ic
b4e1fa2c
AM
1085@@ -28,7 +28,7 @@
1086 #include "mtr0mtr.h"
1087 #include "mtr0log.h"
1088 #include "page0zip.h"
1089-
1090+#include "srv0srv.h"
1091 #define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level
1092 (not really a hard limit).
1093 Used in debug assertions
734d6226 1094@@ -59,7 +59,9 @@
b4e1fa2c
AM
1095 block = buf_page_get_gen(space, zip_size, page_no, mode,
1096 NULL, BUF_GET, file, line, mtr);
1097
1098- if (mode != RW_NO_LATCH) {
1099+ ut_a(srv_pass_corrupt_table || block);
1100+
1101+ if (block && mode != RW_NO_LATCH) {
1102
734d6226
AM
1103 buf_block_dbg_add_level(
1104 block, index != NULL && dict_index_is_ibuf(index)
db82db79
AM
1105--- a/storage/innobase/include/buf0buf.h
1106+++ b/storage/innobase/include/buf0buf.h
734d6226 1107@@ -1016,7 +1016,7 @@
b4e1fa2c
AM
1108 const buf_block_t* block) /*!< in: pointer to the control block */
1109 __attribute__((pure));
1110 #else /* UNIV_DEBUG */
1111-# define buf_block_get_frame(block) (block)->frame
1112+# define buf_block_get_frame(block) (block ? (block)->frame : 0)
1113 #endif /* UNIV_DEBUG */
1114 /*********************************************************************//**
1115 Gets the space id of a block.
734d6226 1116@@ -1463,6 +1463,7 @@
b4e1fa2c
AM
1117 0 if the block was never accessed
1118 in the buffer pool */
1119 /* @} */
1120+ ibool is_corrupt;
df1b5770 1121 # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
b4e1fa2c
AM
1122 ibool file_page_was_freed;
1123 /*!< this is set to TRUE when fsp
db82db79
AM
1124--- a/storage/innobase/include/buf0buf.ic
1125+++ b/storage/innobase/include/buf0buf.ic
b4e1fa2c
AM
1126@@ -34,7 +34,7 @@
1127 #include "buf0flu.h"
1128 #include "buf0lru.h"
1129 #include "buf0rea.h"
1130-
1131+#include "srv0srv.h"
1132 /*********************************************************************//**
1133 Gets the current size of buffer buf_pool in bytes.
1134 @return size in bytes */
734d6226 1135@@ -637,6 +637,12 @@
b4e1fa2c
AM
1136 /*================*/
1137 const buf_block_t* block) /*!< in: pointer to the control block */
1138 {
1139+ ut_a(srv_pass_corrupt_table || block);
1140+
1141+ if (srv_pass_corrupt_table && !block) {
1142+ return(0);
1143+ }
1144+
1145 ut_ad(block);
1146
1147 switch (buf_block_get_state(block)) {
db82db79
AM
1148--- a/storage/innobase/include/dict0dict.h
1149+++ b/storage/innobase/include/dict0dict.h
734d6226
AM
1150@@ -1326,6 +1326,15 @@
1151 /*========================*/
1152 ulint space_id); /*!< in: space ID */
b4e1fa2c
AM
1153
1154+/*************************************************************************
1155+set is_corrupt flag by space_id*/
1156+
1157+void
1158+dict_table_set_corrupt_by_space(
1159+/*============================*/
1160+ ulint space_id,
1161+ ibool need_mutex);
1162+
1163 #ifndef UNIV_NONINL
1164 #include "dict0dict.ic"
1165 #endif
db82db79
AM
1166--- a/storage/innobase/include/dict0mem.h
1167+++ b/storage/innobase/include/dict0mem.h
734d6226 1168@@ -670,6 +670,7 @@
b4e1fa2c
AM
1169 the AUTOINC lock on this table. */
1170 /* @} */
1171 /*----------------------*/
1172+ ibool is_corrupt;
1173 #endif /* !UNIV_HOTBACKUP */
1174
1175 #ifdef UNIV_DEBUG
db82db79
AM
1176--- a/storage/innobase/include/fil0fil.h
1177+++ b/storage/innobase/include/fil0fil.h
413cadc7 1178@@ -750,6 +750,19 @@
b4e1fa2c
AM
1179 fil_system_hash_nodes(void);
1180 /*========================*/
1181
1182+/*************************************************************************
1183+functions to access is_corrupt flag of fil_space_t*/
1184+
1185+ibool
1186+fil_space_is_corrupt(
1187+/*=================*/
1188+ ulint space_id);
1189+
1190+void
1191+fil_space_set_corrupt(
1192+/*==================*/
1193+ ulint space_id);
1194+
1195 typedef struct fil_space_struct fil_space_t;
1196
1197 #endif
db82db79
AM
1198--- a/storage/innobase/include/fut0fut.ic
1199+++ b/storage/innobase/include/fut0fut.ic
b4e1fa2c
AM
1200@@ -23,6 +23,7 @@
1201 Created 12/13/1995 Heikki Tuuri
1202 ***********************************************************************/
1203
1204+#include "srv0srv.h"
1205 #include "sync0rw.h"
1206 #include "buf0buf.h"
1207
1208@@ -48,6 +49,12 @@
1209 ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
1210
1211 block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr);
1212+
1213+ if (srv_pass_corrupt_table && !block) {
1214+ return(0);
1215+ }
1216+ ut_a(block);
1217+
1218 ptr = buf_block_get_frame(block) + addr.boffset;
1219
1220 buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
db82db79
AM
1221--- a/storage/innobase/include/page0page.h
1222+++ b/storage/innobase/include/page0page.h
734d6226 1223@@ -497,7 +497,7 @@
b4e1fa2c
AM
1224 page_is_leaf(
1225 /*=========*/
1226 const page_t* page) /*!< in: page */
1227- __attribute__((nonnull, pure));
1228+ __attribute__((pure));
1229 /************************************************************//**
1230 Gets the pointer to the next record on the page.
1231 @return pointer to next record */
db82db79
AM
1232--- a/storage/innobase/include/page0page.ic
1233+++ b/storage/innobase/include/page0page.ic
b4e1fa2c
AM
1234@@ -274,6 +274,9 @@
1235 /*=========*/
1236 const page_t* page) /*!< in: page */
1237 {
1238+ if (!page) {
1239+ return(FALSE);
1240+ }
1241 return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL)));
1242 }
1243
db82db79
AM
1244--- a/storage/innobase/include/page0zip.h
1245+++ b/storage/innobase/include/page0zip.h
b4e1fa2c
AM
1246@@ -114,7 +114,7 @@
1247 const page_t* page, /*!< in: uncompressed page */
1248 dict_index_t* index, /*!< in: index of the B-tree node */
1249 mtr_t* mtr) /*!< in: mini-transaction, or NULL */
1250- __attribute__((nonnull(1,2,3)));
1251+ __attribute__((nonnull(1,3)));
1252
1253 /**********************************************************************//**
1254 Decompress a page. This function should tolerate errors on the compressed
db82db79
AM
1255--- a/storage/innobase/include/srv0srv.h
1256+++ b/storage/innobase/include/srv0srv.h
734d6226 1257@@ -245,6 +245,7 @@
b4e1fa2c
AM
1258 extern ulint srv_adaptive_flushing_method;
1259
1260 extern ulint srv_expand_import;
1261+extern ulint srv_pass_corrupt_table;
1262
b4e1fa2c 1263 extern ulint srv_dict_size_limit;
11822e22 1264 /*-------------------------------------------*/
db82db79
AM
1265--- a/storage/innobase/page/page0zip.c
1266+++ b/storage/innobase/page/page0zip.c
1267@@ -1195,6 +1195,10 @@
b4e1fa2c
AM
1268 FILE* logfile = NULL;
1269 #endif
1270
1271+ if (!page) {
1272+ return(FALSE);
1273+ }
1274+
1275 ut_a(page_is_comp(page));
1276 ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
1277 ut_ad(page_simple_validate_new((page_t*) page));
db82db79
AM
1278--- a/storage/innobase/row/row0ins.c
1279+++ b/storage/innobase/row/row0ins.c
734d6226 1280@@ -1338,6 +1338,12 @@
b4e1fa2c
AM
1281 const rec_t* rec = btr_pcur_get_rec(&pcur);
1282 const buf_block_t* block = btr_pcur_get_block(&pcur);
1283
1284+ if (srv_pass_corrupt_table && !block) {
1285+ err = DB_CORRUPTION;
1286+ break;
1287+ }
1288+ ut_a(block);
1289+
1290 if (page_rec_is_infimum(rec)) {
1291
1292 continue;
db82db79
AM
1293--- a/storage/innobase/row/row0merge.c
1294+++ b/storage/innobase/row/row0merge.c
b4e1fa2c
AM
1295@@ -1245,6 +1245,13 @@
1296
1297 if (UNIV_LIKELY(has_next)) {
1298 rec = btr_pcur_get_rec(&pcur);
1299+
1300+ if (srv_pass_corrupt_table && !rec) {
1301+ err = DB_CORRUPTION;
1302+ goto err_exit;
1303+ }
1304+ ut_a(rec);
1305+
1306 offsets = rec_get_offsets(rec, clust_index, NULL,
1307 ULINT_UNDEFINED, &row_heap);
1308
db82db79
AM
1309--- a/storage/innobase/row/row0sel.c
1310+++ b/storage/innobase/row/row0sel.c
734d6226 1311@@ -3912,6 +3912,13 @@
b4e1fa2c
AM
1312 /* PHASE 4: Look for matching records in a loop */
1313
1314 rec = btr_pcur_get_rec(pcur);
1315+
1316+ if (srv_pass_corrupt_table && !rec) {
1317+ err = DB_CORRUPTION;
1318+ goto lock_wait_or_error;
1319+ }
1320+ ut_a(rec);
1321+
1322 ut_ad(!!page_rec_is_comp(rec) == comp);
1323 #ifdef UNIV_SEARCH_DEBUG
1324 /*
734d6226 1325@@ -3989,7 +3996,13 @@
adf0fb13
AM
1326 if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
1327
1328 wrong_offs:
1329- if (srv_force_recovery == 0 || moves_up == FALSE) {
1330+ if (srv_pass_corrupt_table && !trx_sys_sys_space(index->table->space)) {
1331+ index->table->is_corrupt = TRUE;
1332+ fil_space_set_corrupt(index->table->space);
1333+ }
1334+
1335+ if ((srv_force_recovery == 0 || moves_up == FALSE)
1336+ && srv_pass_corrupt_table <= 1) {
1337 ut_print_timestamp(stderr);
1338 buf_page_print(page_align(rec), 0);
1339 fprintf(stderr,
734d6226 1340@@ -4040,7 +4053,8 @@
adf0fb13
AM
1341
1342 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1343
1344- if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
1345+ if (UNIV_UNLIKELY(srv_force_recovery > 0)
1346+ || (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) {
1347 if (!rec_validate(rec, offsets)
1348 || !btr_index_rec_validate(rec, index, FALSE)) {
1349 fprintf(stderr,
db82db79
AM
1350--- a/storage/innobase/srv/srv0srv.c
1351+++ b/storage/innobase/srv/srv0srv.c
734d6226 1352@@ -435,6 +435,7 @@
b4e1fa2c
AM
1353 UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
1354
1355 UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
1356+UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
1357
b4e1fa2c 1358 UNIV_INTERN ulint srv_dict_size_limit = 0;
11822e22 1359 /*-------------------------------------------*/
db82db79
AM
1360--- a/storage/innobase/srv/srv0start.c
1361+++ b/storage/innobase/srv/srv0start.c
734d6226 1362@@ -2155,6 +2155,13 @@
b4e1fa2c
AM
1363
1364 os_fast_mutex_free(&srv_os_test_mutex);
1365
1366+ if (!srv_file_per_table_original_value
1367+ && srv_pass_corrupt_table) {
1368+ fprintf(stderr, "InnoDB: Warning:"
d8778560
AM
1369+ " The option innodb_file_per_table is disabled,"
1370+ " so using the option innodb_pass_corrupt_table doesn't make sense.\n");
b4e1fa2c
AM
1371+ }
1372+
1373 if (srv_print_verbose_log) {
1374 ut_print_timestamp(stderr);
1375 fprintf(stderr,
This page took 0.193155 seconds and 4 git commands to generate.