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