]>
Commit | Line | Data |
---|---|---|
b4e1fa2c AM |
1 | # name : innodb_pass_corrupt_table.patch |
2 | # introduced : 11 or before | |
3 | # maintainer : Yasufumi | |
4 | # | |
5 | #!!! notice !!! | |
6 | # Any small change to this file in the main branch | |
7 | # should be done or reviewed by the maintainer! | |
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 | |
11822e22 | 11 | @@ -691,6 +691,12 @@ |
b4e1fa2c AM |
12 | root_page_no = dict_index_get_page(index); |
13 | ||
14 | block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr); | |
15 | + | |
16 | + if (srv_pass_corrupt_table && !block) { | |
17 | + return(0); | |
18 | + } | |
19 | + ut_a(block); | |
20 | + | |
21 | ut_a((ibool)!!page_is_comp(buf_block_get_frame(block)) | |
22 | == dict_table_is_comp(index->table)); | |
23 | #ifdef UNIV_BTR_DEBUG | |
11822e22 | 24 | @@ -977,6 +983,12 @@ |
b4e1fa2c AM |
25 | |
26 | root = btr_root_get(index, &mtr); | |
27 | ||
28 | + if (srv_pass_corrupt_table && !root) { | |
29 | + mtr_commit(&mtr); | |
30 | + return(0); | |
31 | + } | |
32 | + ut_a(root); | |
33 | + | |
34 | if (flag == BTR_N_LEAF_PAGES) { | |
35 | seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; | |
36 | ||
11822e22 | 37 | @@ -1433,6 +1445,13 @@ |
b4e1fa2c AM |
38 | mtr_start(&mtr); |
39 | ||
40 | root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr); | |
41 | + | |
42 | + if (srv_pass_corrupt_table && !root) { | |
43 | + mtr_commit(&mtr); | |
44 | + return; | |
45 | + } | |
46 | + ut_a(root); | |
47 | + | |
48 | #ifdef UNIV_BTR_DEBUG | |
49 | ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF | |
50 | + root, space)); | |
11822e22 | 51 | @@ -1455,6 +1474,12 @@ |
b4e1fa2c AM |
52 | mtr_start(&mtr); |
53 | ||
54 | root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr); | |
55 | + | |
56 | + if (srv_pass_corrupt_table && !root) { | |
57 | + mtr_commit(&mtr); | |
58 | + return; | |
59 | + } | |
60 | + ut_a(root); | |
61 | #ifdef UNIV_BTR_DEBUG | |
62 | ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP | |
63 | + root, space)); | |
11822e22 | 64 | @@ -1488,6 +1513,11 @@ |
b4e1fa2c AM |
65 | |
66 | block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr); | |
67 | ||
68 | + if (srv_pass_corrupt_table && !block) { | |
69 | + return; | |
70 | + } | |
71 | + ut_a(block); | |
72 | + | |
73 | btr_search_drop_page_hash_index(block); | |
74 | ||
75 | header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP; | |
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 | |
df1b5770 | 79 | @@ -250,6 +250,11 @@ |
b4e1fa2c AM |
80 | case BTR_MODIFY_LEAF: |
81 | mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH; | |
82 | get_block = btr_block_get(space, zip_size, page_no, mode, mtr); | |
83 | + | |
84 | + if (srv_pass_corrupt_table && !get_block) { | |
85 | + return; | |
86 | + } | |
87 | + ut_a(get_block); | |
88 | #ifdef UNIV_BTR_DEBUG | |
89 | ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); | |
90 | #endif /* UNIV_BTR_DEBUG */ | |
df1b5770 | 91 | @@ -263,6 +268,11 @@ |
b4e1fa2c AM |
92 | get_block = btr_block_get(space, zip_size, |
93 | left_page_no, | |
94 | RW_X_LATCH, mtr); | |
95 | + | |
96 | + if (srv_pass_corrupt_table && !get_block) { | |
97 | + return; | |
98 | + } | |
99 | + ut_a(get_block); | |
100 | #ifdef UNIV_BTR_DEBUG | |
101 | ut_a(page_is_comp(get_block->frame) | |
102 | == page_is_comp(page)); | |
df1b5770 | 103 | @@ -274,6 +284,11 @@ |
b4e1fa2c AM |
104 | |
105 | get_block = btr_block_get(space, zip_size, page_no, | |
106 | RW_X_LATCH, mtr); | |
107 | + | |
108 | + if (srv_pass_corrupt_table && !get_block) { | |
109 | + return; | |
110 | + } | |
111 | + ut_a(get_block); | |
112 | #ifdef UNIV_BTR_DEBUG | |
113 | ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); | |
114 | #endif /* UNIV_BTR_DEBUG */ | |
df1b5770 | 115 | @@ -285,6 +300,11 @@ |
b4e1fa2c AM |
116 | get_block = btr_block_get(space, zip_size, |
117 | right_page_no, | |
118 | RW_X_LATCH, mtr); | |
119 | + | |
120 | + if (srv_pass_corrupt_table && !get_block) { | |
121 | + return; | |
122 | + } | |
123 | + ut_a(get_block); | |
124 | #ifdef UNIV_BTR_DEBUG | |
125 | ut_a(page_is_comp(get_block->frame) | |
126 | == page_is_comp(page)); | |
df1b5770 | 127 | @@ -306,6 +326,11 @@ |
b4e1fa2c AM |
128 | get_block = btr_block_get(space, zip_size, |
129 | left_page_no, mode, mtr); | |
130 | cursor->left_block = get_block; | |
131 | + | |
132 | + if (srv_pass_corrupt_table && !get_block) { | |
133 | + return; | |
134 | + } | |
135 | + ut_a(get_block); | |
136 | #ifdef UNIV_BTR_DEBUG | |
137 | ut_a(page_is_comp(get_block->frame) | |
138 | == page_is_comp(page)); | |
df1b5770 | 139 | @@ -316,6 +341,11 @@ |
b4e1fa2c AM |
140 | } |
141 | ||
142 | get_block = btr_block_get(space, zip_size, page_no, mode, mtr); | |
143 | + | |
144 | + if (srv_pass_corrupt_table && !get_block) { | |
145 | + return; | |
146 | + } | |
147 | + ut_a(get_block); | |
148 | #ifdef UNIV_BTR_DEBUG | |
149 | ut_a(page_is_comp(get_block->frame) == page_is_comp(page)); | |
150 | #endif /* UNIV_BTR_DEBUG */ | |
df1b5770 | 151 | @@ -588,6 +618,19 @@ |
b4e1fa2c AM |
152 | file, line, mtr); |
153 | ||
154 | if (block == NULL) { | |
155 | + if (srv_pass_corrupt_table | |
156 | + && buf_mode != BUF_GET_IF_IN_POOL | |
157 | + && buf_mode != BUF_GET_IF_IN_POOL_OR_WATCH) { | |
158 | + page_cursor->block = 0; | |
159 | + page_cursor->rec = 0; | |
160 | + if (estimate) { | |
161 | + cursor->path_arr->nth_rec = ULINT_UNDEFINED; | |
162 | + } | |
163 | + goto func_exit; | |
164 | + } | |
165 | + ut_a(buf_mode == BUF_GET_IF_IN_POOL | |
166 | + || buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH); | |
167 | + | |
168 | /* This must be a search to perform an insert/delete | |
169 | mark/ delete; try using the insert/delete buffer */ | |
170 | ||
df1b5770 | 171 | @@ -662,6 +705,16 @@ |
b4e1fa2c AM |
172 | block->check_index_page_at_flush = TRUE; |
173 | page = buf_block_get_frame(block); | |
174 | ||
175 | + if (srv_pass_corrupt_table && !page) { | |
176 | + page_cursor->block = 0; | |
177 | + page_cursor->rec = 0; | |
178 | + if (estimate) { | |
179 | + cursor->path_arr->nth_rec = ULINT_UNDEFINED; | |
180 | + } | |
181 | + goto func_exit; | |
182 | + } | |
183 | + ut_a(page); | |
184 | + | |
185 | if (rw_latch != RW_NO_LATCH) { | |
186 | #ifdef UNIV_ZIP_DEBUG | |
187 | const page_zip_des_t* page_zip | |
df1b5770 | 188 | @@ -866,6 +919,17 @@ |
b4e1fa2c AM |
189 | RW_NO_LATCH, NULL, BUF_GET, |
190 | file, line, mtr); | |
191 | page = buf_block_get_frame(block); | |
192 | + | |
193 | + if (srv_pass_corrupt_table && !page) { | |
194 | + page_cursor->block = 0; | |
195 | + page_cursor->rec = 0; | |
196 | + if (estimate) { | |
197 | + cursor->path_arr->nth_rec = ULINT_UNDEFINED; | |
198 | + } | |
199 | + break; | |
200 | + } | |
201 | + ut_a(page); | |
202 | + | |
203 | ut_ad(index->id == btr_page_get_index_id(page)); | |
204 | ||
205 | block->check_index_page_at_flush = TRUE; | |
df1b5770 | 206 | @@ -986,6 +1050,14 @@ |
b4e1fa2c AM |
207 | RW_NO_LATCH, NULL, BUF_GET, |
208 | file, line, mtr); | |
209 | page = buf_block_get_frame(block); | |
210 | + | |
211 | + if (srv_pass_corrupt_table && !page) { | |
212 | + page_cursor->block = 0; | |
213 | + page_cursor->rec = 0; | |
214 | + break; | |
215 | + } | |
216 | + ut_a(page); | |
217 | + | |
218 | ut_ad(index->id == btr_page_get_index_id(page)); | |
219 | ||
220 | if (height == ULINT_UNDEFINED) { | |
df1b5770 | 221 | @@ -1199,6 +1271,12 @@ |
b4e1fa2c AM |
222 | *big_rec = NULL; |
223 | ||
224 | block = btr_cur_get_block(cursor); | |
225 | + | |
226 | + if (srv_pass_corrupt_table && !block) { | |
227 | + return(DB_CORRUPTION); | |
228 | + } | |
229 | + ut_a(block); | |
230 | + | |
231 | page = buf_block_get_frame(block); | |
232 | index = cursor->index; | |
233 | zip_size = buf_block_get_zip_size(block); | |
11822e22 | 234 | @@ -2925,6 +3003,11 @@ |
b4e1fa2c AM |
235 | |
236 | block = btr_cur_get_block(cursor); | |
237 | ||
238 | + if (srv_pass_corrupt_table && !block) { | |
239 | + return(DB_CORRUPTION); | |
240 | + } | |
241 | + ut_a(block); | |
242 | + | |
243 | ut_ad(page_is_leaf(buf_block_get_frame(block))); | |
244 | ||
245 | rec = btr_cur_get_rec(cursor); | |
11822e22 | 246 | @@ -3628,6 +3711,11 @@ |
b4e1fa2c AM |
247 | |
248 | page = btr_cur_get_page(&cursor); | |
249 | ||
250 | + if (srv_pass_corrupt_table && !page) { | |
251 | + break; | |
252 | + } | |
253 | + ut_a(page); | |
254 | + | |
df1b5770 AM |
255 | rec = page_rec_get_next(page_get_infimum_rec(page)); |
256 | ||
257 | if (!page_rec_is_supremum(rec)) { | |
b4e1fa2c AM |
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(); | |
adf0fb13 | 334 | @@ -1135,6 +1136,11 @@ |
b4e1fa2c AM |
335 | ready = buf_flush_ready_for_replace(&block->page); |
336 | mutex_exit(&block->mutex); | |
337 | ||
338 | + if (block->page.is_corrupt) { | |
339 | + /* corrupt page may remain, it can be skipped */ | |
340 | + break; | |
341 | + } | |
342 | + | |
343 | if (!ready) { | |
344 | ||
345 | return(block); | |
adf0fb13 | 346 | @@ -2479,6 +2485,13 @@ |
b4e1fa2c AM |
347 | return(NULL); |
348 | } | |
349 | ||
adf0fb13 | 350 | + if (srv_pass_corrupt_table <= 1) { |
b4e1fa2c AM |
351 | + if (bpage->is_corrupt) { |
352 | + rw_lock_s_unlock(&buf_pool->page_hash_latch); | |
353 | + return(NULL); | |
354 | + } | |
355 | + } | |
b4e1fa2c AM |
356 | + |
357 | block_mutex = buf_page_get_mutex_enter(bpage); | |
358 | ||
359 | rw_lock_s_unlock(&buf_pool->page_hash_latch); | |
f7ab7acd | 360 | @@ -3059,6 +3072,13 @@ |
b4e1fa2c AM |
361 | return(NULL); |
362 | } | |
363 | ||
adf0fb13 | 364 | + if (srv_pass_corrupt_table <= 1) { |
b4e1fa2c AM |
365 | + if (block->page.is_corrupt) { |
366 | + mutex_exit(block_mutex); | |
367 | + return(NULL); | |
368 | + } | |
369 | + } | |
b4e1fa2c AM |
370 | + |
371 | switch (buf_block_get_state(block)) { | |
372 | buf_page_t* bpage; | |
373 | ibool success; | |
f7ab7acd | 374 | @@ -3733,6 +3753,7 @@ |
b4e1fa2c AM |
375 | bpage->newest_modification = 0; |
376 | bpage->oldest_modification = 0; | |
377 | HASH_INVALIDATE(bpage, hash); | |
378 | + bpage->is_corrupt = FALSE; | |
df1b5770 | 379 | #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
b4e1fa2c | 380 | bpage->file_page_was_freed = FALSE; |
df1b5770 | 381 | #endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */ |
f7ab7acd | 382 | @@ -4322,6 +4343,7 @@ |
b4e1fa2c AM |
383 | (ulong) bpage->offset); |
384 | } | |
385 | ||
386 | + if (!srv_pass_corrupt_table || !bpage->is_corrupt) { | |
387 | /* From version 3.23.38 up we store the page checksum | |
388 | to the 4 first bytes of the page end lsn field */ | |
389 | ||
f7ab7acd | 390 | @@ -4363,6 +4385,23 @@ |
d8778560 | 391 | REFMAN "forcing-innodb-recovery.html\n" |
b4e1fa2c AM |
392 | "InnoDB: about forcing recovery.\n", stderr); |
393 | ||
394 | + if (srv_pass_corrupt_table && !trx_sys_sys_space(bpage->space) | |
395 | + && bpage->space < SRV_LOG_SPACE_FIRST_ID) { | |
adf0fb13 AM |
396 | + trx_t* trx; |
397 | + | |
b4e1fa2c AM |
398 | + fprintf(stderr, |
399 | + "InnoDB: space %u will be treated as corrupt.\n", | |
400 | + bpage->space); | |
401 | + fil_space_set_corrupt(bpage->space); | |
adf0fb13 AM |
402 | + |
403 | + trx = innobase_get_trx(); | |
404 | + if (trx && trx->dict_operation_lock_mode == RW_X_LATCH) { | |
b4e1fa2c | 405 | + dict_table_set_corrupt_by_space(bpage->space, FALSE); |
adf0fb13 AM |
406 | + } else { |
407 | + dict_table_set_corrupt_by_space(bpage->space, TRUE); | |
b4e1fa2c AM |
408 | + } |
409 | + bpage->is_corrupt = TRUE; | |
410 | + } else | |
411 | if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { | |
412 | fputs("InnoDB: Ending processing because of" | |
413 | " a corrupt database page.\n", | |
f7ab7acd | 414 | @@ -4370,6 +4409,7 @@ |
b4e1fa2c AM |
415 | exit(1); |
416 | } | |
417 | } | |
418 | + } /**/ | |
419 | ||
420 | if (recv_recovery_is_on()) { | |
421 | /* Pages must be uncompressed for crash recovery. */ | |
f7ab7acd | 422 | @@ -4379,8 +4419,11 @@ |
b4e1fa2c AM |
423 | |
424 | if (uncompressed && !recv_no_ibuf_operations) { | |
425 | ibuf_merge_or_delete_for_page( | |
426 | + /* Delete possible entries, if bpage is_corrupt */ | |
427 | + (srv_pass_corrupt_table && bpage->is_corrupt) ? NULL : | |
428 | (buf_block_t*) bpage, bpage->space, | |
429 | bpage->offset, buf_page_get_zip_size(bpage), | |
430 | + (srv_pass_corrupt_table && bpage->is_corrupt) ? FALSE : | |
431 | TRUE); | |
432 | } | |
433 | } | |
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 | |
adf0fb13 | 437 | @@ -193,7 +193,14 @@ |
b4e1fa2c AM |
438 | ((buf_block_t*) bpage)->frame, bpage, trx); |
439 | } | |
440 | thd_wait_end(NULL); | |
441 | + | |
442 | + if (srv_pass_corrupt_table) { | |
443 | + if (*err != DB_SUCCESS) { | |
444 | + bpage->is_corrupt = TRUE; | |
445 | + } | |
446 | + } else { | |
447 | ut_a(*err == DB_SUCCESS); | |
448 | + } | |
449 | ||
450 | if (sync) { | |
451 | /* The i/o is already completed when we arrive from | |
b4e1fa2c AM |
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 | |
adf0fb13 AM |
455 | @@ -54,6 +54,7 @@ |
456 | #include "row0merge.h" | |
b4e1fa2c | 457 | #include "m_ctype.h" /* my_isspace() */ |
d8778560 | 458 | #include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/ |
b4e1fa2c AM |
459 | +#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */ |
460 | ||
461 | #include <ctype.h> | |
462 | ||
adf0fb13 | 463 | @@ -750,7 +751,7 @@ |
b4e1fa2c AM |
464 | |
465 | mutex_exit(&(dict_sys->mutex)); | |
466 | ||
467 | - if (table != NULL) { | |
468 | + if (table != NULL && !table->is_corrupt) { | |
469 | /* If table->ibd_file_missing == TRUE, this will | |
470 | print an error message and return without doing | |
471 | anything. */ | |
adf0fb13 | 472 | @@ -1293,7 +1294,7 @@ |
b4e1fa2c AM |
473 | + dict_sys->size) > srv_dict_size_limit ) { |
474 | prev_table = UT_LIST_GET_PREV(table_LRU, table); | |
475 | ||
476 | - if (table == self || table->n_mysql_handles_opened) | |
477 | + if (table == self || table->n_mysql_handles_opened || table->is_corrupt) | |
478 | goto next_loop; | |
479 | ||
480 | cached_foreign_tables = 0; | |
adf0fb13 | 481 | @@ -4332,6 +4333,12 @@ |
b4e1fa2c AM |
482 | heap = mem_heap_create(1000); |
483 | ||
484 | while (index) { | |
485 | + if (table->is_corrupt) { | |
486 | + ut_a(srv_pass_corrupt_table); | |
487 | + mem_heap_free(heap); | |
488 | + return(FALSE); | |
489 | + } | |
490 | + | |
491 | size = btr_get_size(index, BTR_TOTAL_SIZE); | |
492 | ||
493 | index->stat_index_size = size; | |
adf0fb13 | 494 | @@ -4479,6 +4486,12 @@ |
b4e1fa2c AM |
495 | heap = mem_heap_create(1000); |
496 | ||
497 | while (index) { | |
498 | + if (table->is_corrupt) { | |
499 | + ut_a(srv_pass_corrupt_table); | |
500 | + mem_heap_free(heap); | |
501 | + return; | |
502 | + } | |
503 | + | |
504 | /*===========================================*/ | |
505 | { | |
506 | dict_table_t* sys_stats; | |
adf0fb13 | 507 | @@ -4671,6 +4684,13 @@ |
b4e1fa2c AM |
508 | || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO |
509 | && dict_index_is_clust(index)))) { | |
510 | ulint size; | |
511 | + | |
512 | + if (table->is_corrupt) { | |
513 | + ut_a(srv_pass_corrupt_table); | |
adf0fb13 | 514 | + dict_table_stats_unlock(table, RW_X_LATCH); |
b4e1fa2c AM |
515 | + return; |
516 | + } | |
517 | + | |
518 | size = btr_get_size(index, BTR_TOTAL_SIZE); | |
519 | ||
520 | index->stat_index_size = size; | |
adf0fb13 | 521 | @@ -5467,4 +5487,42 @@ |
b4e1fa2c AM |
522 | rw_lock_free(&dict_table_stats_latches[i]); |
523 | } | |
524 | } | |
525 | + | |
526 | +/************************************************************************* | |
527 | +set is_corrupt flag by space_id*/ | |
528 | + | |
529 | +void | |
530 | +dict_table_set_corrupt_by_space( | |
531 | +/*============================*/ | |
532 | + ulint space_id, | |
533 | + ibool need_mutex) | |
534 | +{ | |
535 | + dict_table_t* table; | |
536 | + ibool found = FALSE; | |
537 | + | |
538 | + ut_a(!trx_sys_sys_space(space_id) && space_id < SRV_LOG_SPACE_FIRST_ID); | |
539 | + | |
540 | + if (need_mutex) | |
541 | + mutex_enter(&(dict_sys->mutex)); | |
542 | + | |
543 | + table = UT_LIST_GET_FIRST(dict_sys->table_LRU); | |
544 | + | |
545 | + while (table) { | |
546 | + if (table->space == space_id) { | |
547 | + table->is_corrupt = TRUE; | |
548 | + found = TRUE; | |
549 | + } | |
550 | + | |
551 | + table = UT_LIST_GET_NEXT(table_LRU, table); | |
552 | + } | |
553 | + | |
554 | + if (need_mutex) | |
555 | + mutex_exit(&(dict_sys->mutex)); | |
556 | + | |
557 | + if (!found) { | |
558 | + fprintf(stderr, "InnoDB: space to be marked as " | |
559 | + "crashed was not found for id %lu.\n", | |
560 | + (ulong) space_id); | |
561 | + } | |
562 | +} | |
563 | #endif /* !UNIV_HOTBACKUP */ | |
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 | |
adf0fb13 | 567 | @@ -96,6 +96,8 @@ |
b4e1fa2c AM |
568 | /* The number of transactions that are either waiting on the |
569 | AUTOINC lock or have been granted the lock. */ | |
570 | table->n_waiting_or_granted_auto_inc_locks = 0; | |
571 | + | |
572 | + table->is_corrupt = FALSE; | |
573 | #endif /* !UNIV_HOTBACKUP */ | |
574 | ||
575 | ut_d(table->magic_n = DICT_TABLE_MAGIC_N); | |
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 | |
adf0fb13 | 579 | @@ -235,6 +235,7 @@ |
b4e1fa2c AM |
580 | file we have written to */ |
581 | ibool is_in_unflushed_spaces; /*!< TRUE if this space is | |
582 | currently in unflushed_spaces */ | |
583 | + ibool is_corrupt; | |
584 | UT_LIST_NODE_T(fil_space_t) space_list; | |
585 | /*!< list of all spaces */ | |
586 | ulint magic_n;/*!< FIL_SPACE_MAGIC_N */ | |
adf0fb13 | 587 | @@ -1293,6 +1294,8 @@ |
b4e1fa2c AM |
588 | ut_fold_string(name), space); |
589 | space->is_in_unflushed_spaces = FALSE; | |
590 | ||
591 | + space->is_corrupt = FALSE; | |
592 | + | |
593 | UT_LIST_ADD_LAST(space_list, fil_system->space_list, space); | |
594 | ||
595 | mutex_exit(&fil_system->mutex); | |
adf0fb13 | 596 | @@ -5267,6 +5270,34 @@ |
b4e1fa2c AM |
597 | ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0); |
598 | ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0); | |
599 | ||
adf0fb13 | 600 | + if (srv_pass_corrupt_table == 1 && space->is_corrupt) { |
b4e1fa2c AM |
601 | + /* should ignore i/o for the crashed space */ |
602 | + mutex_enter(&fil_system->mutex); | |
603 | + fil_node_complete_io(node, fil_system, type); | |
604 | + mutex_exit(&fil_system->mutex); | |
605 | + if (mode == OS_AIO_NORMAL) { | |
606 | + ut_a(space->purpose == FIL_TABLESPACE); | |
adf0fb13 | 607 | + buf_page_io_complete(message); |
b4e1fa2c AM |
608 | + } |
609 | + if (type == OS_FILE_READ) { | |
610 | + return(DB_TABLESPACE_DELETED); | |
611 | + } else { | |
612 | + return(DB_SUCCESS); | |
613 | + } | |
614 | + } else { | |
adf0fb13 AM |
615 | + if (srv_pass_corrupt_table > 1 && space->is_corrupt) { |
616 | + /* should ignore write i/o for the crashed space */ | |
617 | + if (type == OS_FILE_WRITE) { | |
618 | + mutex_enter(&fil_system->mutex); | |
619 | + fil_node_complete_io(node, fil_system, type); | |
620 | + mutex_exit(&fil_system->mutex); | |
621 | + if (mode == OS_AIO_NORMAL) { | |
622 | + ut_a(space->purpose == FIL_TABLESPACE); | |
623 | + buf_page_io_complete(message); | |
624 | + } | |
625 | + return(DB_SUCCESS); | |
626 | + } | |
627 | + } | |
b4e1fa2c AM |
628 | #ifdef UNIV_HOTBACKUP |
629 | /* In ibbackup do normal i/o, not aio */ | |
630 | if (type == OS_FILE_READ) { | |
adf0fb13 | 631 | @@ -5281,6 +5312,8 @@ |
b4e1fa2c AM |
632 | ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, |
633 | offset_low, offset_high, len, node, message, trx); | |
634 | #endif | |
635 | + } /**/ | |
636 | + | |
637 | ut_a(ret); | |
638 | ||
639 | if (mode == OS_AIO_SYNC) { | |
413cadc7 | 640 | @@ -5781,3 +5814,46 @@ |
b4e1fa2c AM |
641 | return 0; |
642 | } | |
643 | } | |
644 | + | |
645 | +/************************************************************************* | |
646 | +functions to access is_corrupt flag of fil_space_t*/ | |
647 | + | |
648 | +ibool | |
649 | +fil_space_is_corrupt( | |
650 | +/*=================*/ | |
651 | + ulint space_id) | |
652 | +{ | |
653 | + fil_space_t* space; | |
654 | + ibool ret = FALSE; | |
655 | + | |
656 | + mutex_enter(&fil_system->mutex); | |
657 | + | |
658 | + space = fil_space_get_by_id(space_id); | |
659 | + | |
660 | + if (space && space->is_corrupt) { | |
661 | + ret = TRUE; | |
662 | + } | |
663 | + | |
664 | + mutex_exit(&fil_system->mutex); | |
665 | + | |
666 | + return(ret); | |
667 | +} | |
668 | + | |
669 | +void | |
670 | +fil_space_set_corrupt( | |
671 | +/*==================*/ | |
672 | + ulint space_id) | |
673 | +{ | |
674 | + fil_space_t* space; | |
675 | + | |
676 | + mutex_enter(&fil_system->mutex); | |
677 | + | |
678 | + space = fil_space_get_by_id(space_id); | |
679 | + | |
680 | + if (space) { | |
681 | + space->is_corrupt = TRUE; | |
682 | + } | |
683 | + | |
684 | + mutex_exit(&fil_system->mutex); | |
685 | +} | |
686 | + | |
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 | |
adf0fb13 | 801 | @@ -3972,6 +3972,12 @@ |
b4e1fa2c AM |
802 | DBUG_RETURN(1); |
803 | } | |
804 | ||
adf0fb13 | 805 | + if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) { |
b4e1fa2c AM |
806 | + free_share(share); |
807 | + | |
808 | + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); | |
809 | + } | |
810 | + | |
811 | /* Create buffers for packing the fields of a record. Why | |
812 | table->reclength did not work here? Obviously, because char | |
813 | fields when packed actually became 1 byte longer, when we also | |
adf0fb13 | 814 | @@ -3999,6 +4005,19 @@ |
b4e1fa2c AM |
815 | /* Get pointer to a table object in InnoDB dictionary cache */ |
816 | ib_table = dict_table_get(norm_name, TRUE); | |
817 | ||
adf0fb13 | 818 | + if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) { |
b4e1fa2c AM |
819 | + free_share(share); |
820 | + my_free(upd_buff); | |
821 | + | |
822 | + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); | |
823 | + } | |
824 | + | |
825 | + if (share->ib_table) { | |
826 | + ut_a(share->ib_table == ib_table); | |
827 | + } else { | |
828 | + share->ib_table = ib_table; | |
829 | + } | |
830 | + | |
831 | if (NULL == ib_table) { | |
832 | if (is_part && retries < 10) { | |
833 | ++retries; | |
adf0fb13 | 834 | @@ -5163,6 +5182,10 @@ |
b4e1fa2c AM |
835 | |
836 | ha_statistic_increment(&SSV::ha_write_count); | |
837 | ||
838 | + if (share->ib_table->is_corrupt) { | |
839 | + DBUG_RETURN(HA_ERR_CRASHED); | |
840 | + } | |
841 | + | |
842 | if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) | |
843 | table->timestamp_field->set_time(); | |
844 | ||
adf0fb13 | 845 | @@ -5380,6 +5403,10 @@ |
b4e1fa2c AM |
846 | func_exit: |
847 | innobase_active_small(); | |
848 | ||
849 | + if (share->ib_table->is_corrupt) { | |
850 | + DBUG_RETURN(HA_ERR_CRASHED); | |
851 | + } | |
852 | + | |
853 | DBUG_RETURN(error_result); | |
854 | } | |
855 | ||
adf0fb13 | 856 | @@ -5556,6 +5583,10 @@ |
b4e1fa2c AM |
857 | |
858 | ha_statistic_increment(&SSV::ha_update_count); | |
859 | ||
860 | + if (share->ib_table->is_corrupt) { | |
861 | + DBUG_RETURN(HA_ERR_CRASHED); | |
862 | + } | |
863 | + | |
864 | if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) | |
865 | table->timestamp_field->set_time(); | |
866 | ||
adf0fb13 | 867 | @@ -5645,6 +5676,10 @@ |
b4e1fa2c AM |
868 | |
869 | innobase_active_small(); | |
870 | ||
871 | + if (share->ib_table->is_corrupt) { | |
872 | + DBUG_RETURN(HA_ERR_CRASHED); | |
873 | + } | |
874 | + | |
875 | DBUG_RETURN(error); | |
876 | } | |
877 | ||
adf0fb13 | 878 | @@ -5666,6 +5701,10 @@ |
b4e1fa2c AM |
879 | |
880 | ha_statistic_increment(&SSV::ha_delete_count); | |
881 | ||
882 | + if (share->ib_table->is_corrupt) { | |
883 | + DBUG_RETURN(HA_ERR_CRASHED); | |
884 | + } | |
885 | + | |
886 | if (!prebuilt->upd_node) { | |
887 | row_get_prebuilt_update_vector(prebuilt); | |
888 | } | |
adf0fb13 | 889 | @@ -5692,6 +5731,10 @@ |
b4e1fa2c AM |
890 | |
891 | innobase_active_small(); | |
892 | ||
893 | + if (share->ib_table->is_corrupt) { | |
894 | + DBUG_RETURN(HA_ERR_CRASHED); | |
895 | + } | |
896 | + | |
897 | DBUG_RETURN(error); | |
898 | } | |
899 | ||
adf0fb13 | 900 | @@ -5931,6 +5974,10 @@ |
b4e1fa2c AM |
901 | |
902 | ha_statistic_increment(&SSV::ha_read_key_count); | |
903 | ||
adf0fb13 | 904 | + if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { |
b4e1fa2c AM |
905 | + DBUG_RETURN(HA_ERR_CRASHED); |
906 | + } | |
907 | + | |
908 | index = prebuilt->index; | |
909 | ||
910 | if (UNIV_UNLIKELY(index == NULL)) { | |
adf0fb13 | 911 | @@ -5996,6 +6043,10 @@ |
b4e1fa2c AM |
912 | ret = DB_UNSUPPORTED; |
913 | } | |
914 | ||
adf0fb13 | 915 | + if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { |
b4e1fa2c AM |
916 | + DBUG_RETURN(HA_ERR_CRASHED); |
917 | + } | |
918 | + | |
919 | switch (ret) { | |
920 | case DB_SUCCESS: | |
921 | error = 0; | |
adf0fb13 | 922 | @@ -6111,6 +6162,10 @@ |
b4e1fa2c AM |
923 | { |
924 | DBUG_ENTER("change_active_index"); | |
925 | ||
adf0fb13 | 926 | + if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { |
b4e1fa2c AM |
927 | + DBUG_RETURN(HA_ERR_CRASHED); |
928 | + } | |
929 | + | |
930 | ut_ad(user_thd == ha_thd()); | |
931 | ut_a(prebuilt->trx == thd_to_trx(user_thd)); | |
932 | ||
adf0fb13 | 933 | @@ -6201,6 +6256,10 @@ |
b4e1fa2c AM |
934 | |
935 | DBUG_ENTER("general_fetch"); | |
936 | ||
adf0fb13 | 937 | + if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { |
b4e1fa2c AM |
938 | + DBUG_RETURN(HA_ERR_CRASHED); |
939 | + } | |
940 | + | |
941 | ut_a(prebuilt->trx == thd_to_trx(user_thd)); | |
942 | ||
943 | innodb_srv_conc_enter_innodb(prebuilt->trx); | |
adf0fb13 | 944 | @@ -6210,6 +6269,10 @@ |
b4e1fa2c AM |
945 | |
946 | innodb_srv_conc_exit_innodb(prebuilt->trx); | |
947 | ||
adf0fb13 | 948 | + if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) { |
b4e1fa2c AM |
949 | + DBUG_RETURN(HA_ERR_CRASHED); |
950 | + } | |
951 | + | |
952 | switch (ret) { | |
953 | case DB_SUCCESS: | |
954 | error = 0; | |
adf0fb13 | 955 | @@ -7476,10 +7539,18 @@ |
b4e1fa2c AM |
956 | |
957 | update_thd(ha_thd()); | |
958 | ||
959 | + if (share->ib_table->is_corrupt) { | |
960 | + DBUG_RETURN(HA_ERR_CRASHED); | |
961 | + } | |
962 | + | |
963 | /* Truncate the table in InnoDB */ | |
964 | ||
965 | error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx); | |
966 | ||
967 | + if (share->ib_table->is_corrupt) { | |
968 | + DBUG_RETURN(HA_ERR_CRASHED); | |
969 | + } | |
970 | + | |
971 | error = convert_error_code_to_mysql(error, prebuilt->table->flags, | |
972 | NULL); | |
973 | ||
adf0fb13 | 974 | @@ -7980,6 +8051,16 @@ |
b4e1fa2c AM |
975 | return(ranges + (double) rows / (double) total_rows * time_for_scan); |
976 | } | |
977 | ||
978 | +UNIV_INTERN | |
979 | +bool | |
980 | +ha_innobase::is_corrupt() const | |
981 | +{ | |
982 | + if (share->ib_table) | |
983 | + return ((bool)share->ib_table->is_corrupt); | |
984 | + else | |
985 | + return (FALSE); | |
986 | +} | |
987 | + | |
988 | /*********************************************************************//** | |
989 | Calculates the key number used inside MySQL for an Innobase index. We will | |
990 | first check the "index translation table" for a match of the index to get | |
adf0fb13 | 991 | @@ -8157,7 +8238,7 @@ |
b4e1fa2c AM |
992 | ib_table = prebuilt->table; |
993 | ||
994 | if (flag & HA_STATUS_TIME) { | |
995 | - if (called_from_analyze || innobase_stats_on_metadata) { | |
996 | + if ((called_from_analyze || innobase_stats_on_metadata) && !share->ib_table->is_corrupt) { | |
997 | /* In sql_show we call with this flag: update | |
998 | then statistics so that they are up-to-date */ | |
999 | ||
adf0fb13 | 1000 | @@ -8450,10 +8531,18 @@ |
b4e1fa2c AM |
1001 | THD* thd, /*!< in: connection thread handle */ |
1002 | HA_CHECK_OPT* check_opt) /*!< in: currently ignored */ | |
1003 | { | |
1004 | + if (share->ib_table->is_corrupt) { | |
1005 | + return(HA_ADMIN_CORRUPT); | |
1006 | + } | |
1007 | + | |
1008 | /* Simply call ::info() with all the flags */ | |
1009 | info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE, | |
1010 | true /* called from analyze */); | |
1011 | ||
1012 | + if (share->ib_table->is_corrupt) { | |
1013 | + return(HA_ADMIN_CORRUPT); | |
1014 | + } | |
1015 | + | |
1016 | return(0); | |
1017 | } | |
1018 | ||
adf0fb13 | 1019 | @@ -8635,6 +8724,10 @@ |
b4e1fa2c AM |
1020 | my_error(ER_QUERY_INTERRUPTED, MYF(0)); |
1021 | } | |
1022 | ||
1023 | + if (share->ib_table->is_corrupt) { | |
1024 | + return(HA_ADMIN_CORRUPT); | |
1025 | + } | |
1026 | + | |
1027 | DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT); | |
1028 | } | |
1029 | ||
adf0fb13 | 1030 | @@ -9405,6 +9498,10 @@ |
b4e1fa2c AM |
1031 | |
1032 | update_thd(thd); | |
1033 | ||
1034 | + if (share->ib_table->is_corrupt) { | |
1035 | + DBUG_RETURN(HA_ERR_CRASHED); | |
1036 | + } | |
1037 | + | |
1038 | if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) { | |
1039 | ut_print_timestamp(stderr); | |
1040 | fprintf(stderr, | |
adf0fb13 | 1041 | @@ -11807,6 +11904,26 @@ |
b4e1fa2c AM |
1042 | "0 (the default) disables automatic dumps.", |
1043 | NULL, NULL, 0, 0, UINT_MAX32, 0); | |
1044 | ||
a9ee80b9 ER |
1045 | +const char *corrupt_table_action_names[]= |
1046 | +{ | |
1047 | + "assert", /* 0 */ | |
1048 | + "warn", /* 1 */ | |
adf0fb13 | 1049 | + "salvage", /* 2 */ |
a9ee80b9 ER |
1050 | + NullS |
1051 | +}; | |
1052 | +TYPELIB corrupt_table_action_typelib= | |
1053 | +{ | |
1054 | + array_elements(corrupt_table_action_names) - 1, "corrupt_table_action_typelib", | |
1055 | + corrupt_table_action_names, NULL | |
1056 | +}; | |
1057 | +static MYSQL_SYSVAR_ENUM(corrupt_table_action, srv_pass_corrupt_table, | |
b4e1fa2c | 1058 | + PLUGIN_VAR_RQCMDARG, |
a9ee80b9 | 1059 | + "Warn corruptions of user tables as 'corrupt table' instead of not crashing itself, " |
b4e1fa2c AM |
1060 | + "when used with file_per_table. " |
1061 | + "All file io for the datafile after detected as corrupt are disabled, " | |
1062 | + "except for the deletion.", | |
a9ee80b9 | 1063 | + NULL, NULL, 0, &corrupt_table_action_typelib); |
b4e1fa2c AM |
1064 | + |
1065 | static struct st_mysql_sys_var* innobase_system_variables[]= { | |
1066 | MYSQL_SYSVAR(additional_mem_pool_size), | |
1067 | MYSQL_SYSVAR(autoextend_increment), | |
adf0fb13 | 1068 | @@ -11893,6 +12010,7 @@ |
b4e1fa2c AM |
1069 | MYSQL_SYSVAR(purge_threads), |
1070 | MYSQL_SYSVAR(purge_batch_size), | |
11822e22 | 1071 | MYSQL_SYSVAR(rollback_segments), |
a9ee80b9 | 1072 | + MYSQL_SYSVAR(corrupt_table_action), |
b4e1fa2c AM |
1073 | NULL |
1074 | }; | |
1075 | ||
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 | |
adf0fb13 | 1121 | @@ -986,7 +986,7 @@ |
b4e1fa2c AM |
1122 | const buf_block_t* block) /*!< in: pointer to the control block */ |
1123 | __attribute__((pure)); | |
1124 | #else /* UNIV_DEBUG */ | |
1125 | -# define buf_block_get_frame(block) (block)->frame | |
1126 | +# define buf_block_get_frame(block) (block ? (block)->frame : 0) | |
1127 | #endif /* UNIV_DEBUG */ | |
1128 | /*********************************************************************//** | |
1129 | Gets the space id of a block. | |
adf0fb13 | 1130 | @@ -1433,6 +1433,7 @@ |
b4e1fa2c AM |
1131 | 0 if the block was never accessed |
1132 | in the buffer pool */ | |
1133 | /* @} */ | |
1134 | + ibool is_corrupt; | |
df1b5770 | 1135 | # if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG |
b4e1fa2c AM |
1136 | ibool file_page_was_freed; |
1137 | /*!< this is set to TRUE when fsp | |
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 */ | |
11822e22 | 1150 | @@ -619,6 +619,12 @@ |
b4e1fa2c AM |
1151 | /*================*/ |
1152 | const buf_block_t* block) /*!< in: pointer to the control block */ | |
1153 | { | |
1154 | + ut_a(srv_pass_corrupt_table || block); | |
1155 | + | |
1156 | + if (srv_pass_corrupt_table && !block) { | |
1157 | + return(0); | |
1158 | + } | |
1159 | + | |
1160 | ut_ad(block); | |
1161 | ||
1162 | switch (buf_block_get_state(block)) { | |
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 | |
11822e22 | 1166 | @@ -1245,6 +1245,15 @@ |
b4e1fa2c AM |
1167 | dict_close(void); |
1168 | /*============*/ | |
1169 | ||
1170 | +/************************************************************************* | |
1171 | +set is_corrupt flag by space_id*/ | |
1172 | + | |
1173 | +void | |
1174 | +dict_table_set_corrupt_by_space( | |
1175 | +/*============================*/ | |
1176 | + ulint space_id, | |
1177 | + ibool need_mutex); | |
1178 | + | |
1179 | #ifndef UNIV_NONINL | |
1180 | #include "dict0dict.ic" | |
1181 | #endif | |
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 | |
adf0fb13 | 1185 | @@ -640,6 +640,7 @@ |
b4e1fa2c AM |
1186 | the AUTOINC lock on this table. */ |
1187 | /* @} */ | |
1188 | /*----------------------*/ | |
1189 | + ibool is_corrupt; | |
1190 | #endif /* !UNIV_HOTBACKUP */ | |
1191 | ||
1192 | #ifdef UNIV_DEBUG | |
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 | |
413cadc7 | 1196 | @@ -750,6 +750,19 @@ |
b4e1fa2c AM |
1197 | fil_system_hash_nodes(void); |
1198 | /*========================*/ | |
1199 | ||
1200 | +/************************************************************************* | |
1201 | +functions to access is_corrupt flag of fil_space_t*/ | |
1202 | + | |
1203 | +ibool | |
1204 | +fil_space_is_corrupt( | |
1205 | +/*=================*/ | |
1206 | + ulint space_id); | |
1207 | + | |
1208 | +void | |
1209 | +fil_space_set_corrupt( | |
1210 | +/*==================*/ | |
1211 | + ulint space_id); | |
1212 | + | |
1213 | typedef struct fil_space_struct fil_space_t; | |
1214 | ||
1215 | #endif | |
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 | |
adf0fb13 | 1280 | @@ -240,6 +240,7 @@ |
b4e1fa2c AM |
1281 | extern ulint srv_adaptive_flushing_method; |
1282 | ||
1283 | extern ulint srv_expand_import; | |
1284 | +extern ulint srv_pass_corrupt_table; | |
1285 | ||
b4e1fa2c | 1286 | extern ulint srv_dict_size_limit; |
11822e22 | 1287 | /*-------------------------------------------*/ |
b4e1fa2c AM |
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 | |
adf0fb13 | 1338 | @@ -3853,6 +3853,13 @@ |
b4e1fa2c AM |
1339 | /* PHASE 4: Look for matching records in a loop */ |
1340 | ||
1341 | rec = btr_pcur_get_rec(pcur); | |
1342 | + | |
1343 | + if (srv_pass_corrupt_table && !rec) { | |
1344 | + err = DB_CORRUPTION; | |
1345 | + goto lock_wait_or_error; | |
1346 | + } | |
1347 | + ut_a(rec); | |
1348 | + | |
1349 | ut_ad(!!page_rec_is_comp(rec) == comp); | |
1350 | #ifdef UNIV_SEARCH_DEBUG | |
1351 | /* | |
adf0fb13 AM |
1352 | @@ -3930,7 +3937,13 @@ |
1353 | if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) { | |
1354 | ||
1355 | wrong_offs: | |
1356 | - if (srv_force_recovery == 0 || moves_up == FALSE) { | |
1357 | + if (srv_pass_corrupt_table && !trx_sys_sys_space(index->table->space)) { | |
1358 | + index->table->is_corrupt = TRUE; | |
1359 | + fil_space_set_corrupt(index->table->space); | |
1360 | + } | |
1361 | + | |
1362 | + if ((srv_force_recovery == 0 || moves_up == FALSE) | |
1363 | + && srv_pass_corrupt_table <= 1) { | |
1364 | ut_print_timestamp(stderr); | |
1365 | buf_page_print(page_align(rec), 0); | |
1366 | fprintf(stderr, | |
1367 | @@ -3981,7 +3994,8 @@ | |
1368 | ||
1369 | offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); | |
1370 | ||
1371 | - if (UNIV_UNLIKELY(srv_force_recovery > 0)) { | |
1372 | + if (UNIV_UNLIKELY(srv_force_recovery > 0) | |
1373 | + || (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) { | |
1374 | if (!rec_validate(rec, offsets) | |
1375 | || !btr_index_rec_validate(rec, index, FALSE)) { | |
1376 | fprintf(stderr, | |
b4e1fa2c AM |
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 | |
adf0fb13 | 1380 | @@ -430,6 +430,7 @@ |
b4e1fa2c AM |
1381 | UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */ |
1382 | ||
1383 | UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */ | |
1384 | +UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */ | |
1385 | ||
b4e1fa2c | 1386 | UNIV_INTERN ulint srv_dict_size_limit = 0; |
11822e22 | 1387 | /*-------------------------------------------*/ |
b4e1fa2c AM |
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 | |
adf0fb13 | 1391 | @@ -2149,6 +2149,13 @@ |
b4e1fa2c AM |
1392 | |
1393 | os_fast_mutex_free(&srv_os_test_mutex); | |
1394 | ||
1395 | + if (!srv_file_per_table_original_value | |
1396 | + && srv_pass_corrupt_table) { | |
1397 | + fprintf(stderr, "InnoDB: Warning:" | |
d8778560 AM |
1398 | + " The option innodb_file_per_table is disabled," |
1399 | + " so using the option innodb_pass_corrupt_table doesn't make sense.\n"); | |
b4e1fa2c AM |
1400 | + } |
1401 | + | |
1402 | if (srv_print_verbose_log) { | |
1403 | ut_print_timestamp(stderr); | |
1404 | fprintf(stderr, |