]> git.pld-linux.org Git - packages/percona-server.git/blame - innodb_pass_corrupt_table.patch
- raise error visibility
[packages/percona-server.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
543222d2 10@@ -713,6 +713,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+
543222d2 20 btr_assert_not_corrupted(block, index);
b4e1fa2c 21 #ifdef UNIV_BTR_DEBUG
543222d2
AM
22 if (!dict_index_is_ibuf(index)) {
23@@ -998,6 +1004,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
543222d2 36@@ -1457,6 +1469,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));
543222d2 50@@ -1480,6 +1499,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));
543222d2 63@@ -1513,6 +1538,11 @@
734d6226
AM
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 */
543222d2 149@@ -595,6 +625,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
543222d2 169@@ -669,6 +712,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
543222d2 186@@ -862,6 +915,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;
543222d2 204@@ -982,6 +1046,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) {
543222d2 219@@ -1195,6 +1267,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);
543222d2 232@@ -2927,6 +3005,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);
543222d2 244@@ -3635,6 +3718,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 */
543222d2 267@@ -114,6 +114,12 @@
b4e1fa2c
AM
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);
543222d2 280@@ -409,6 +415,15 @@
734d6226
AM
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?
13ceb006 305 Protected by btr_search_latch. */
b4e1fa2c 306 UNIV_INTERN char btr_search_enabled = TRUE;
13ceb006 307@@ -609,6 +609,11 @@
b4e1fa2c
AM
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();
543222d2 329@@ -1150,6 +1151,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);
543222d2 341@@ -1946,6 +1952,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);
543222d2 355@@ -2525,6 +2538,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;
543222d2 369@@ -3199,6 +3219,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 */
543222d2 377@@ -3837,6 +3858,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
543222d2 385@@ -3878,6 +3900,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
543222d2 409@@ -3894,6 +3933,7 @@
734d6226 410 }
b4e1fa2c
AM
411 }
412 }
413+ } /**/
414
415 if (recv_recovery_is_on()) {
416 /* Pages must be uncompressed for crash recovery. */
543222d2 417@@ -3903,8 +3943,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. */
29ffd636 465@@ -1298,7 +1299,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;
29ffd636 474@@ -4377,6 +4378,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;
29ffd636 487@@ -4524,6 +4531,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;
29ffd636 500@@ -4716,6 +4729,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;
29ffd636 514@@ -5695,4 +5715,42 @@
734d6226
AM
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);
29ffd636 587@@ -5285,6 +5288,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) {
29ffd636 622@@ -5299,6 +5330,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) {
29ffd636 631@@ -5799,3 +5832,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
29ffd636 680@@ -308,6 +308,12 @@
b4e1fa2c
AM
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
29ffd636 693@@ -726,6 +732,12 @@
b4e1fa2c
AM
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);
29ffd636 706@@ -1805,6 +1817,11 @@
b4e1fa2c
AM
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(
29ffd636 718@@ -1918,6 +1935,11 @@
b4e1fa2c
AM
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);
29ffd636 730@@ -2011,6 +2033,11 @@
b4e1fa2c
AM
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;
29ffd636 742@@ -2037,7 +2064,7 @@
b4e1fa2c
AM
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
29ffd636 751@@ -3243,6 +3270,11 @@
b4e1fa2c
AM
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: ",
29ffd636 763@@ -3490,6 +3522,11 @@
b4e1fa2c
AM
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
29ffd636 775@@ -3574,6 +3611,12 @@
b4e1fa2c
AM
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
543222d2 790@@ -4024,6 +4024,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+
543222d2
AM
800 /* Will be allocated if it is needed in ::update_row() */
801 upd_buf = NULL;
802 upd_buf_size = 0;
803@@ -4043,6 +4049,17 @@
b4e1fa2c
AM
804 /* Get pointer to a table object in InnoDB dictionary cache */
805 ib_table = dict_table_get(norm_name, TRUE);
543222d2 806
adf0fb13 807+ if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
b4e1fa2c 808+ free_share(share);
543222d2
AM
809+ my_free(upd_buf);
810+ upd_buf = NULL;
811+ upd_buf_size = 0;
b4e1fa2c
AM
812+
813+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
814+ }
815+
734d6226 816+ share->ib_table = ib_table;
b4e1fa2c
AM
817+
818 if (NULL == ib_table) {
819 if (is_part && retries < 10) {
543222d2
AM
820 /* MySQL partition engine hard codes the file name
821@@ -5263,6 +5280,10 @@
b4e1fa2c
AM
822
823 ha_statistic_increment(&SSV::ha_write_count);
824
825+ if (share->ib_table->is_corrupt) {
826+ DBUG_RETURN(HA_ERR_CRASHED);
827+ }
828+
829 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
830 table->timestamp_field->set_time();
831
543222d2 832@@ -5479,6 +5500,10 @@
b4e1fa2c
AM
833 func_exit:
834 innobase_active_small();
835
836+ if (share->ib_table->is_corrupt) {
837+ DBUG_RETURN(HA_ERR_CRASHED);
838+ }
839+
840 DBUG_RETURN(error_result);
841 }
842
543222d2 843@@ -5673,6 +5698,10 @@
b4e1fa2c
AM
844
845 ha_statistic_increment(&SSV::ha_update_count);
846
847+ if (share->ib_table->is_corrupt) {
848+ DBUG_RETURN(HA_ERR_CRASHED);
849+ }
850+
851 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
852 table->timestamp_field->set_time();
853
543222d2 854@@ -5760,6 +5789,10 @@
b4e1fa2c
AM
855
856 innobase_active_small();
857
858+ if (share->ib_table->is_corrupt) {
859+ DBUG_RETURN(HA_ERR_CRASHED);
860+ }
861+
862 DBUG_RETURN(error);
863 }
864
543222d2 865@@ -5781,6 +5814,10 @@
b4e1fa2c
AM
866
867 ha_statistic_increment(&SSV::ha_delete_count);
868
869+ if (share->ib_table->is_corrupt) {
870+ DBUG_RETURN(HA_ERR_CRASHED);
871+ }
872+
873 if (!prebuilt->upd_node) {
874 row_get_prebuilt_update_vector(prebuilt);
875 }
543222d2 876@@ -5807,6 +5844,10 @@
b4e1fa2c
AM
877
878 innobase_active_small();
879
880+ if (share->ib_table->is_corrupt) {
881+ DBUG_RETURN(HA_ERR_CRASHED);
882+ }
883+
884 DBUG_RETURN(error);
885 }
886
543222d2 887@@ -6046,6 +6087,10 @@
b4e1fa2c
AM
888
889 ha_statistic_increment(&SSV::ha_read_key_count);
890
adf0fb13 891+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
892+ DBUG_RETURN(HA_ERR_CRASHED);
893+ }
894+
895 index = prebuilt->index;
896
734d6226 897 if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
543222d2 898@@ -6113,6 +6158,10 @@
b4e1fa2c
AM
899 ret = DB_UNSUPPORTED;
900 }
901
adf0fb13 902+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
903+ DBUG_RETURN(HA_ERR_CRASHED);
904+ }
905+
906 switch (ret) {
907 case DB_SUCCESS:
908 error = 0;
543222d2 909@@ -6227,6 +6276,10 @@
b4e1fa2c
AM
910 {
911 DBUG_ENTER("change_active_index");
912
adf0fb13 913+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
914+ DBUG_RETURN(HA_ERR_CRASHED);
915+ }
916+
917 ut_ad(user_thd == ha_thd());
918 ut_a(prebuilt->trx == thd_to_trx(user_thd));
919
543222d2 920@@ -6340,6 +6393,10 @@
b4e1fa2c
AM
921
922 DBUG_ENTER("general_fetch");
923
adf0fb13 924+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
925+ DBUG_RETURN(HA_ERR_CRASHED);
926+ }
927+
928 ut_a(prebuilt->trx == thd_to_trx(user_thd));
929
930 innodb_srv_conc_enter_innodb(prebuilt->trx);
543222d2 931@@ -6349,6 +6406,10 @@
b4e1fa2c
AM
932
933 innodb_srv_conc_exit_innodb(prebuilt->trx);
934
adf0fb13 935+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
936+ DBUG_RETURN(HA_ERR_CRASHED);
937+ }
938+
939 switch (ret) {
940 case DB_SUCCESS:
941 error = 0;
543222d2 942@@ -7615,10 +7676,18 @@
b4e1fa2c
AM
943
944 update_thd(ha_thd());
945
946+ if (share->ib_table->is_corrupt) {
947+ DBUG_RETURN(HA_ERR_CRASHED);
948+ }
949+
950 /* Truncate the table in InnoDB */
951
952 error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
953
954+ if (share->ib_table->is_corrupt) {
955+ DBUG_RETURN(HA_ERR_CRASHED);
956+ }
957+
958 error = convert_error_code_to_mysql(error, prebuilt->table->flags,
959 NULL);
960
543222d2 961@@ -8124,6 +8193,16 @@
b4e1fa2c
AM
962 return(ranges + (double) rows / (double) total_rows * time_for_scan);
963 }
964
965+UNIV_INTERN
966+bool
967+ha_innobase::is_corrupt() const
968+{
969+ if (share->ib_table)
970+ return ((bool)share->ib_table->is_corrupt);
971+ else
972+ return (FALSE);
973+}
974+
975 /*********************************************************************//**
976 Calculates the key number used inside MySQL for an Innobase index. We will
977 first check the "index translation table" for a match of the index to get
543222d2 978@@ -8301,7 +8380,7 @@
b4e1fa2c
AM
979 ib_table = prebuilt->table;
980
981 if (flag & HA_STATUS_TIME) {
982- if (called_from_analyze || innobase_stats_on_metadata) {
983+ if ((called_from_analyze || innobase_stats_on_metadata) && !share->ib_table->is_corrupt) {
984 /* In sql_show we call with this flag: update
985 then statistics so that they are up-to-date */
986
543222d2 987@@ -8601,10 +8680,18 @@
b4e1fa2c
AM
988 THD* thd, /*!< in: connection thread handle */
989 HA_CHECK_OPT* check_opt) /*!< in: currently ignored */
990 {
991+ if (share->ib_table->is_corrupt) {
992+ return(HA_ADMIN_CORRUPT);
993+ }
994+
995 /* Simply call ::info() with all the flags */
996 info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
997 true /* called from analyze */);
998
999+ if (share->ib_table->is_corrupt) {
1000+ return(HA_ADMIN_CORRUPT);
1001+ }
1002+
1003 return(0);
1004 }
1005
543222d2 1006@@ -8840,6 +8927,10 @@
b4e1fa2c
AM
1007 my_error(ER_QUERY_INTERRUPTED, MYF(0));
1008 }
1009
1010+ if (share->ib_table->is_corrupt) {
1011+ return(HA_ADMIN_CORRUPT);
1012+ }
1013+
1014 DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
1015 }
1016
543222d2 1017@@ -9610,6 +9701,10 @@
b4e1fa2c
AM
1018
1019 update_thd(thd);
1020
1021+ if (share->ib_table->is_corrupt) {
1022+ DBUG_RETURN(HA_ERR_CRASHED);
1023+ }
1024+
1025 if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
1026 ut_print_timestamp(stderr);
1027 fprintf(stderr,
543222d2 1028@@ -12073,6 +12168,26 @@
734d6226
AM
1029 "dump file (if present). Disabled by default.",
1030 NULL, NULL, FALSE);
b4e1fa2c 1031
a9ee80b9
ER
1032+const char *corrupt_table_action_names[]=
1033+{
1034+ "assert", /* 0 */
1035+ "warn", /* 1 */
adf0fb13 1036+ "salvage", /* 2 */
a9ee80b9
ER
1037+ NullS
1038+};
1039+TYPELIB corrupt_table_action_typelib=
1040+{
1041+ array_elements(corrupt_table_action_names) - 1, "corrupt_table_action_typelib",
1042+ corrupt_table_action_names, NULL
1043+};
1044+static MYSQL_SYSVAR_ENUM(corrupt_table_action, srv_pass_corrupt_table,
b4e1fa2c 1045+ PLUGIN_VAR_RQCMDARG,
a9ee80b9 1046+ "Warn corruptions of user tables as 'corrupt table' instead of not crashing itself, "
b4e1fa2c
AM
1047+ "when used with file_per_table. "
1048+ "All file io for the datafile after detected as corrupt are disabled, "
1049+ "except for the deletion.",
a9ee80b9 1050+ NULL, NULL, 0, &corrupt_table_action_typelib);
b4e1fa2c
AM
1051+
1052 static struct st_mysql_sys_var* innobase_system_variables[]= {
1053 MYSQL_SYSVAR(additional_mem_pool_size),
1054 MYSQL_SYSVAR(autoextend_increment),
543222d2 1055@@ -12166,6 +12281,7 @@
1bfc1981 1056 #ifdef UNIV_DEBUG
543222d2
AM
1057 MYSQL_SYSVAR(trx_rseg_n_slots_debug),
1058 #endif /* UNIV_DEBUG */
a9ee80b9 1059+ MYSQL_SYSVAR(corrupt_table_action),
b4e1fa2c
AM
1060 NULL
1061 };
1062
db82db79
AM
1063--- a/storage/innobase/handler/ha_innodb.h
1064+++ b/storage/innobase/handler/ha_innodb.h
b4e1fa2c
AM
1065@@ -52,6 +52,7 @@
1066 innodb_idx_translate_t idx_trans_tbl; /*!< index translation
1067 table between MySQL and
1068 Innodb */
1069+ dict_table_t* ib_table;
1070 } INNOBASE_SHARE;
1071
1072
543222d2 1073@@ -136,6 +137,7 @@
b4e1fa2c
AM
1074 int close(void);
1075 double scan_time();
1076 double read_time(uint index, uint ranges, ha_rows rows);
1077+ bool is_corrupt() const;
1078
1079 int write_row(uchar * buf);
1080 int update_row(const uchar * old_data, uchar * new_data);
db82db79
AM
1081--- a/storage/innobase/include/btr0btr.ic
1082+++ b/storage/innobase/include/btr0btr.ic
b4e1fa2c
AM
1083@@ -28,7 +28,7 @@
1084 #include "mtr0mtr.h"
1085 #include "mtr0log.h"
1086 #include "page0zip.h"
1087-
1088+#include "srv0srv.h"
1089 #define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level
1090 (not really a hard limit).
1091 Used in debug assertions
734d6226 1092@@ -59,7 +59,9 @@
b4e1fa2c
AM
1093 block = buf_page_get_gen(space, zip_size, page_no, mode,
1094 NULL, BUF_GET, file, line, mtr);
1095
1096- if (mode != RW_NO_LATCH) {
1097+ ut_a(srv_pass_corrupt_table || block);
1098+
1099+ if (block && mode != RW_NO_LATCH) {
1100
734d6226
AM
1101 buf_block_dbg_add_level(
1102 block, index != NULL && dict_index_is_ibuf(index)
db82db79
AM
1103--- a/storage/innobase/include/buf0buf.h
1104+++ b/storage/innobase/include/buf0buf.h
29ffd636 1105@@ -1023,7 +1023,7 @@
b4e1fa2c
AM
1106 const buf_block_t* block) /*!< in: pointer to the control block */
1107 __attribute__((pure));
1108 #else /* UNIV_DEBUG */
1109-# define buf_block_get_frame(block) (block)->frame
1110+# define buf_block_get_frame(block) (block ? (block)->frame : 0)
1111 #endif /* UNIV_DEBUG */
1112 /*********************************************************************//**
1113 Gets the space id of a block.
29ffd636 1114@@ -1470,6 +1470,7 @@
b4e1fa2c
AM
1115 0 if the block was never accessed
1116 in the buffer pool */
1117 /* @} */
1118+ ibool is_corrupt;
df1b5770 1119 # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
b4e1fa2c
AM
1120 ibool file_page_was_freed;
1121 /*!< this is set to TRUE when fsp
db82db79
AM
1122--- a/storage/innobase/include/buf0buf.ic
1123+++ b/storage/innobase/include/buf0buf.ic
b4e1fa2c
AM
1124@@ -34,7 +34,7 @@
1125 #include "buf0flu.h"
1126 #include "buf0lru.h"
1127 #include "buf0rea.h"
1128-
1129+#include "srv0srv.h"
1130 /*********************************************************************//**
1131 Gets the current size of buffer buf_pool in bytes.
1132 @return size in bytes */
29ffd636 1133@@ -681,6 +681,12 @@
b4e1fa2c
AM
1134 /*================*/
1135 const buf_block_t* block) /*!< in: pointer to the control block */
1136 {
1137+ ut_a(srv_pass_corrupt_table || block);
1138+
1139+ if (srv_pass_corrupt_table && !block) {
1140+ return(0);
1141+ }
1142+
1143 ut_ad(block);
1144
1145 switch (buf_block_get_state(block)) {
db82db79
AM
1146--- a/storage/innobase/include/dict0dict.h
1147+++ b/storage/innobase/include/dict0dict.h
734d6226
AM
1148@@ -1326,6 +1326,15 @@
1149 /*========================*/
1150 ulint space_id); /*!< in: space ID */
b4e1fa2c
AM
1151
1152+/*************************************************************************
1153+set is_corrupt flag by space_id*/
1154+
1155+void
1156+dict_table_set_corrupt_by_space(
1157+/*============================*/
1158+ ulint space_id,
1159+ ibool need_mutex);
1160+
1161 #ifndef UNIV_NONINL
1162 #include "dict0dict.ic"
1163 #endif
db82db79
AM
1164--- a/storage/innobase/include/dict0mem.h
1165+++ b/storage/innobase/include/dict0mem.h
734d6226 1166@@ -670,6 +670,7 @@
b4e1fa2c
AM
1167 the AUTOINC lock on this table. */
1168 /* @} */
1169 /*----------------------*/
1170+ ibool is_corrupt;
1171 #endif /* !UNIV_HOTBACKUP */
1172
1173 #ifdef UNIV_DEBUG
db82db79
AM
1174--- a/storage/innobase/include/fil0fil.h
1175+++ b/storage/innobase/include/fil0fil.h
29ffd636 1176@@ -759,6 +759,19 @@
b4e1fa2c
AM
1177 fil_system_hash_nodes(void);
1178 /*========================*/
1179
1180+/*************************************************************************
1181+functions to access is_corrupt flag of fil_space_t*/
1182+
1183+ibool
1184+fil_space_is_corrupt(
1185+/*=================*/
1186+ ulint space_id);
1187+
1188+void
1189+fil_space_set_corrupt(
1190+/*==================*/
1191+ ulint space_id);
1192+
1193 typedef struct fil_space_struct fil_space_t;
1194
1195 #endif
db82db79
AM
1196--- a/storage/innobase/include/fut0fut.ic
1197+++ b/storage/innobase/include/fut0fut.ic
b4e1fa2c
AM
1198@@ -23,6 +23,7 @@
1199 Created 12/13/1995 Heikki Tuuri
1200 ***********************************************************************/
1201
1202+#include "srv0srv.h"
1203 #include "sync0rw.h"
1204 #include "buf0buf.h"
1205
1206@@ -48,6 +49,12 @@
1207 ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
1208
1209 block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr);
1210+
1211+ if (srv_pass_corrupt_table && !block) {
1212+ return(0);
1213+ }
1214+ ut_a(block);
1215+
1216 ptr = buf_block_get_frame(block) + addr.boffset;
1217
1218 buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
db82db79
AM
1219--- a/storage/innobase/include/page0page.h
1220+++ b/storage/innobase/include/page0page.h
734d6226 1221@@ -497,7 +497,7 @@
b4e1fa2c
AM
1222 page_is_leaf(
1223 /*=========*/
1224 const page_t* page) /*!< in: page */
1225- __attribute__((nonnull, pure));
1226+ __attribute__((pure));
1227 /************************************************************//**
1228 Gets the pointer to the next record on the page.
1229 @return pointer to next record */
db82db79
AM
1230--- a/storage/innobase/include/page0page.ic
1231+++ b/storage/innobase/include/page0page.ic
b4e1fa2c
AM
1232@@ -274,6 +274,9 @@
1233 /*=========*/
1234 const page_t* page) /*!< in: page */
1235 {
1236+ if (!page) {
1237+ return(FALSE);
1238+ }
1239 return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL)));
1240 }
1241
db82db79
AM
1242--- a/storage/innobase/include/page0zip.h
1243+++ b/storage/innobase/include/page0zip.h
b4e1fa2c
AM
1244@@ -114,7 +114,7 @@
1245 const page_t* page, /*!< in: uncompressed page */
1246 dict_index_t* index, /*!< in: index of the B-tree node */
1247 mtr_t* mtr) /*!< in: mini-transaction, or NULL */
1248- __attribute__((nonnull(1,2,3)));
1249+ __attribute__((nonnull(1,3)));
1250
1251 /**********************************************************************//**
1252 Decompress a page. This function should tolerate errors on the compressed
db82db79
AM
1253--- a/storage/innobase/include/srv0srv.h
1254+++ b/storage/innobase/include/srv0srv.h
734d6226 1255@@ -245,6 +245,7 @@
b4e1fa2c
AM
1256 extern ulint srv_adaptive_flushing_method;
1257
1258 extern ulint srv_expand_import;
1259+extern ulint srv_pass_corrupt_table;
1260
b4e1fa2c 1261 extern ulint srv_dict_size_limit;
11822e22 1262 /*-------------------------------------------*/
db82db79
AM
1263--- a/storage/innobase/page/page0zip.c
1264+++ b/storage/innobase/page/page0zip.c
1265@@ -1195,6 +1195,10 @@
b4e1fa2c
AM
1266 FILE* logfile = NULL;
1267 #endif
1268
1269+ if (!page) {
1270+ return(FALSE);
1271+ }
1272+
1273 ut_a(page_is_comp(page));
1274 ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
1275 ut_ad(page_simple_validate_new((page_t*) page));
db82db79
AM
1276--- a/storage/innobase/row/row0ins.c
1277+++ b/storage/innobase/row/row0ins.c
13ceb006 1278@@ -1341,6 +1341,12 @@
b4e1fa2c
AM
1279 const rec_t* rec = btr_pcur_get_rec(&pcur);
1280 const buf_block_t* block = btr_pcur_get_block(&pcur);
1281
1282+ if (srv_pass_corrupt_table && !block) {
1283+ err = DB_CORRUPTION;
1284+ break;
1285+ }
1286+ ut_a(block);
1287+
1288 if (page_rec_is_infimum(rec)) {
1289
1290 continue;
db82db79
AM
1291--- a/storage/innobase/row/row0merge.c
1292+++ b/storage/innobase/row/row0merge.c
b4e1fa2c
AM
1293@@ -1245,6 +1245,13 @@
1294
1295 if (UNIV_LIKELY(has_next)) {
1296 rec = btr_pcur_get_rec(&pcur);
1297+
1298+ if (srv_pass_corrupt_table && !rec) {
1299+ err = DB_CORRUPTION;
1300+ goto err_exit;
1301+ }
1302+ ut_a(rec);
1303+
1304 offsets = rec_get_offsets(rec, clust_index, NULL,
1305 ULINT_UNDEFINED, &row_heap);
1306
db82db79
AM
1307--- a/storage/innobase/row/row0sel.c
1308+++ b/storage/innobase/row/row0sel.c
543222d2 1309@@ -3919,6 +3919,13 @@
b4e1fa2c
AM
1310 /* PHASE 4: Look for matching records in a loop */
1311
1312 rec = btr_pcur_get_rec(pcur);
1313+
1314+ if (srv_pass_corrupt_table && !rec) {
1315+ err = DB_CORRUPTION;
1316+ goto lock_wait_or_error;
1317+ }
1318+ ut_a(rec);
1319+
1320 ut_ad(!!page_rec_is_comp(rec) == comp);
1321 #ifdef UNIV_SEARCH_DEBUG
1322 /*
543222d2 1323@@ -3996,7 +4003,13 @@
adf0fb13
AM
1324 if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
1325
1326 wrong_offs:
1327- if (srv_force_recovery == 0 || moves_up == FALSE) {
1328+ if (srv_pass_corrupt_table && !trx_sys_sys_space(index->table->space)) {
1329+ index->table->is_corrupt = TRUE;
1330+ fil_space_set_corrupt(index->table->space);
1331+ }
1332+
1333+ if ((srv_force_recovery == 0 || moves_up == FALSE)
1334+ && srv_pass_corrupt_table <= 1) {
1335 ut_print_timestamp(stderr);
1336 buf_page_print(page_align(rec), 0);
1337 fprintf(stderr,
543222d2 1338@@ -4047,7 +4060,8 @@
adf0fb13
AM
1339
1340 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1341
1342- if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
1343+ if (UNIV_UNLIKELY(srv_force_recovery > 0)
1344+ || (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) {
1345 if (!rec_validate(rec, offsets)
1346 || !btr_index_rec_validate(rec, index, FALSE)) {
1347 fprintf(stderr,
db82db79
AM
1348--- a/storage/innobase/srv/srv0srv.c
1349+++ b/storage/innobase/srv/srv0srv.c
734d6226 1350@@ -435,6 +435,7 @@
b4e1fa2c
AM
1351 UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
1352
1353 UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
1354+UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
1355
b4e1fa2c 1356 UNIV_INTERN ulint srv_dict_size_limit = 0;
11822e22 1357 /*-------------------------------------------*/
db82db79
AM
1358--- a/storage/innobase/srv/srv0start.c
1359+++ b/storage/innobase/srv/srv0start.c
29ffd636 1360@@ -2175,6 +2175,13 @@
b4e1fa2c
AM
1361
1362 os_fast_mutex_free(&srv_os_test_mutex);
1363
1364+ if (!srv_file_per_table_original_value
1365+ && srv_pass_corrupt_table) {
1366+ fprintf(stderr, "InnoDB: Warning:"
d8778560
AM
1367+ " The option innodb_file_per_table is disabled,"
1368+ " so using the option innodb_pass_corrupt_table doesn't make sense.\n");
b4e1fa2c
AM
1369+ }
1370+
1371 if (srv_print_verbose_log) {
1372 ut_print_timestamp(stderr);
1373 fprintf(stderr,
This page took 0.229184 seconds and 4 git commands to generate.