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