]> git.pld-linux.org Git - packages/mysql.git/blame - innodb_pass_corrupt_table.patch
- make mysql.init a bit more lsb-compatible
[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
11822e22 11@@ -691,6 +691,12 @@
b4e1fa2c
AM
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
11822e22 24@@ -977,6 +983,12 @@
b4e1fa2c
AM
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
11822e22 37@@ -1433,6 +1445,13 @@
b4e1fa2c
AM
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));
11822e22 51@@ -1455,6 +1474,12 @@
b4e1fa2c
AM
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));
11822e22 64@@ -1488,6 +1513,11 @@
b4e1fa2c
AM
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
df1b5770 79@@ -250,6 +250,11 @@
b4e1fa2c
AM
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 */
df1b5770 91@@ -263,6 +268,11 @@
b4e1fa2c
AM
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));
df1b5770 103@@ -274,6 +284,11 @@
b4e1fa2c
AM
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 */
df1b5770 115@@ -285,6 +300,11 @@
b4e1fa2c
AM
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));
df1b5770 127@@ -306,6 +326,11 @@
b4e1fa2c
AM
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));
df1b5770 139@@ -316,6 +341,11 @@
b4e1fa2c
AM
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 */
df1b5770 151@@ -588,6 +618,19 @@
b4e1fa2c
AM
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
df1b5770 171@@ -662,6 +705,16 @@
b4e1fa2c
AM
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
df1b5770 188@@ -866,6 +919,17 @@
b4e1fa2c
AM
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;
df1b5770 206@@ -986,6 +1050,14 @@
b4e1fa2c
AM
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) {
df1b5770 221@@ -1199,6 +1271,12 @@
b4e1fa2c
AM
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);
11822e22 234@@ -2925,6 +3003,11 @@
b4e1fa2c
AM
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);
11822e22 246@@ -3628,6 +3711,11 @@
b4e1fa2c
AM
247
248 page = btr_cur_get_page(&cursor);
249
250+ if (srv_pass_corrupt_table && !page) {
251+ break;
252+ }
253+ ut_a(page);
254+
df1b5770
AM
255 rec = page_rec_get_next(page_get_infimum_rec(page));
256
257 if (!page_rec_is_supremum(rec)) {
b4e1fa2c
AM
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();
adf0fb13 334@@ -1135,6 +1136,11 @@
b4e1fa2c
AM
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);
adf0fb13 346@@ -2479,6 +2485,13 @@
b4e1fa2c
AM
347 return(NULL);
348 }
349
adf0fb13 350+ if (srv_pass_corrupt_table <= 1) {
b4e1fa2c
AM
351+ if (bpage->is_corrupt) {
352+ rw_lock_s_unlock(&buf_pool->page_hash_latch);
353+ return(NULL);
354+ }
355+ }
b4e1fa2c
AM
356+
357 block_mutex = buf_page_get_mutex_enter(bpage);
358
359 rw_lock_s_unlock(&buf_pool->page_hash_latch);
f7ab7acd 360@@ -3059,6 +3072,13 @@
b4e1fa2c
AM
361 return(NULL);
362 }
363
adf0fb13 364+ if (srv_pass_corrupt_table <= 1) {
b4e1fa2c
AM
365+ if (block->page.is_corrupt) {
366+ mutex_exit(block_mutex);
367+ return(NULL);
368+ }
369+ }
b4e1fa2c
AM
370+
371 switch (buf_block_get_state(block)) {
372 buf_page_t* bpage;
373 ibool success;
f7ab7acd 374@@ -3733,6 +3753,7 @@
b4e1fa2c
AM
375 bpage->newest_modification = 0;
376 bpage->oldest_modification = 0;
377 HASH_INVALIDATE(bpage, hash);
378+ bpage->is_corrupt = FALSE;
df1b5770 379 #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
b4e1fa2c 380 bpage->file_page_was_freed = FALSE;
df1b5770 381 #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
f7ab7acd 382@@ -4322,6 +4343,7 @@
b4e1fa2c
AM
383 (ulong) bpage->offset);
384 }
385
386+ if (!srv_pass_corrupt_table || !bpage->is_corrupt) {
387 /* From version 3.23.38 up we store the page checksum
388 to the 4 first bytes of the page end lsn field */
389
f7ab7acd 390@@ -4363,6 +4385,23 @@
d8778560 391 REFMAN "forcing-innodb-recovery.html\n"
b4e1fa2c
AM
392 "InnoDB: about forcing recovery.\n", stderr);
393
394+ if (srv_pass_corrupt_table && !trx_sys_sys_space(bpage->space)
395+ && bpage->space < SRV_LOG_SPACE_FIRST_ID) {
adf0fb13
AM
396+ trx_t* trx;
397+
b4e1fa2c
AM
398+ fprintf(stderr,
399+ "InnoDB: space %u will be treated as corrupt.\n",
400+ bpage->space);
401+ fil_space_set_corrupt(bpage->space);
adf0fb13
AM
402+
403+ trx = innobase_get_trx();
404+ if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) {
b4e1fa2c 405+ dict_table_set_corrupt_by_space(bpage->space, FALSE);
adf0fb13
AM
406+ } else {
407+ dict_table_set_corrupt_by_space(bpage->space, TRUE);
b4e1fa2c
AM
408+ }
409+ bpage->is_corrupt = TRUE;
410+ } else
411 if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
412 fputs("InnoDB: Ending processing because of"
413 " a corrupt database page.\n",
f7ab7acd 414@@ -4370,6 +4409,7 @@
b4e1fa2c
AM
415 exit(1);
416 }
417 }
418+ } /**/
419
420 if (recv_recovery_is_on()) {
421 /* Pages must be uncompressed for crash recovery. */
f7ab7acd 422@@ -4379,8 +4419,11 @@
b4e1fa2c
AM
423
424 if (uncompressed && !recv_no_ibuf_operations) {
425 ibuf_merge_or_delete_for_page(
426+ /* Delete possible entries, if bpage is_corrupt */
427+ (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL :
428 (buf_block_t*) bpage, bpage->space,
429 bpage->offset, buf_page_get_zip_size(bpage),
430+ (srv_pass_corrupt_table && bpage->is_corrupt) ? FALSE :
431 TRUE);
432 }
433 }
434diff -ruN a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
435--- a/storage/innobase/buf/buf0rea.c 2010-12-04 15:37:50.557553380 +0900
436+++ b/storage/innobase/buf/buf0rea.c 2010-12-04 15:41:09.784467585 +0900
adf0fb13 437@@ -193,7 +193,14 @@
b4e1fa2c
AM
438 ((buf_block_t*) bpage)->frame, bpage, trx);
439 }
440 thd_wait_end(NULL);
441+
442+ if (srv_pass_corrupt_table) {
443+ if (*err != DB_SUCCESS) {
444+ bpage->is_corrupt = TRUE;
445+ }
446+ } else {
447 ut_a(*err == DB_SUCCESS);
448+ }
449
450 if (sync) {
451 /* The i/o is already completed when we arrive from
b4e1fa2c
AM
452diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
453--- a/storage/innobase/dict/dict0dict.c 2010-12-03 17:30:16.248987063 +0900
454+++ b/storage/innobase/dict/dict0dict.c 2010-12-04 15:45:23.808513973 +0900
adf0fb13
AM
455@@ -54,6 +54,7 @@
456 #include "row0merge.h"
b4e1fa2c 457 #include "m_ctype.h" /* my_isspace() */
d8778560 458 #include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
b4e1fa2c
AM
459+#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
460
461 #include <ctype.h>
462
adf0fb13 463@@ -750,7 +751,7 @@
b4e1fa2c
AM
464
465 mutex_exit(&(dict_sys->mutex));
466
467- if (table != NULL) {
468+ if (table != NULL && !table->is_corrupt) {
469 /* If table->ibd_file_missing == TRUE, this will
470 print an error message and return without doing
471 anything. */
adf0fb13 472@@ -1293,7 +1294,7 @@
b4e1fa2c
AM
473 + dict_sys->size) > srv_dict_size_limit ) {
474 prev_table = UT_LIST_GET_PREV(table_LRU, table);
475
476- if (table == self || table->n_mysql_handles_opened)
477+ if (table == self || table->n_mysql_handles_opened || table->is_corrupt)
478 goto next_loop;
479
480 cached_foreign_tables = 0;
adf0fb13 481@@ -4332,6 +4333,12 @@
b4e1fa2c
AM
482 heap = mem_heap_create(1000);
483
484 while (index) {
485+ if (table->is_corrupt) {
486+ ut_a(srv_pass_corrupt_table);
487+ mem_heap_free(heap);
488+ return(FALSE);
489+ }
490+
491 size = btr_get_size(index, BTR_TOTAL_SIZE);
492
493 index->stat_index_size = size;
adf0fb13 494@@ -4479,6 +4486,12 @@
b4e1fa2c
AM
495 heap = mem_heap_create(1000);
496
497 while (index) {
498+ if (table->is_corrupt) {
499+ ut_a(srv_pass_corrupt_table);
500+ mem_heap_free(heap);
501+ return;
502+ }
503+
504 /*===========================================*/
505 {
506 dict_table_t* sys_stats;
adf0fb13 507@@ -4671,6 +4684,13 @@
b4e1fa2c
AM
508 || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
509 && dict_index_is_clust(index)))) {
510 ulint size;
511+
512+ if (table->is_corrupt) {
513+ ut_a(srv_pass_corrupt_table);
adf0fb13 514+ dict_table_stats_unlock(table, RW_X_LATCH);
b4e1fa2c
AM
515+ return;
516+ }
517+
518 size = btr_get_size(index, BTR_TOTAL_SIZE);
519
520 index->stat_index_size = size;
adf0fb13 521@@ -5467,4 +5487,42 @@
b4e1fa2c
AM
522 rw_lock_free(&dict_table_stats_latches[i]);
523 }
524 }
525+
526+/*************************************************************************
527+set is_corrupt flag by space_id*/
528+
529+void
530+dict_table_set_corrupt_by_space(
531+/*============================*/
532+ ulint space_id,
533+ ibool need_mutex)
534+{
535+ dict_table_t* table;
536+ ibool found = FALSE;
537+
538+ ut_a(!trx_sys_sys_space(space_id) && space_id < SRV_LOG_SPACE_FIRST_ID);
539+
540+ if (need_mutex)
541+ mutex_enter(&(dict_sys->mutex));
542+
543+ table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
544+
545+ while (table) {
546+ if (table->space == space_id) {
547+ table->is_corrupt = TRUE;
548+ found = TRUE;
549+ }
550+
551+ table = UT_LIST_GET_NEXT(table_LRU, table);
552+ }
553+
554+ if (need_mutex)
555+ mutex_exit(&(dict_sys->mutex));
556+
557+ if (!found) {
558+ fprintf(stderr, "InnoDB: space to be marked as "
559+ "crashed was not found for id %lu.\n",
560+ (ulong) space_id);
561+ }
562+}
563 #endif /* !UNIV_HOTBACKUP */
564diff -ruN a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c
565--- a/storage/innobase/dict/dict0mem.c 2010-11-03 07:01:13.000000000 +0900
566+++ b/storage/innobase/dict/dict0mem.c 2010-12-04 15:38:18.126549463 +0900
adf0fb13 567@@ -96,6 +96,8 @@
b4e1fa2c
AM
568 /* The number of transactions that are either waiting on the
569 AUTOINC lock or have been granted the lock. */
570 table->n_waiting_or_granted_auto_inc_locks = 0;
571+
572+ table->is_corrupt = FALSE;
573 #endif /* !UNIV_HOTBACKUP */
574
575 ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
576diff -ruN a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
577--- a/storage/innobase/fil/fil0fil.c 2010-12-04 15:37:50.564551587 +0900
578+++ b/storage/innobase/fil/fil0fil.c 2010-12-04 15:38:18.128549252 +0900
adf0fb13 579@@ -235,6 +235,7 @@
b4e1fa2c
AM
580 file we have written to */
581 ibool is_in_unflushed_spaces; /*!< TRUE if this space is
582 currently in unflushed_spaces */
583+ ibool is_corrupt;
584 UT_LIST_NODE_T(fil_space_t) space_list;
585 /*!< list of all spaces */
586 ulint magic_n;/*!< FIL_SPACE_MAGIC_N */
adf0fb13 587@@ -1293,6 +1294,8 @@
b4e1fa2c
AM
588 ut_fold_string(name), space);
589 space->is_in_unflushed_spaces = FALSE;
590
591+ space->is_corrupt = FALSE;
592+
593 UT_LIST_ADD_LAST(space_list, fil_system->space_list, space);
594
595 mutex_exit(&fil_system->mutex);
adf0fb13 596@@ -5267,6 +5270,34 @@
b4e1fa2c
AM
597 ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
598 ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
599
adf0fb13 600+ if (srv_pass_corrupt_table == 1 && space->is_corrupt) {
b4e1fa2c
AM
601+ /* should ignore i/o for the crashed space */
602+ mutex_enter(&fil_system->mutex);
603+ fil_node_complete_io(node, fil_system, type);
604+ mutex_exit(&fil_system->mutex);
605+ if (mode == OS_AIO_NORMAL) {
606+ ut_a(space->purpose == FIL_TABLESPACE);
adf0fb13 607+ buf_page_io_complete(message);
b4e1fa2c
AM
608+ }
609+ if (type == OS_FILE_READ) {
610+ return(DB_TABLESPACE_DELETED);
611+ } else {
612+ return(DB_SUCCESS);
613+ }
614+ } else {
adf0fb13
AM
615+ if (srv_pass_corrupt_table > 1 && space->is_corrupt) {
616+ /* should ignore write i/o for the crashed space */
617+ if (type == OS_FILE_WRITE) {
618+ mutex_enter(&fil_system->mutex);
619+ fil_node_complete_io(node, fil_system, type);
620+ mutex_exit(&fil_system->mutex);
621+ if (mode == OS_AIO_NORMAL) {
622+ ut_a(space->purpose == FIL_TABLESPACE);
623+ buf_page_io_complete(message);
624+ }
625+ return(DB_SUCCESS);
626+ }
627+ }
b4e1fa2c
AM
628 #ifdef UNIV_HOTBACKUP
629 /* In ibbackup do normal i/o, not aio */
630 if (type == OS_FILE_READ) {
adf0fb13 631@@ -5281,6 +5312,8 @@
b4e1fa2c
AM
632 ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
633 offset_low, offset_high, len, node, message, trx);
634 #endif
635+ } /**/
636+
637 ut_a(ret);
638
639 if (mode == OS_AIO_SYNC) {
413cadc7 640@@ -5781,3 +5814,46 @@
b4e1fa2c
AM
641 return 0;
642 }
643 }
644+
645+/*************************************************************************
646+functions to access is_corrupt flag of fil_space_t*/
647+
648+ibool
649+fil_space_is_corrupt(
650+/*=================*/
651+ ulint space_id)
652+{
653+ fil_space_t* space;
654+ ibool ret = FALSE;
655+
656+ mutex_enter(&fil_system->mutex);
657+
658+ space = fil_space_get_by_id(space_id);
659+
660+ if (space && space->is_corrupt) {
661+ ret = TRUE;
662+ }
663+
664+ mutex_exit(&fil_system->mutex);
665+
666+ return(ret);
667+}
668+
669+void
670+fil_space_set_corrupt(
671+/*==================*/
672+ ulint space_id)
673+{
674+ fil_space_t* space;
675+
676+ mutex_enter(&fil_system->mutex);
677+
678+ space = fil_space_get_by_id(space_id);
679+
680+ if (space) {
681+ space->is_corrupt = TRUE;
682+ }
683+
684+ mutex_exit(&fil_system->mutex);
685+}
686+
687diff -ruN a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c
688--- a/storage/innobase/fsp/fsp0fsp.c 2010-12-04 15:37:50.569480615 +0900
689+++ b/storage/innobase/fsp/fsp0fsp.c 2010-12-04 15:38:18.131550103 +0900
690@@ -369,6 +369,12 @@
691 ut_ad(id || !zip_size);
692
693 block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr);
694+
695+ if (srv_pass_corrupt_table && !block) {
696+ return(0);
697+ }
698+ ut_a(block);
699+
700 header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
701 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
702
703@@ -787,6 +793,12 @@
704 fsp_header_t* sp_header;
705
706 block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
707+
708+ if (srv_pass_corrupt_table && !block) {
709+ return(0);
710+ }
711+ ut_a(block);
712+
713 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
714
715 sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
716@@ -1866,6 +1878,11 @@
717 {
718 fseg_inode_t* inode;
719
720+ if (srv_pass_corrupt_table && !page) {
721+ return(ULINT_UNDEFINED);
722+ }
723+ ut_a(page);
724+
725 for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
726
727 inode = fsp_seg_inode_page_get_nth_inode(
728@@ -1979,6 +1996,11 @@
729
730 page = buf_block_get_frame(block);
731
732+ if (srv_pass_corrupt_table && !page) {
733+ return(0);
734+ }
735+ ut_a(page);
736+
737 n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr);
738
739 ut_a(n != ULINT_UNDEFINED);
740@@ -2072,6 +2094,11 @@
741
742 inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
743
744+ if (srv_pass_corrupt_table && !inode) {
745+ return(0);
746+ }
747+ ut_a(inode);
748+
749 if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
750
751 inode = NULL;
752@@ -2098,7 +2125,7 @@
753 {
754 fseg_inode_t* inode
755 = fseg_inode_try_get(header, space, zip_size, mtr);
756- ut_a(inode);
757+ ut_a(srv_pass_corrupt_table || inode);
758 return(inode);
759 }
760
761@@ -3304,6 +3331,11 @@
762
763 descr = xdes_get_descriptor(space, zip_size, page, mtr);
764
765+ if (srv_pass_corrupt_table && !descr) {
766+ /* The page may be corrupt. pass it. */
767+ return;
768+ }
769+
770 ut_a(descr);
771 if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
772 fputs("InnoDB: Dump of the tablespace extent descriptor: ",
773@@ -3551,6 +3583,11 @@
774
775 descr = xdes_get_descriptor(space, zip_size, header_page, mtr);
776
777+ if (srv_pass_corrupt_table && !descr) {
778+ /* The page may be corrupt. pass it. */
779+ return(TRUE);
780+ }
781+
782 /* Check that the header resides on a page which has not been
783 freed yet */
784
785@@ -3635,6 +3672,12 @@
786
787 inode = fseg_inode_get(header, space, zip_size, mtr);
788
789+ if (srv_pass_corrupt_table && !inode) {
790+ /* ignore the corruption */
791+ return(TRUE);
792+ }
793+ ut_a(inode);
794+
795 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
796
797 if (descr != NULL) {
798diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
799--- a/storage/innobase/handler/ha_innodb.cc 2010-12-04 15:37:50.578486593 +0900
800+++ b/storage/innobase/handler/ha_innodb.cc 2010-12-04 15:38:18.137549396 +0900
adf0fb13 801@@ -3972,6 +3972,12 @@
b4e1fa2c
AM
802 DBUG_RETURN(1);
803 }
804
adf0fb13 805+ if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) {
b4e1fa2c
AM
806+ free_share(share);
807+
808+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
809+ }
810+
811 /* Create buffers for packing the fields of a record. Why
812 table->reclength did not work here? Obviously, because char
813 fields when packed actually became 1 byte longer, when we also
adf0fb13 814@@ -3999,6 +4005,19 @@
b4e1fa2c
AM
815 /* Get pointer to a table object in InnoDB dictionary cache */
816 ib_table = dict_table_get(norm_name, TRUE);
817
adf0fb13 818+ if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
b4e1fa2c
AM
819+ free_share(share);
820+ my_free(upd_buff);
821+
822+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
823+ }
824+
825+ if (share->ib_table) {
826+ ut_a(share->ib_table == ib_table);
827+ } else {
828+ share->ib_table = ib_table;
829+ }
830+
831 if (NULL == ib_table) {
832 if (is_part && retries < 10) {
833 ++retries;
adf0fb13 834@@ -5163,6 +5182,10 @@
b4e1fa2c
AM
835
836 ha_statistic_increment(&SSV::ha_write_count);
837
838+ if (share->ib_table->is_corrupt) {
839+ DBUG_RETURN(HA_ERR_CRASHED);
840+ }
841+
842 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
843 table->timestamp_field->set_time();
844
adf0fb13 845@@ -5380,6 +5403,10 @@
b4e1fa2c
AM
846 func_exit:
847 innobase_active_small();
848
849+ if (share->ib_table->is_corrupt) {
850+ DBUG_RETURN(HA_ERR_CRASHED);
851+ }
852+
853 DBUG_RETURN(error_result);
854 }
855
adf0fb13 856@@ -5556,6 +5583,10 @@
b4e1fa2c
AM
857
858 ha_statistic_increment(&SSV::ha_update_count);
859
860+ if (share->ib_table->is_corrupt) {
861+ DBUG_RETURN(HA_ERR_CRASHED);
862+ }
863+
864 if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
865 table->timestamp_field->set_time();
866
adf0fb13 867@@ -5645,6 +5676,10 @@
b4e1fa2c
AM
868
869 innobase_active_small();
870
871+ if (share->ib_table->is_corrupt) {
872+ DBUG_RETURN(HA_ERR_CRASHED);
873+ }
874+
875 DBUG_RETURN(error);
876 }
877
adf0fb13 878@@ -5666,6 +5701,10 @@
b4e1fa2c
AM
879
880 ha_statistic_increment(&SSV::ha_delete_count);
881
882+ if (share->ib_table->is_corrupt) {
883+ DBUG_RETURN(HA_ERR_CRASHED);
884+ }
885+
886 if (!prebuilt->upd_node) {
887 row_get_prebuilt_update_vector(prebuilt);
888 }
adf0fb13 889@@ -5692,6 +5731,10 @@
b4e1fa2c
AM
890
891 innobase_active_small();
892
893+ if (share->ib_table->is_corrupt) {
894+ DBUG_RETURN(HA_ERR_CRASHED);
895+ }
896+
897 DBUG_RETURN(error);
898 }
899
adf0fb13 900@@ -5931,6 +5974,10 @@
b4e1fa2c
AM
901
902 ha_statistic_increment(&SSV::ha_read_key_count);
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 index = prebuilt->index;
909
910 if (UNIV_UNLIKELY(index == NULL)) {
adf0fb13 911@@ -5996,6 +6043,10 @@
b4e1fa2c
AM
912 ret = DB_UNSUPPORTED;
913 }
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 switch (ret) {
920 case DB_SUCCESS:
921 error = 0;
adf0fb13 922@@ -6111,6 +6162,10 @@
b4e1fa2c
AM
923 {
924 DBUG_ENTER("change_active_index");
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_ad(user_thd == ha_thd());
931 ut_a(prebuilt->trx == thd_to_trx(user_thd));
932
adf0fb13 933@@ -6201,6 +6256,10 @@
b4e1fa2c
AM
934
935 DBUG_ENTER("general_fetch");
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 ut_a(prebuilt->trx == thd_to_trx(user_thd));
942
943 innodb_srv_conc_enter_innodb(prebuilt->trx);
adf0fb13 944@@ -6210,6 +6269,10 @@
b4e1fa2c
AM
945
946 innodb_srv_conc_exit_innodb(prebuilt->trx);
947
adf0fb13 948+ if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
b4e1fa2c
AM
949+ DBUG_RETURN(HA_ERR_CRASHED);
950+ }
951+
952 switch (ret) {
953 case DB_SUCCESS:
954 error = 0;
adf0fb13 955@@ -7476,10 +7539,18 @@
b4e1fa2c
AM
956
957 update_thd(ha_thd());
958
959+ if (share->ib_table->is_corrupt) {
960+ DBUG_RETURN(HA_ERR_CRASHED);
961+ }
962+
963 /* Truncate the table in InnoDB */
964
965 error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
966
967+ if (share->ib_table->is_corrupt) {
968+ DBUG_RETURN(HA_ERR_CRASHED);
969+ }
970+
971 error = convert_error_code_to_mysql(error, prebuilt->table->flags,
972 NULL);
973
adf0fb13 974@@ -7980,6 +8051,16 @@
b4e1fa2c
AM
975 return(ranges + (double) rows / (double) total_rows * time_for_scan);
976 }
977
978+UNIV_INTERN
979+bool
980+ha_innobase::is_corrupt() const
981+{
982+ if (share->ib_table)
983+ return ((bool)share->ib_table->is_corrupt);
984+ else
985+ return (FALSE);
986+}
987+
988 /*********************************************************************//**
989 Calculates the key number used inside MySQL for an Innobase index. We will
990 first check the "index translation table" for a match of the index to get
adf0fb13 991@@ -8157,7 +8238,7 @@
b4e1fa2c
AM
992 ib_table = prebuilt->table;
993
994 if (flag & HA_STATUS_TIME) {
995- if (called_from_analyze || innobase_stats_on_metadata) {
996+ if ((called_from_analyze || innobase_stats_on_metadata) && !share->ib_table->is_corrupt) {
997 /* In sql_show we call with this flag: update
998 then statistics so that they are up-to-date */
999
adf0fb13 1000@@ -8450,10 +8531,18 @@
b4e1fa2c
AM
1001 THD* thd, /*!< in: connection thread handle */
1002 HA_CHECK_OPT* check_opt) /*!< in: currently ignored */
1003 {
1004+ if (share->ib_table->is_corrupt) {
1005+ return(HA_ADMIN_CORRUPT);
1006+ }
1007+
1008 /* Simply call ::info() with all the flags */
1009 info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE,
1010 true /* called from analyze */);
1011
1012+ if (share->ib_table->is_corrupt) {
1013+ return(HA_ADMIN_CORRUPT);
1014+ }
1015+
1016 return(0);
1017 }
1018
adf0fb13 1019@@ -8635,6 +8724,10 @@
b4e1fa2c
AM
1020 my_error(ER_QUERY_INTERRUPTED, MYF(0));
1021 }
1022
1023+ if (share->ib_table->is_corrupt) {
1024+ return(HA_ADMIN_CORRUPT);
1025+ }
1026+
1027 DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
1028 }
1029
adf0fb13 1030@@ -9405,6 +9498,10 @@
b4e1fa2c
AM
1031
1032 update_thd(thd);
1033
1034+ if (share->ib_table->is_corrupt) {
1035+ DBUG_RETURN(HA_ERR_CRASHED);
1036+ }
1037+
1038 if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
1039 ut_print_timestamp(stderr);
1040 fprintf(stderr,
adf0fb13 1041@@ -11807,6 +11904,26 @@
b4e1fa2c
AM
1042 "0 (the default) disables automatic dumps.",
1043 NULL, NULL, 0, 0, UINT_MAX32, 0);
1044
a9ee80b9
ER
1045+const char *corrupt_table_action_names[]=
1046+{
1047+ "assert", /* 0 */
1048+ "warn", /* 1 */
adf0fb13 1049+ "salvage", /* 2 */
a9ee80b9
ER
1050+ NullS
1051+};
1052+TYPELIB corrupt_table_action_typelib=
1053+{
1054+ array_elements(corrupt_table_action_names) - 1, "corrupt_table_action_typelib",
1055+ corrupt_table_action_names, NULL
1056+};
1057+static MYSQL_SYSVAR_ENUM(corrupt_table_action, srv_pass_corrupt_table,
b4e1fa2c 1058+ PLUGIN_VAR_RQCMDARG,
a9ee80b9 1059+ "Warn corruptions of user tables as 'corrupt table' instead of not crashing itself, "
b4e1fa2c
AM
1060+ "when used with file_per_table. "
1061+ "All file io for the datafile after detected as corrupt are disabled, "
1062+ "except for the deletion.",
a9ee80b9 1063+ NULL, NULL, 0, &corrupt_table_action_typelib);
b4e1fa2c
AM
1064+
1065 static struct st_mysql_sys_var* innobase_system_variables[]= {
1066 MYSQL_SYSVAR(additional_mem_pool_size),
1067 MYSQL_SYSVAR(autoextend_increment),
adf0fb13 1068@@ -11893,6 +12010,7 @@
b4e1fa2c
AM
1069 MYSQL_SYSVAR(purge_threads),
1070 MYSQL_SYSVAR(purge_batch_size),
11822e22 1071 MYSQL_SYSVAR(rollback_segments),
a9ee80b9 1072+ MYSQL_SYSVAR(corrupt_table_action),
b4e1fa2c
AM
1073 NULL
1074 };
1075
1076diff -ruN a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
1077--- a/storage/innobase/handler/ha_innodb.h 2010-11-03 07:01:13.000000000 +0900
1078+++ b/storage/innobase/handler/ha_innodb.h 2010-12-04 15:38:18.159588579 +0900
1079@@ -52,6 +52,7 @@
1080 innodb_idx_translate_t idx_trans_tbl; /*!< index translation
1081 table between MySQL and
1082 Innodb */
1083+ dict_table_t* ib_table;
1084 } INNOBASE_SHARE;
1085
1086
1087@@ -135,6 +136,7 @@
1088 int close(void);
1089 double scan_time();
1090 double read_time(uint index, uint ranges, ha_rows rows);
1091+ bool is_corrupt() const;
1092
1093 int write_row(uchar * buf);
1094 int update_row(const uchar * old_data, uchar * new_data);
1095diff -ruN a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
1096--- a/storage/innobase/include/btr0btr.ic 2010-11-03 07:01:13.000000000 +0900
1097+++ b/storage/innobase/include/btr0btr.ic 2010-12-04 15:38:18.162515035 +0900
1098@@ -28,7 +28,7 @@
1099 #include "mtr0mtr.h"
1100 #include "mtr0log.h"
1101 #include "page0zip.h"
1102-
1103+#include "srv0srv.h"
1104 #define BTR_MAX_NODE_LEVEL 50 /*!< Maximum B-tree page level
1105 (not really a hard limit).
1106 Used in debug assertions
1107@@ -55,7 +55,9 @@
1108 block = buf_page_get_gen(space, zip_size, page_no, mode,
1109 NULL, BUF_GET, file, line, mtr);
1110
1111- if (mode != RW_NO_LATCH) {
1112+ ut_a(srv_pass_corrupt_table || block);
1113+
1114+ if (block && mode != RW_NO_LATCH) {
1115
1116 buf_block_dbg_add_level(block, SYNC_TREE_NODE);
1117 }
1118diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
1119--- a/storage/innobase/include/buf0buf.h 2010-12-03 15:49:59.218956083 +0900
1120+++ b/storage/innobase/include/buf0buf.h 2010-12-04 15:38:18.164513667 +0900
adf0fb13 1121@@ -986,7 +986,7 @@
b4e1fa2c
AM
1122 const buf_block_t* block) /*!< in: pointer to the control block */
1123 __attribute__((pure));
1124 #else /* UNIV_DEBUG */
1125-# define buf_block_get_frame(block) (block)->frame
1126+# define buf_block_get_frame(block) (block ? (block)->frame : 0)
1127 #endif /* UNIV_DEBUG */
1128 /*********************************************************************//**
1129 Gets the space id of a block.
adf0fb13 1130@@ -1433,6 +1433,7 @@
b4e1fa2c
AM
1131 0 if the block was never accessed
1132 in the buffer pool */
1133 /* @} */
1134+ ibool is_corrupt;
df1b5770 1135 # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
b4e1fa2c
AM
1136 ibool file_page_was_freed;
1137 /*!< this is set to TRUE when fsp
1138diff -ruN a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
1139--- a/storage/innobase/include/buf0buf.ic 2010-12-03 15:49:59.221956024 +0900
1140+++ b/storage/innobase/include/buf0buf.ic 2010-12-04 15:38:18.167513925 +0900
1141@@ -34,7 +34,7 @@
1142 #include "buf0flu.h"
1143 #include "buf0lru.h"
1144 #include "buf0rea.h"
1145-
1146+#include "srv0srv.h"
1147 /*********************************************************************//**
1148 Gets the current size of buffer buf_pool in bytes.
1149 @return size in bytes */
11822e22 1150@@ -619,6 +619,12 @@
b4e1fa2c
AM
1151 /*================*/
1152 const buf_block_t* block) /*!< in: pointer to the control block */
1153 {
1154+ ut_a(srv_pass_corrupt_table || block);
1155+
1156+ if (srv_pass_corrupt_table && !block) {
1157+ return(0);
1158+ }
1159+
1160 ut_ad(block);
1161
1162 switch (buf_block_get_state(block)) {
1163diff -ruN a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
1164--- a/storage/innobase/include/dict0dict.h 2010-12-03 17:30:16.306955940 +0900
1165+++ b/storage/innobase/include/dict0dict.h 2010-12-04 15:38:18.169513750 +0900
11822e22 1166@@ -1245,6 +1245,15 @@
b4e1fa2c
AM
1167 dict_close(void);
1168 /*============*/
1169
1170+/*************************************************************************
1171+set is_corrupt flag by space_id*/
1172+
1173+void
1174+dict_table_set_corrupt_by_space(
1175+/*============================*/
1176+ ulint space_id,
1177+ ibool need_mutex);
1178+
1179 #ifndef UNIV_NONINL
1180 #include "dict0dict.ic"
1181 #endif
1182diff -ruN a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
1183--- a/storage/innobase/include/dict0mem.h 2010-11-03 07:01:13.000000000 +0900
1184+++ b/storage/innobase/include/dict0mem.h 2010-12-04 15:38:18.171513956 +0900
adf0fb13 1185@@ -640,6 +640,7 @@
b4e1fa2c
AM
1186 the AUTOINC lock on this table. */
1187 /* @} */
1188 /*----------------------*/
1189+ ibool is_corrupt;
1190 #endif /* !UNIV_HOTBACKUP */
1191
1192 #ifdef UNIV_DEBUG
1193diff -ruN a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
1194--- a/storage/innobase/include/fil0fil.h 2010-12-04 15:35:29.175520016 +0900
1195+++ b/storage/innobase/include/fil0fil.h 2010-12-04 15:38:18.172483391 +0900
413cadc7 1196@@ -750,6 +750,19 @@
b4e1fa2c
AM
1197 fil_system_hash_nodes(void);
1198 /*========================*/
1199
1200+/*************************************************************************
1201+functions to access is_corrupt flag of fil_space_t*/
1202+
1203+ibool
1204+fil_space_is_corrupt(
1205+/*=================*/
1206+ ulint space_id);
1207+
1208+void
1209+fil_space_set_corrupt(
1210+/*==================*/
1211+ ulint space_id);
1212+
1213 typedef struct fil_space_struct fil_space_t;
1214
1215 #endif
1216diff -ruN a/storage/innobase/include/fut0fut.ic b/storage/innobase/include/fut0fut.ic
1217--- a/storage/innobase/include/fut0fut.ic 2010-11-03 07:01:13.000000000 +0900
1218+++ b/storage/innobase/include/fut0fut.ic 2010-12-04 15:38:18.174481728 +0900
1219@@ -23,6 +23,7 @@
1220 Created 12/13/1995 Heikki Tuuri
1221 ***********************************************************************/
1222
1223+#include "srv0srv.h"
1224 #include "sync0rw.h"
1225 #include "buf0buf.h"
1226
1227@@ -48,6 +49,12 @@
1228 ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
1229
1230 block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr);
1231+
1232+ if (srv_pass_corrupt_table && !block) {
1233+ return(0);
1234+ }
1235+ ut_a(block);
1236+
1237 ptr = buf_block_get_frame(block) + addr.boffset;
1238
1239 buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
1240diff -ruN a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
1241--- a/storage/innobase/include/page0page.h 2010-11-03 07:01:13.000000000 +0900
1242+++ b/storage/innobase/include/page0page.h 2010-12-04 15:38:18.175514037 +0900
1243@@ -500,7 +500,7 @@
1244 page_is_leaf(
1245 /*=========*/
1246 const page_t* page) /*!< in: page */
1247- __attribute__((nonnull, pure));
1248+ __attribute__((pure));
1249 /************************************************************//**
1250 Gets the pointer to the next record on the page.
1251 @return pointer to next record */
1252diff -ruN a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
1253--- a/storage/innobase/include/page0page.ic 2010-11-03 07:01:13.000000000 +0900
1254+++ b/storage/innobase/include/page0page.ic 2010-12-04 15:38:18.177482672 +0900
1255@@ -274,6 +274,9 @@
1256 /*=========*/
1257 const page_t* page) /*!< in: page */
1258 {
1259+ if (!page) {
1260+ return(FALSE);
1261+ }
1262 return(!*(const uint16*) (page + (PAGE_HEADER + PAGE_LEVEL)));
1263 }
1264
1265diff -ruN a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h
1266--- a/storage/innobase/include/page0zip.h 2010-11-03 07:01:13.000000000 +0900
1267+++ b/storage/innobase/include/page0zip.h 2010-12-04 15:38:18.179513974 +0900
1268@@ -114,7 +114,7 @@
1269 const page_t* page, /*!< in: uncompressed page */
1270 dict_index_t* index, /*!< in: index of the B-tree node */
1271 mtr_t* mtr) /*!< in: mini-transaction, or NULL */
1272- __attribute__((nonnull(1,2,3)));
1273+ __attribute__((nonnull(1,3)));
1274
1275 /**********************************************************************//**
1276 Decompress a page. This function should tolerate errors on the compressed
1277diff -ruN a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
1278--- a/storage/innobase/include/srv0srv.h 2010-12-04 15:37:50.591516341 +0900
1279+++ b/storage/innobase/include/srv0srv.h 2010-12-04 15:38:18.180563749 +0900
adf0fb13 1280@@ -240,6 +240,7 @@
b4e1fa2c
AM
1281 extern ulint srv_adaptive_flushing_method;
1282
1283 extern ulint srv_expand_import;
1284+extern ulint srv_pass_corrupt_table;
1285
b4e1fa2c 1286 extern ulint srv_dict_size_limit;
11822e22 1287 /*-------------------------------------------*/
b4e1fa2c
AM
1288diff -ruN a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c
1289--- a/storage/innobase/page/page0zip.c 2010-11-03 07:01:13.000000000 +0900
1290+++ b/storage/innobase/page/page0zip.c 2010-12-04 15:38:18.195515935 +0900
1291@@ -1153,6 +1153,10 @@
1292 FILE* logfile = NULL;
1293 #endif
1294
1295+ if (!page) {
1296+ return(FALSE);
1297+ }
1298+
1299 ut_a(page_is_comp(page));
1300 ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
1301 ut_ad(page_simple_validate_new((page_t*) page));
1302diff -ruN a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c
1303--- a/storage/innobase/row/row0ins.c 2010-11-03 07:01:13.000000000 +0900
1304+++ b/storage/innobase/row/row0ins.c 2010-12-04 15:38:18.198514028 +0900
1305@@ -1335,6 +1335,12 @@
1306 const rec_t* rec = btr_pcur_get_rec(&pcur);
1307 const buf_block_t* block = btr_pcur_get_block(&pcur);
1308
1309+ if (srv_pass_corrupt_table && !block) {
1310+ err = DB_CORRUPTION;
1311+ break;
1312+ }
1313+ ut_a(block);
1314+
1315 if (page_rec_is_infimum(rec)) {
1316
1317 continue;
1318diff -ruN a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c
1319--- a/storage/innobase/row/row0merge.c 2010-12-03 17:30:16.330986655 +0900
1320+++ b/storage/innobase/row/row0merge.c 2010-12-04 15:38:18.201513966 +0900
1321@@ -1245,6 +1245,13 @@
1322
1323 if (UNIV_LIKELY(has_next)) {
1324 rec = btr_pcur_get_rec(&pcur);
1325+
1326+ if (srv_pass_corrupt_table && !rec) {
1327+ err = DB_CORRUPTION;
1328+ goto err_exit;
1329+ }
1330+ ut_a(rec);
1331+
1332 offsets = rec_get_offsets(rec, clust_index, NULL,
1333 ULINT_UNDEFINED, &row_heap);
1334
1335diff -ruN a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
1336--- a/storage/innobase/row/row0sel.c 2010-11-03 07:01:13.000000000 +0900
1337+++ b/storage/innobase/row/row0sel.c 2010-12-04 15:38:18.205551115 +0900
adf0fb13 1338@@ -3853,6 +3853,13 @@
b4e1fa2c
AM
1339 /* PHASE 4: Look for matching records in a loop */
1340
1341 rec = btr_pcur_get_rec(pcur);
1342+
1343+ if (srv_pass_corrupt_table && !rec) {
1344+ err = DB_CORRUPTION;
1345+ goto lock_wait_or_error;
1346+ }
1347+ ut_a(rec);
1348+
1349 ut_ad(!!page_rec_is_comp(rec) == comp);
1350 #ifdef UNIV_SEARCH_DEBUG
1351 /*
adf0fb13
AM
1352@@ -3930,7 +3937,13 @@
1353 if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
1354
1355 wrong_offs:
1356- if (srv_force_recovery == 0 || moves_up == FALSE) {
1357+ if (srv_pass_corrupt_table && !trx_sys_sys_space(index->table->space)) {
1358+ index->table->is_corrupt = TRUE;
1359+ fil_space_set_corrupt(index->table->space);
1360+ }
1361+
1362+ if ((srv_force_recovery == 0 || moves_up == FALSE)
1363+ && srv_pass_corrupt_table <= 1) {
1364 ut_print_timestamp(stderr);
1365 buf_page_print(page_align(rec), 0);
1366 fprintf(stderr,
1367@@ -3981,7 +3994,8 @@
1368
1369 offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1370
1371- if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
1372+ if (UNIV_UNLIKELY(srv_force_recovery > 0)
1373+ || (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) {
1374 if (!rec_validate(rec, offsets)
1375 || !btr_index_rec_validate(rec, index, FALSE)) {
1376 fprintf(stderr,
b4e1fa2c
AM
1377diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
1378--- a/storage/innobase/srv/srv0srv.c 2010-12-04 15:37:50.602481253 +0900
1379+++ b/storage/innobase/srv/srv0srv.c 2010-12-04 15:38:18.209513823 +0900
adf0fb13 1380@@ -430,6 +430,7 @@
b4e1fa2c
AM
1381 UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
1382
1383 UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
1384+UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
1385
b4e1fa2c 1386 UNIV_INTERN ulint srv_dict_size_limit = 0;
11822e22 1387 /*-------------------------------------------*/
b4e1fa2c
AM
1388diff -ruN a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c
1389--- a/storage/innobase/srv/srv0start.c 2010-12-04 15:37:50.605491300 +0900
1390+++ b/storage/innobase/srv/srv0start.c 2010-12-04 15:38:18.212513722 +0900
adf0fb13 1391@@ -2149,6 +2149,13 @@
b4e1fa2c
AM
1392
1393 os_fast_mutex_free(&srv_os_test_mutex);
1394
1395+ if (!srv_file_per_table_original_value
1396+ && srv_pass_corrupt_table) {
1397+ fprintf(stderr, "InnoDB: Warning:"
d8778560
AM
1398+ " The option innodb_file_per_table is disabled,"
1399+ " so using the option innodb_pass_corrupt_table doesn't make sense.\n");
b4e1fa2c
AM
1400+ }
1401+
1402 if (srv_print_verbose_log) {
1403 ut_print_timestamp(stderr);
1404 fprintf(stderr,
This page took 0.961097 seconds and 4 git commands to generate.