]> git.pld-linux.org Git - packages/mysql.git/blob - innodb_pass_corrupt_table.patch
- exports for hiphop-php
[packages/mysql.git] / 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 diff -ruN a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
9 --- a/storage/innobase/btr/btr0btr.c    2010-11-03 07:01:13.000000000 +0900
10 +++ b/storage/innobase/btr/btr0btr.c    2010-12-04 15:38:18.110513593 +0900
11 @@ -691,6 +691,12 @@
12         root_page_no = dict_index_get_page(index);
13  
14         block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
15 +
16 +       if (srv_pass_corrupt_table && !block) {
17 +               return(0);
18 +       }
19 +       ut_a(block);
20 +
21         ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
22              == dict_table_is_comp(index->table));
23  #ifdef UNIV_BTR_DEBUG
24 @@ -977,6 +983,12 @@
25  
26         root = btr_root_get(index, &mtr);
27  
28 +       if (srv_pass_corrupt_table && !root) {
29 +               mtr_commit(&mtr);
30 +               return(0);
31 +       }
32 +       ut_a(root);
33 +
34         if (flag == BTR_N_LEAF_PAGES) {
35                 seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
36  
37 @@ -1433,6 +1445,13 @@
38         mtr_start(&mtr);
39  
40         root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
41 +
42 +       if (srv_pass_corrupt_table && !root) {
43 +               mtr_commit(&mtr);
44 +               return;
45 +       }
46 +       ut_a(root);
47 +       
48  #ifdef UNIV_BTR_DEBUG
49         ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
50                                     + root, space));
51 @@ -1455,6 +1474,12 @@
52         mtr_start(&mtr);
53  
54         root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
55 +
56 +       if (srv_pass_corrupt_table && !root) {
57 +               mtr_commit(&mtr);
58 +               return;
59 +       }
60 +       ut_a(root);
61  #ifdef UNIV_BTR_DEBUG
62         ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
63                                     + root, space));
64 @@ -1488,6 +1513,11 @@
65  
66         block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
67  
68 +       if (srv_pass_corrupt_table && !block) {
69 +               return;
70 +       }
71 +       ut_a(block);
72 +
73         btr_search_drop_page_hash_index(block);
74  
75         header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
76 diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
77 --- a/storage/innobase/btr/btr0cur.c    2010-12-03 17:30:16.239038936 +0900
78 +++ b/storage/innobase/btr/btr0cur.c    2010-12-04 15:38:18.114551906 +0900
79 @@ -250,6 +250,11 @@
80         case BTR_MODIFY_LEAF:
81                 mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
82                 get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
83 +
84 +               if (srv_pass_corrupt_table && !get_block) {
85 +                       return;
86 +               }
87 +               ut_a(get_block);
88  #ifdef UNIV_BTR_DEBUG
89                 ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
90  #endif /* UNIV_BTR_DEBUG */
91 @@ -263,6 +268,11 @@
92                         get_block = btr_block_get(space, zip_size,
93                                                   left_page_no,
94                                                   RW_X_LATCH, mtr);
95 +
96 +                       if (srv_pass_corrupt_table && !get_block) {
97 +                               return;
98 +                       }
99 +                       ut_a(get_block);
100  #ifdef UNIV_BTR_DEBUG
101                         ut_a(page_is_comp(get_block->frame)
102                              == page_is_comp(page));
103 @@ -274,6 +284,11 @@
104  
105                 get_block = btr_block_get(space, zip_size, page_no,
106                                           RW_X_LATCH, mtr);
107 +
108 +               if (srv_pass_corrupt_table && !get_block) {
109 +                       return;
110 +               }
111 +               ut_a(get_block);
112  #ifdef UNIV_BTR_DEBUG
113                 ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
114  #endif /* UNIV_BTR_DEBUG */
115 @@ -285,6 +300,11 @@
116                         get_block = btr_block_get(space, zip_size,
117                                                   right_page_no,
118                                                   RW_X_LATCH, mtr);
119 +
120 +                       if (srv_pass_corrupt_table && !get_block) {
121 +                               return;
122 +                       }
123 +                       ut_a(get_block);
124  #ifdef UNIV_BTR_DEBUG
125                         ut_a(page_is_comp(get_block->frame)
126                              == page_is_comp(page));
127 @@ -306,6 +326,11 @@
128                         get_block = btr_block_get(space, zip_size,
129                                                   left_page_no, mode, mtr);
130                         cursor->left_block = get_block;
131 +
132 +                       if (srv_pass_corrupt_table && !get_block) {
133 +                               return;
134 +                       }
135 +                       ut_a(get_block);
136  #ifdef UNIV_BTR_DEBUG
137                         ut_a(page_is_comp(get_block->frame)
138                              == page_is_comp(page));
139 @@ -316,6 +341,11 @@
140                 }
141  
142                 get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
143 +
144 +               if (srv_pass_corrupt_table && !get_block) {
145 +                       return;
146 +               }
147 +               ut_a(get_block);
148  #ifdef UNIV_BTR_DEBUG
149                 ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
150  #endif /* UNIV_BTR_DEBUG */
151 @@ -588,6 +618,19 @@
152                 file, line, mtr);
153  
154         if (block == NULL) {
155 +               if (srv_pass_corrupt_table
156 +                   && buf_mode != BUF_GET_IF_IN_POOL
157 +                   && buf_mode != BUF_GET_IF_IN_POOL_OR_WATCH) {
158 +                       page_cursor->block = 0;
159 +                       page_cursor->rec = 0;
160 +                       if (estimate) {
161 +                               cursor->path_arr->nth_rec = ULINT_UNDEFINED;
162 +                       }
163 +                       goto func_exit;
164 +               }
165 +               ut_a(buf_mode == BUF_GET_IF_IN_POOL
166 +                    || buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH);
167 +
168                 /* This must be a search to perform an insert/delete
169                 mark/ delete; try using the insert/delete buffer */
170  
171 @@ -662,6 +705,16 @@
172         block->check_index_page_at_flush = TRUE;
173         page = buf_block_get_frame(block);
174  
175 +       if (srv_pass_corrupt_table && !page) {
176 +               page_cursor->block = 0;
177 +               page_cursor->rec = 0;
178 +               if (estimate) {
179 +                       cursor->path_arr->nth_rec = ULINT_UNDEFINED;
180 +               }
181 +               goto func_exit;
182 +       }
183 +       ut_a(page);
184 +
185         if (rw_latch != RW_NO_LATCH) {
186  #ifdef UNIV_ZIP_DEBUG
187                 const page_zip_des_t*   page_zip
188 @@ -866,6 +919,17 @@
189                                          RW_NO_LATCH, NULL, BUF_GET,
190                                          file, line, mtr);
191                 page = buf_block_get_frame(block);
192 +
193 +               if (srv_pass_corrupt_table && !page) {
194 +                       page_cursor->block = 0;
195 +                       page_cursor->rec = 0;
196 +                       if (estimate) {
197 +                               cursor->path_arr->nth_rec = ULINT_UNDEFINED;
198 +                       }
199 +                       break;
200 +               }
201 +               ut_a(page);
202 +
203                 ut_ad(index->id == btr_page_get_index_id(page));
204  
205                 block->check_index_page_at_flush = TRUE;
206 @@ -986,6 +1050,14 @@
207                                          RW_NO_LATCH, NULL, BUF_GET,
208                                          file, line, mtr);
209                 page = buf_block_get_frame(block);
210 +
211 +               if (srv_pass_corrupt_table && !page) {
212 +                       page_cursor->block = 0;
213 +                       page_cursor->rec = 0;
214 +                       break;
215 +               }
216 +               ut_a(page);
217 +
218                 ut_ad(index->id == btr_page_get_index_id(page));
219  
220                 if (height == ULINT_UNDEFINED) {
221 @@ -1199,6 +1271,12 @@
222         *big_rec = NULL;
223  
224         block = btr_cur_get_block(cursor);
225 +
226 +       if (srv_pass_corrupt_table && !block) {
227 +               return(DB_CORRUPTION);
228 +       }
229 +       ut_a(block);
230 +
231         page = buf_block_get_frame(block);
232         index = cursor->index;
233         zip_size = buf_block_get_zip_size(block);
234 @@ -2925,6 +3003,11 @@
235  
236         block = btr_cur_get_block(cursor);
237  
238 +       if (srv_pass_corrupt_table && !block) {
239 +               return(DB_CORRUPTION);
240 +       }
241 +       ut_a(block);
242 +
243         ut_ad(page_is_leaf(buf_block_get_frame(block)));
244  
245         rec = btr_cur_get_rec(cursor);
246 @@ -3628,6 +3711,11 @@
247  
248                 page = btr_cur_get_page(&cursor);
249  
250 +               if (srv_pass_corrupt_table && !page) {
251 +                       break;
252 +               }
253 +               ut_a(page);
254 +
255                 rec = page_rec_get_next(page_get_infimum_rec(page));
256  
257                 if (!page_rec_is_supremum(rec)) {
258 diff -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)
299 diff -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
323 diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
324 --- a/storage/innobase/buf/buf0buf.c    2010-12-04 15:37:50.554565654 +0900
325 +++ b/storage/innobase/buf/buf0buf.c    2010-12-04 15:38:18.119548922 +0900
326 @@ -52,6 +52,7 @@
327  #include "log0recv.h"
328  #include "page0zip.h"
329  #include "trx0trx.h"
330 +#include "srv0start.h"
331  
332  /* prototypes for new functions added to ha_innodb.cc */
333  trx_t* innobase_get_trx();
334 @@ -1135,6 +1136,11 @@
335                         ready = buf_flush_ready_for_replace(&block->page);
336                         mutex_exit(&block->mutex);
337  
338 +                       if (block->page.is_corrupt) {
339 +                               /* corrupt page may remain, it can be skipped */
340 +                               break;
341 +                       }
342 +
343                         if (!ready) {
344  
345                                 return(block);
346 @@ -2479,6 +2485,13 @@
347                 return(NULL);
348         }
349  
350 +       if (srv_pass_corrupt_table <= 1) {
351 +               if (bpage->is_corrupt) {
352 +                       rw_lock_s_unlock(&buf_pool->page_hash_latch);
353 +                       return(NULL);
354 +               }
355 +       }
356 +
357         block_mutex = buf_page_get_mutex_enter(bpage);
358  
359         rw_lock_s_unlock(&buf_pool->page_hash_latch);
360 @@ -3059,6 +3072,13 @@
361                 return(NULL);
362         }
363  
364 +       if (srv_pass_corrupt_table <= 1) {
365 +               if (block->page.is_corrupt) {
366 +                       mutex_exit(block_mutex);
367 +                       return(NULL);
368 +               }
369 +       }
370 +
371         switch (buf_block_get_state(block)) {
372                 buf_page_t*     bpage;
373                 ibool           success;
374 @@ -3733,6 +3753,7 @@
375         bpage->newest_modification = 0;
376         bpage->oldest_modification = 0;
377         HASH_INVALIDATE(bpage, hash);
378 +       bpage->is_corrupt = FALSE;
379  #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
380         bpage->file_page_was_freed = FALSE;
381  #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
382 @@ -4322,6 +4343,7 @@
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  
390 @@ -4363,6 +4385,23 @@
391                               REFMAN "forcing-innodb-recovery.html\n"
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) {
396 +                               trx_t*  trx;
397 +
398 +                               fprintf(stderr,
399 +                                       "InnoDB: space %u will be treated as corrupt.\n",
400 +                                       bpage->space);
401 +                               fil_space_set_corrupt(bpage->space);
402 +
403 +                               trx = innobase_get_trx();
404 +                               if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) {
405 +                                       dict_table_set_corrupt_by_space(bpage->space, FALSE);
406 +                               } else {
407 +                                       dict_table_set_corrupt_by_space(bpage->space, TRUE);
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",
414 @@ -4370,6 +4409,7 @@
415                                 exit(1);
416                         }
417                 }
418 +               } /**/
419  
420                 if (recv_recovery_is_on()) {
421                         /* Pages must be uncompressed for crash recovery. */
422 @@ -4379,8 +4419,11 @@
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         }
434 diff -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
437 @@ -193,7 +193,14 @@
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
452 diff -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
455 @@ -54,6 +54,7 @@
456  #include "row0merge.h"
457  #include "m_ctype.h" /* my_isspace() */
458  #include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
459 +#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
460  
461  #include <ctype.h>
462  
463 @@ -750,7 +751,7 @@
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. */
472 @@ -1293,7 +1294,7 @@
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;
481 @@ -4332,6 +4333,12 @@
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;
494 @@ -4479,6 +4486,12 @@
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;
507 @@ -4671,6 +4684,13 @@
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);
514 +                               dict_table_stats_unlock(table, RW_X_LATCH);
515 +                               return;
516 +                       }
517 +
518                         size = btr_get_size(index, BTR_TOTAL_SIZE);
519  
520                         index->stat_index_size = size;
521 @@ -5467,4 +5487,42 @@
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 */
564 diff -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
567 @@ -96,6 +96,8 @@
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);
576 diff -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
579 @@ -235,6 +235,7 @@
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 */
587 @@ -1293,6 +1294,8 @@
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);
596 @@ -5267,6 +5270,34 @@
597         ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
598         ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
599  
600 +       if (srv_pass_corrupt_table == 1 && space->is_corrupt) {
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);
607 +                       buf_page_io_complete(message);
608 +               }
609 +               if (type == OS_FILE_READ) {
610 +                       return(DB_TABLESPACE_DELETED);
611 +               } else {
612 +                       return(DB_SUCCESS);
613 +               }
614 +       } else {
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 +               }
628  #ifdef UNIV_HOTBACKUP
629         /* In ibbackup do normal i/o, not aio */
630         if (type == OS_FILE_READ) {
631 @@ -5281,6 +5312,8 @@
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) {
640 @@ -5781,3 +5814,46 @@
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 +
687 diff -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) {
798 diff -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
801 @@ -3972,6 +3972,12 @@
802                 DBUG_RETURN(1);
803         }
804  
805 +       if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) {
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
814 @@ -3999,6 +4005,19 @@
815         /* Get pointer to a table object in InnoDB dictionary cache */
816         ib_table = dict_table_get(norm_name, TRUE);
817         
818 +       if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
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;
834 @@ -5163,6 +5182,10 @@
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  
845 @@ -5380,6 +5403,10 @@
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  
856 @@ -5556,6 +5583,10 @@
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  
867 @@ -5645,6 +5676,10 @@
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  
878 @@ -5666,6 +5701,10 @@
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         }
889 @@ -5692,6 +5731,10 @@
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  
900 @@ -5931,6 +5974,10 @@
901  
902         ha_statistic_increment(&SSV::ha_read_key_count);
903  
904 +       if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
905 +               DBUG_RETURN(HA_ERR_CRASHED);
906 +       }
907 +
908         index = prebuilt->index;
909  
910         if (UNIV_UNLIKELY(index == NULL)) {
911 @@ -5996,6 +6043,10 @@
912                 ret = DB_UNSUPPORTED;
913         }
914  
915 +       if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
916 +               DBUG_RETURN(HA_ERR_CRASHED);
917 +       }
918 +
919         switch (ret) {
920         case DB_SUCCESS:
921                 error = 0;
922 @@ -6111,6 +6162,10 @@
923  {
924         DBUG_ENTER("change_active_index");
925  
926 +       if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
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  
933 @@ -6201,6 +6256,10 @@
934  
935         DBUG_ENTER("general_fetch");
936  
937 +       if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
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);
944 @@ -6210,6 +6269,10 @@
945  
946         innodb_srv_conc_exit_innodb(prebuilt->trx);
947  
948 +       if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
949 +               DBUG_RETURN(HA_ERR_CRASHED);
950 +       }
951 +
952         switch (ret) {
953         case DB_SUCCESS:
954                 error = 0;
955 @@ -7476,10 +7539,18 @@
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  
974 @@ -7980,6 +8051,16 @@
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
991 @@ -8157,7 +8238,7 @@
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  
1000 @@ -8450,10 +8531,18 @@
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  
1019 @@ -8635,6 +8724,10 @@
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  
1030 @@ -9405,6 +9498,10 @@
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,
1041 @@ -11807,6 +11904,26 @@
1042    "0 (the default) disables automatic dumps.",
1043    NULL, NULL, 0, 0, UINT_MAX32, 0);
1044  
1045 +const char *corrupt_table_action_names[]=
1046 +{
1047 +  "assert", /* 0 */
1048 +  "warn", /* 1 */
1049 +  "salvage", /* 2 */
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,
1058 +  PLUGIN_VAR_RQCMDARG,
1059 +  "Warn corruptions of user tables as 'corrupt table' instead of not crashing itself, "
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.",
1063 +  NULL, NULL, 0, &corrupt_table_action_typelib);
1064 +
1065  static struct st_mysql_sys_var* innobase_system_variables[]= {
1066    MYSQL_SYSVAR(additional_mem_pool_size),
1067    MYSQL_SYSVAR(autoextend_increment),
1068 @@ -11893,6 +12010,7 @@
1069    MYSQL_SYSVAR(purge_threads),
1070    MYSQL_SYSVAR(purge_batch_size),
1071    MYSQL_SYSVAR(rollback_segments),
1072 +  MYSQL_SYSVAR(corrupt_table_action),
1073    NULL
1074  };
1075  
1076 diff -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);
1095 diff -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         }
1118 diff -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
1121 @@ -986,7 +986,7 @@
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.
1130 @@ -1433,6 +1433,7 @@
1131                                         0 if the block was never accessed
1132                                         in the buffer pool */
1133         /* @} */
1134 +       ibool           is_corrupt;
1135  # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
1136         ibool           file_page_was_freed;
1137                                         /*!< this is set to TRUE when fsp
1138 diff -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 */
1150 @@ -619,6 +619,12 @@
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)) {
1163 diff -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
1166 @@ -1245,6 +1245,15 @@
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
1182 diff -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
1185 @@ -640,6 +640,7 @@
1186                                 the AUTOINC lock on this table. */
1187                                 /* @} */
1188         /*----------------------*/
1189 +       ibool           is_corrupt;
1190  #endif /* !UNIV_HOTBACKUP */
1191  
1192  #ifdef UNIV_DEBUG
1193 diff -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
1196 @@ -750,6 +750,19 @@
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
1216 diff -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);
1240 diff -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 */
1252 diff -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  
1265 diff -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
1277 diff -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
1280 @@ -240,6 +240,7 @@
1281  extern ulint   srv_adaptive_flushing_method;
1282  
1283  extern ulint   srv_expand_import;
1284 +extern ulint   srv_pass_corrupt_table;
1285  
1286  extern ulint   srv_dict_size_limit;
1287  /*-------------------------------------------*/
1288 diff -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));
1302 diff -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;
1318 diff -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  
1335 diff -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
1338 @@ -3853,6 +3853,13 @@
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         /*
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,
1377 diff -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
1380 @@ -430,6 +430,7 @@
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  
1386  UNIV_INTERN ulint      srv_dict_size_limit = 0;
1387  /*-------------------------------------------*/
1388 diff -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
1391 @@ -2149,6 +2149,13 @@
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:"
1398 +                       " The option innodb_file_per_table is disabled,"
1399 +                       " so using the option innodb_pass_corrupt_table doesn't make sense.\n");
1400 +       }
1401 +
1402         if (srv_print_verbose_log) {
1403                 ut_print_timestamp(stderr);
1404                 fprintf(stderr,
This page took 1.004596 seconds and 3 git commands to generate.