@@ -421,6 +421,8 @@ class AbstractCallback
421
421
return (m_page_size);
422
422
}
423
423
424
+ const char * filename () const { return m_filepath; }
425
+
424
426
/* *
425
427
Called for every page in the tablespace. If the page was not
426
428
updated then its state must be set to BUF_PAGE_NOT_USED. For
@@ -437,6 +439,8 @@ class AbstractCallback
437
439
@return the space id of the tablespace */
438
440
virtual ulint get_space_id () const UNIV_NOTHROW = 0;
439
441
442
+ bool is_interrupted () const { return trx_is_interrupted (m_trx); }
443
+
440
444
protected:
441
445
/* *
442
446
Get the data page depending on the table type, compressed or not.
@@ -451,18 +455,6 @@ class AbstractCallback
451
455
return (buf_block_get_frame (block));
452
456
}
453
457
454
- /* * Check for session interrupt. If required we could
455
- even flush to disk here every N pages.
456
- @retval DB_SUCCESS or error code */
457
- dberr_t periodic_check () UNIV_NOTHROW
458
- {
459
- if (trx_is_interrupted (m_trx)) {
460
- return (DB_INTERRUPTED);
461
- }
462
-
463
- return (DB_SUCCESS);
464
- }
465
-
466
458
/* *
467
459
Get the physical offset of the extent descriptor within the page.
468
460
@param page_no - page number of the extent descriptor
@@ -732,11 +724,7 @@ FetchIndexRootPages::operator() (
732
724
os_offset_t offset,
733
725
buf_block_t * block) UNIV_NOTHROW
734
726
{
735
- dberr_t err;
736
-
737
- if ((err = periodic_check ()) != DB_SUCCESS) {
738
- return (err);
739
- }
727
+ if (is_interrupted ()) return DB_INTERRUPTED;
740
728
741
729
const page_t * page = get_frame (block);
742
730
@@ -749,9 +737,9 @@ FetchIndexRootPages::operator() (
749
737
block->page .offset ,
750
738
(ulint) (offset / m_page_size));
751
739
752
- err = DB_CORRUPTION;
740
+ return DB_CORRUPTION;
753
741
} else if (page_type == FIL_PAGE_TYPE_XDES) {
754
- err = set_current_xdes (block->page .offset , page);
742
+ return set_current_xdes (block->page .offset , page);
755
743
} else if (page_type == FIL_PAGE_INDEX
756
744
&& !is_free (block->page .offset )
757
745
&& is_root_page (page)) {
@@ -776,7 +764,7 @@ FetchIndexRootPages::operator() (
776
764
}
777
765
}
778
766
779
- return (err) ;
767
+ return DB_SUCCESS ;
780
768
}
781
769
782
770
/* *
@@ -900,14 +888,6 @@ class PageConverter : public AbstractCallback {
900
888
os_offset_t offset,
901
889
buf_block_t * block) UNIV_NOTHROW;
902
890
private:
903
-
904
- /* * Status returned by PageConverter::validate() */
905
- enum import_page_status_t {
906
- IMPORT_PAGE_STATUS_OK, /* !< Page is OK */
907
- IMPORT_PAGE_STATUS_ALL_ZERO, /* !< Page is all zeros */
908
- IMPORT_PAGE_STATUS_CORRUPTED /* !< Page is corrupted */
909
- };
910
-
911
891
/* *
912
892
Update the page, set the space id, max trx id and index id.
913
893
@param block - block read from file
@@ -917,17 +897,6 @@ class PageConverter : public AbstractCallback {
917
897
buf_block_t * block,
918
898
ulint& page_type) UNIV_NOTHROW;
919
899
920
- #if defined UNIV_DEBUG
921
- /* *
922
- @return true error condition is enabled. */
923
- bool trigger_corruption () UNIV_NOTHROW
924
- {
925
- return (false );
926
- }
927
- #else
928
- #define trigger_corruption () (false )
929
- #endif /* UNIV_DEBUG */
930
-
931
900
/* *
932
901
Update the space, index id, trx id.
933
902
@param block - block to convert
@@ -940,15 +909,6 @@ class PageConverter : public AbstractCallback {
940
909
@retval DB_SUCCESS or error code */
941
910
dberr_t update_records (buf_block_t * block) UNIV_NOTHROW;
942
911
943
- /* *
944
- Validate the page, check for corruption.
945
- @param offset - physical offset within file.
946
- @param page - page read from file.
947
- @return 0 on success, 1 if all zero, 2 if corrupted */
948
- import_page_status_t validate (
949
- os_offset_t offset,
950
- buf_block_t * page) UNIV_NOTHROW;
951
-
952
912
/* *
953
913
Validate the space flags and update tablespace header page.
954
914
@param block - block read from file, not from the buffer pool.
@@ -2075,97 +2035,24 @@ PageConverter::update_page(
2075
2035
return (DB_CORRUPTION);
2076
2036
}
2077
2037
2078
- /* *
2079
- Validate the page
2080
- @param offset - physical offset within file.
2081
- @param page - page read from file.
2082
- @return status */
2083
- PageConverter::import_page_status_t
2084
- PageConverter::validate (
2085
- os_offset_t offset,
2086
- buf_block_t * block) UNIV_NOTHROW
2087
- {
2088
- buf_frame_t * page = get_frame (block);
2089
-
2090
- /* Check that the page number corresponds to the offset in
2091
- the file. Flag as corrupt if it doesn't. Disable the check
2092
- for LSN in buf_page_is_corrupted() */
2093
-
2094
- if (buf_page_is_corrupted (false , page, get_zip_size (), NULL )
2095
- || (page_get_page_no (page) != offset / m_page_size
2096
- && page_get_page_no (page) != 0 )) {
2097
-
2098
- return (IMPORT_PAGE_STATUS_CORRUPTED);
2099
-
2100
- } else if (offset > 0 && page_get_page_no (page) == 0 ) {
2101
- ulint checksum;
2102
-
2103
- checksum = mach_read_from_4 (page + FIL_PAGE_SPACE_OR_CHKSUM);
2104
- if (checksum != 0 ) {
2105
- /* Checksum check passed in buf_page_is_corrupted(). */
2106
- ib_logf (IB_LOG_LEVEL_WARN,
2107
- " %s: Page %lu checksum " ULINTPF
2108
- " should be zero." ,
2109
- m_filepath, (ulong) (offset / m_page_size),
2110
- checksum);
2111
- }
2112
-
2113
- const byte* b = page + FIL_PAGE_OFFSET;
2114
- const byte* e = page + m_page_size
2115
- - FIL_PAGE_END_LSN_OLD_CHKSUM;
2116
-
2117
- /* If the page number is zero and offset > 0 then
2118
- the entire page MUST consist of zeroes. If not then
2119
- we flag it as corrupt. */
2120
-
2121
- while (b != e) {
2122
-
2123
- if (*b++ && !trigger_corruption ()) {
2124
- return (IMPORT_PAGE_STATUS_CORRUPTED);
2125
- }
2126
- }
2127
-
2128
- /* The page is all zero: do nothing. */
2129
- return (IMPORT_PAGE_STATUS_ALL_ZERO);
2130
- }
2131
-
2132
- return (IMPORT_PAGE_STATUS_OK);
2133
- }
2134
-
2135
2038
/* *
2136
2039
Called for every page in the tablespace. If the page was not
2137
2040
updated then its state must be set to BUF_PAGE_NOT_USED.
2138
- @param offset - physical offset within the file
2139
2041
@param block - block read from file, note it is not from the buffer pool
2140
2042
@retval DB_SUCCESS or error code. */
2141
2043
dberr_t
2142
- PageConverter::operator () (
2143
- os_offset_t offset,
2144
- buf_block_t * block) UNIV_NOTHROW
2044
+ PageConverter::operator () (os_offset_t , buf_block_t * block) UNIV_NOTHROW
2145
2045
{
2146
2046
ulint page_type;
2147
- dberr_t err = DB_SUCCESS;
2148
-
2149
- if ((err = periodic_check ()) != DB_SUCCESS) {
2150
- return (err);
2151
- }
2152
2047
2153
2048
if (is_compressed_table ()) {
2154
2049
m_page_zip_ptr = &block->page .zip ;
2155
2050
} else {
2156
2051
ut_ad (m_page_zip_ptr == 0 );
2157
2052
}
2158
2053
2159
- switch (validate (offset, block)) {
2160
- case IMPORT_PAGE_STATUS_OK:
2161
-
2162
- /* We have to decompress the compressed pages before
2163
- we can work on them */
2164
-
2165
- if ((err = update_page (block, page_type)) != DB_SUCCESS) {
2166
- break ;
2167
- }
2168
-
2054
+ dberr_t err = update_page (block, page_type);
2055
+ if (err == DB_SUCCESS) {
2169
2056
/* Note: For compressed pages this function will write to the
2170
2057
zip descriptor and for uncompressed pages it will write to
2171
2058
page (ie. the block->frame). Therefore the caller should write
@@ -2187,23 +2074,9 @@ PageConverter::operator() (
2187
2074
get_frame (block), get_zip_size (),
2188
2075
m_current_lsn);
2189
2076
}
2190
-
2191
- break ;
2192
-
2193
- case IMPORT_PAGE_STATUS_ALL_ZERO:
2194
- /* The page is all zero: leave it as is. */
2195
- break ;
2196
-
2197
- case IMPORT_PAGE_STATUS_CORRUPTED:
2198
-
2199
- ib_logf (IB_LOG_LEVEL_WARN,
2200
- " %s: Page %lu at offset " UINT64PF " looks corrupted." ,
2201
- m_filepath, (ulong) (offset / m_page_size), offset);
2202
-
2203
- err = DB_CORRUPTION;
2204
2077
}
2205
2078
2206
- /* If we already had and old page with matching number
2079
+ /* If we already had an old page with matching number
2207
2080
in the buffer pool, evict it now, because
2208
2081
we no longer evict the pages on DISCARD TABLESPACE. */
2209
2082
buf_page_get_gen (get_space_id (), get_zip_size (), block->page .offset ,
@@ -3519,8 +3392,6 @@ fil_iterate(
3519
3392
AbstractCallback& callback)
3520
3393
{
3521
3394
os_offset_t offset;
3522
- ulint page_no = 0 ;
3523
- ulint space_id = callback.get_space_id ();
3524
3395
ulint n_bytes = iter.n_io_buffers * iter.page_size ;
3525
3396
3526
3397
ut_ad (!srv_read_only_mode);
@@ -3531,6 +3402,9 @@ fil_iterate(
3531
3402
const bool row_compressed = callback.get_zip_size () > 0 ;
3532
3403
3533
3404
for (offset = iter.start ; offset < iter.end ; offset += n_bytes) {
3405
+ if (callback.is_interrupted ()) {
3406
+ return DB_INTERRUPTED;
3407
+ }
3534
3408
3535
3409
byte* io_buffer = iter.io_buffer ;
3536
3410
@@ -3572,30 +3446,45 @@ fil_iterate(
3572
3446
os_offset_t page_off = offset;
3573
3447
ulint n_pages_read = (ulint) n_bytes / iter.page_size ;
3574
3448
bool decrypted = false ;
3449
+ const ulint size = iter.page_size ;
3450
+ block->page .offset = page_off / size;
3575
3451
3576
- for (ulint i = 0 ; i < n_pages_read; ++i) {
3577
- ulint size = iter.page_size ;
3452
+ for (ulint i = 0 ; i < n_pages_read;
3453
+ ++i, page_off += size, block->frame += size,
3454
+ block->page .offset ++) {
3578
3455
dberr_t err = DB_SUCCESS;
3579
3456
byte* src = readptr + (i * size);
3580
3457
byte* dst = io_buffer + (i * size);
3581
3458
bool frame_changed = false ;
3582
-
3583
3459
ulint page_type = mach_read_from_2 (src+FIL_PAGE_TYPE);
3584
-
3585
3460
const bool page_compressed
3586
- = page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
3461
+ = page_type
3462
+ == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED
3587
3463
|| page_type == FIL_PAGE_PAGE_COMPRESSED;
3464
+ const ulint page_no = page_get_page_no (src);
3465
+ if (!page_no && page_off) {
3466
+ const ulint* b = reinterpret_cast <const ulint*>
3467
+ (src);
3468
+ const ulint* const e = b + size / sizeof *b;
3469
+ do {
3470
+ if (*b++) {
3471
+ goto page_corrupted;
3472
+ }
3473
+ } while (b != e);
3474
+
3475
+ /* Proceed to the next page,
3476
+ because this one is all zero. */
3477
+ continue ;
3478
+ }
3479
+
3480
+ if (page_no != page_off / size) {
3481
+ goto page_corrupted;
3482
+ }
3588
3483
3589
- /* If tablespace is encrypted, we need to decrypt
3590
- the page. Note that tablespaces are not in
3591
- fil_system during import. */
3592
3484
if (encrypted) {
3593
3485
decrypted = fil_space_decrypt (
3594
- iter.crypt_data ,
3595
- dst, // dst
3596
- iter.page_size ,
3597
- src, // src
3598
- &err);
3486
+ iter.crypt_data , dst,
3487
+ iter.page_size , src, &err);
3599
3488
3600
3489
if (err != DB_SUCCESS) {
3601
3490
return err;
@@ -3619,10 +3508,20 @@ fil_iterate(
3619
3508
fil_decompress_page (NULL , dst, ulong (size),
3620
3509
NULL );
3621
3510
updated = true ;
3511
+ } else if (buf_page_is_corrupted (
3512
+ false ,
3513
+ encrypted && !frame_changed
3514
+ ? dst : src,
3515
+ callback.get_zip_size (), NULL )) {
3516
+ page_corrupted:
3517
+ ib_logf (IB_LOG_LEVEL_WARN,
3518
+ " %s: Page %lu at offset "
3519
+ UINT64PF " looks corrupted." ,
3520
+ callback.filename (),
3521
+ ulong (offset / size), offset);
3522
+ return DB_CORRUPTION;
3622
3523
}
3623
3524
3624
- buf_block_set_file_page (block, space_id, page_no++);
3625
-
3626
3525
if ((err = callback (page_off, block)) != DB_SUCCESS) {
3627
3526
return err;
3628
3527
} else if (!updated) {
@@ -3714,9 +3613,6 @@ fil_iterate(
3714
3613
3715
3614
updated = true ;
3716
3615
}
3717
-
3718
- page_off += iter.page_size ;
3719
- block->frame += iter.page_size ;
3720
3616
}
3721
3617
3722
3618
/* A page was updated in the set, write back to disk. */
@@ -3820,6 +3716,7 @@ fil_tablespace_iterate(
3820
3716
3821
3717
memset (&block, 0 , sizeof block);
3822
3718
block.frame = page;
3719
+ block.page .space = callback.get_space_id ();
3823
3720
block.page .io_fix = BUF_IO_NONE;
3824
3721
block.page .buf_fix_count = 1 ;
3825
3722
block.page .state = BUF_BLOCK_FILE_PAGE;
0 commit comments