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