00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "fsp0fsp.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "fsp0fsp.ic"
00030 #endif
00031
00032 #include "buf0buf.h"
00033 #include "fil0fil.h"
00034 #include "mtr0log.h"
00035 #include "ut0byte.h"
00036 #include "page0page.h"
00037 #include "page0zip.h"
00038 #ifdef UNIV_HOTBACKUP
00039 # include "fut0lst.h"
00040 #else
00041 # include "sync0sync.h"
00042 # include "fut0fut.h"
00043 # include "srv0srv.h"
00044 # include "ibuf0ibuf.h"
00045 # include "btr0btr.h"
00046 # include "btr0sea.h"
00047 # include "dict0boot.h"
00048 # include "log0log.h"
00049 #endif
00050 #include "dict0mem.h"
00051
00052
00053 #define FSP_HEADER_OFFSET FIL_PAGE_DATA
00054
00055
00056
00057 typedef byte fsp_header_t;
00058 typedef byte xdes_t;
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define FSP_SPACE_ID 0
00069 #define FSP_NOT_USED 4
00070
00071
00072
00073 #define FSP_SIZE 8
00074
00075 #define FSP_FREE_LIMIT 12
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #define FSP_SPACE_FLAGS 16
00086 #define FSP_FRAG_N_USED 20
00087
00088 #define FSP_FREE 24
00089 #define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
00090
00091
00092 #define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
00093
00094
00095 #define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
00096
00097
00098 #define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
00099
00100
00101
00102 #define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
00103
00104
00105
00106
00107
00108 #define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
00109
00110 #define FSP_FREE_ADD 4
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 typedef byte fseg_inode_t;
00123
00124 #define FSEG_INODE_PAGE_NODE FSEG_PAGE_DATA
00125
00126
00127
00128 #define FSEG_ARR_OFFSET (FSEG_PAGE_DATA + FLST_NODE_SIZE)
00129
00130 #define FSEG_ID 0
00131
00132 #define FSEG_NOT_FULL_N_USED 8
00133
00134
00135 #define FSEG_FREE 12
00136
00137
00138 #define FSEG_NOT_FULL (12 + FLST_BASE_NODE_SIZE)
00139
00140 #define FSEG_FULL (12 + 2 * FLST_BASE_NODE_SIZE)
00141
00142 #define FSEG_MAGIC_N (12 + 3 * FLST_BASE_NODE_SIZE)
00143
00144 #define FSEG_FRAG_ARR (16 + 3 * FLST_BASE_NODE_SIZE)
00145
00146
00147
00148 #define FSEG_FRAG_ARR_N_SLOTS (FSP_EXTENT_SIZE / 2)
00149
00150
00151 #define FSEG_FRAG_SLOT_SIZE 4
00152
00153
00154
00155 #define FSEG_INODE_SIZE \
00156 (16 + 3 * FLST_BASE_NODE_SIZE \
00157 + FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
00158
00159 #define FSP_SEG_INODES_PER_PAGE(zip_size) \
00160 (((zip_size ? zip_size : UNIV_PAGE_SIZE) \
00161 - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE)
00162
00163
00164
00165 #define FSEG_MAGIC_N_VALUE 97937874
00166
00167 #define FSEG_FILLFACTOR 8
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 #define FSEG_FRAG_LIMIT FSEG_FRAG_ARR_N_SLOTS
00178
00179
00180
00181
00182
00183
00184 #define FSEG_FREE_LIST_LIMIT 40
00185
00186
00187
00188
00189 #define FSEG_FREE_LIST_MAX_LEN 4
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 #define XDES_ID 0
00200
00201 #define XDES_FLST_NODE 8
00202
00203 #define XDES_STATE (FLST_NODE_SIZE + 8)
00204
00205
00206 #define XDES_BITMAP (FLST_NODE_SIZE + 12)
00207
00208
00209
00210
00211 #define XDES_BITS_PER_PAGE 2
00212 #define XDES_FREE_BIT 0
00213
00214 #define XDES_CLEAN_BIT 1
00215
00216
00217
00218
00219 #define XDES_FREE 1
00220 #define XDES_FREE_FRAG 2
00221
00222 #define XDES_FULL_FRAG 3
00223
00224 #define XDES_FSEG 4
00225
00226
00227 #define XDES_SIZE \
00228 (XDES_BITMAP + UT_BITS_IN_BYTES(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE))
00229
00230
00231 #define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
00232
00233 #ifndef UNIV_HOTBACKUP
00234
00235 static ibool fsp_tbs_full_error_printed = FALSE;
00236
00237
00239 static
00240 void
00241 fsp_free_extent(
00242
00243 ulint space,
00244 ulint zip_size,
00246 ulint page,
00247 mtr_t* mtr);
00248
00250 static
00251 void
00252 fseg_free_extent(
00253
00254 fseg_inode_t* seg_inode,
00255 ulint space,
00256 ulint zip_size,
00258 ulint page,
00259 mtr_t* mtr);
00260
00264 static
00265 ulint
00266 fseg_n_reserved_pages_low(
00267
00268 fseg_inode_t* header,
00269 ulint* used,
00271 mtr_t* mtr);
00272
00275 static
00276 void
00277 fseg_mark_page_used(
00278
00279 fseg_inode_t* seg_inode,
00280 ulint space,
00281 ulint zip_size,
00283 ulint page,
00284 mtr_t* mtr);
00285
00290 static
00291 xdes_t*
00292 fseg_get_first_extent(
00293
00294 fseg_inode_t* inode,
00295 ulint space,
00296 ulint zip_size,
00298 mtr_t* mtr);
00299
00304 static
00305 void
00306 fsp_fill_free_list(
00307
00308 ibool init_space,
00313 ulint space,
00314 fsp_header_t* header,
00315 mtr_t* mtr);
00316
00321 static
00322 ulint
00323 fseg_alloc_free_page_low(
00324
00325 ulint space,
00326 ulint zip_size,
00328 fseg_inode_t* seg_inode,
00329 ulint hint,
00330 byte direction,
00335 mtr_t* mtr);
00336 #endif
00337
00338
00341 UNIV_INTERN
00342 ulint
00343 fsp_get_size_low(
00344
00345 page_t* page)
00346 {
00347 return(mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SIZE));
00348 }
00349
00350 #ifndef UNIV_HOTBACKUP
00351
00354 UNIV_INLINE
00355 fsp_header_t*
00356 fsp_get_space_header(
00357
00358 ulint id,
00359 ulint zip_size,
00361 mtr_t* mtr)
00362 {
00363 buf_block_t* block;
00364 fsp_header_t* header;
00365
00366 ut_ad(ut_is_2pow(zip_size));
00367 ut_ad(zip_size <= UNIV_PAGE_SIZE);
00368 ut_ad(!zip_size || zip_size >= PAGE_ZIP_MIN_SIZE);
00369 ut_ad(id || !zip_size);
00370
00371 block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr);
00372 header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
00373 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
00374
00375 ut_ad(id == mach_read_from_4(FSP_SPACE_ID + header));
00376 ut_ad(zip_size == dict_table_flags_to_zip_size(
00377 mach_read_from_4(FSP_SPACE_FLAGS + header)));
00378 return(header);
00379 }
00380
00381
00384 UNIV_INLINE
00385 ibool
00386 xdes_get_bit(
00387
00388 const xdes_t* descr,
00389 ulint bit,
00390 ulint offset,
00392 mtr_t* mtr)
00393 {
00394 ulint index;
00395 ulint byte_index;
00396 ulint bit_index;
00397
00398 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00399 ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
00400 ut_ad(offset < FSP_EXTENT_SIZE);
00401
00402 index = bit + XDES_BITS_PER_PAGE * offset;
00403
00404 byte_index = index / 8;
00405 bit_index = index % 8;
00406
00407 return(ut_bit_get_nth(mtr_read_ulint(descr + XDES_BITMAP + byte_index,
00408 MLOG_1BYTE, mtr),
00409 bit_index));
00410 }
00411
00412
00414 UNIV_INLINE
00415 void
00416 xdes_set_bit(
00417
00418 xdes_t* descr,
00419 ulint bit,
00420 ulint offset,
00422 ibool val,
00423 mtr_t* mtr)
00424 {
00425 ulint index;
00426 ulint byte_index;
00427 ulint bit_index;
00428 ulint descr_byte;
00429
00430 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00431 ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
00432 ut_ad(offset < FSP_EXTENT_SIZE);
00433
00434 index = bit + XDES_BITS_PER_PAGE * offset;
00435
00436 byte_index = index / 8;
00437 bit_index = index % 8;
00438
00439 descr_byte = mtr_read_ulint(descr + XDES_BITMAP + byte_index,
00440 MLOG_1BYTE, mtr);
00441 descr_byte = ut_bit_set_nth(descr_byte, bit_index, val);
00442
00443 mlog_write_ulint(descr + XDES_BITMAP + byte_index, descr_byte,
00444 MLOG_1BYTE, mtr);
00445 }
00446
00447
00452 UNIV_INLINE
00453 ulint
00454 xdes_find_bit(
00455
00456 xdes_t* descr,
00457 ulint bit,
00458 ibool val,
00459 ulint hint,
00460 mtr_t* mtr)
00461 {
00462 ulint i;
00463
00464 ut_ad(descr && mtr);
00465 ut_ad(val <= TRUE);
00466 ut_ad(hint < FSP_EXTENT_SIZE);
00467 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00468 for (i = hint; i < FSP_EXTENT_SIZE; i++) {
00469 if (val == xdes_get_bit(descr, bit, i, mtr)) {
00470
00471 return(i);
00472 }
00473 }
00474
00475 for (i = 0; i < hint; i++) {
00476 if (val == xdes_get_bit(descr, bit, i, mtr)) {
00477
00478 return(i);
00479 }
00480 }
00481
00482 return(ULINT_UNDEFINED);
00483 }
00484
00485
00489 UNIV_INLINE
00490 ulint
00491 xdes_find_bit_downward(
00492
00493 xdes_t* descr,
00494 ulint bit,
00495 ibool val,
00496 ulint hint,
00497 mtr_t* mtr)
00498 {
00499 ulint i;
00500
00501 ut_ad(descr && mtr);
00502 ut_ad(val <= TRUE);
00503 ut_ad(hint < FSP_EXTENT_SIZE);
00504 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00505 for (i = hint + 1; i > 0; i--) {
00506 if (val == xdes_get_bit(descr, bit, i - 1, mtr)) {
00507
00508 return(i - 1);
00509 }
00510 }
00511
00512 for (i = FSP_EXTENT_SIZE - 1; i > hint; i--) {
00513 if (val == xdes_get_bit(descr, bit, i, mtr)) {
00514
00515 return(i);
00516 }
00517 }
00518
00519 return(ULINT_UNDEFINED);
00520 }
00521
00522
00525 UNIV_INLINE
00526 ulint
00527 xdes_get_n_used(
00528
00529 const xdes_t* descr,
00530 mtr_t* mtr)
00531 {
00532 ulint i;
00533 ulint count = 0;
00534
00535 ut_ad(descr && mtr);
00536 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00537 for (i = 0; i < FSP_EXTENT_SIZE; i++) {
00538 if (FALSE == xdes_get_bit(descr, XDES_FREE_BIT, i, mtr)) {
00539 count++;
00540 }
00541 }
00542
00543 return(count);
00544 }
00545
00546
00549 UNIV_INLINE
00550 ibool
00551 xdes_is_free(
00552
00553 const xdes_t* descr,
00554 mtr_t* mtr)
00555 {
00556 if (0 == xdes_get_n_used(descr, mtr)) {
00557
00558 return(TRUE);
00559 }
00560
00561 return(FALSE);
00562 }
00563
00564
00567 UNIV_INLINE
00568 ibool
00569 xdes_is_full(
00570
00571 const xdes_t* descr,
00572 mtr_t* mtr)
00573 {
00574 if (FSP_EXTENT_SIZE == xdes_get_n_used(descr, mtr)) {
00575
00576 return(TRUE);
00577 }
00578
00579 return(FALSE);
00580 }
00581
00582
00584 UNIV_INLINE
00585 void
00586 xdes_set_state(
00587
00588 xdes_t* descr,
00589 ulint state,
00590 mtr_t* mtr)
00591 {
00592 ut_ad(descr && mtr);
00593 ut_ad(state >= XDES_FREE);
00594 ut_ad(state <= XDES_FSEG);
00595 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00596
00597 mlog_write_ulint(descr + XDES_STATE, state, MLOG_4BYTES, mtr);
00598 }
00599
00600
00603 UNIV_INLINE
00604 ulint
00605 xdes_get_state(
00606
00607 const xdes_t* descr,
00608 mtr_t* mtr)
00609 {
00610 ulint state;
00611
00612 ut_ad(descr && mtr);
00613 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00614
00615 state = mtr_read_ulint(descr + XDES_STATE, MLOG_4BYTES, mtr);
00616 ut_ad(state - 1 < XDES_FSEG);
00617 return(state);
00618 }
00619
00620
00622 UNIV_INLINE
00623 void
00624 xdes_init(
00625
00626 xdes_t* descr,
00627 mtr_t* mtr)
00628 {
00629 ulint i;
00630
00631 ut_ad(descr && mtr);
00632 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
00633 ut_ad((XDES_SIZE - XDES_BITMAP) % 4 == 0);
00634
00635 for (i = XDES_BITMAP; i < XDES_SIZE; i += 4) {
00636 mlog_write_ulint(descr + i, 0xFFFFFFFFUL, MLOG_4BYTES, mtr);
00637 }
00638
00639 xdes_set_state(descr, XDES_FREE, mtr);
00640 }
00641
00642
00645 UNIV_INLINE
00646 ulint
00647 xdes_calc_descriptor_page(
00648
00649 ulint zip_size,
00651 ulint offset)
00652 {
00653 ut_a(UNIV_PAGE_SIZE >
00654 XDES_ARR_OFFSET + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE);
00655 ut_a(PAGE_ZIP_MIN_SIZE >
00656 XDES_ARR_OFFSET +
00657 (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE);
00658
00659 ut_ad(ut_is_2pow(zip_size));
00660
00661 if (!zip_size) {
00662 return(ut_2pow_round(offset, UNIV_PAGE_SIZE));
00663 } else {
00664 ut_ad(zip_size > XDES_ARR_OFFSET
00665 + (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE);
00666 return(ut_2pow_round(offset, zip_size));
00667 }
00668 }
00669
00670
00673 UNIV_INLINE
00674 ulint
00675 xdes_calc_descriptor_index(
00676
00677 ulint zip_size,
00679 ulint offset)
00680 {
00681 ut_ad(ut_is_2pow(zip_size));
00682
00683 if (!zip_size) {
00684 return(ut_2pow_remainder(offset, UNIV_PAGE_SIZE)
00685 / FSP_EXTENT_SIZE);
00686 } else {
00687 return(ut_2pow_remainder(offset, zip_size) / FSP_EXTENT_SIZE);
00688 }
00689 }
00690
00691
00699 UNIV_INLINE
00700 xdes_t*
00701 xdes_get_descriptor_with_space_hdr(
00702
00703 fsp_header_t* sp_header,
00704 ulint space,
00705 ulint offset,
00709 mtr_t* mtr)
00710 {
00711 ulint limit;
00712 ulint size;
00713 ulint zip_size;
00714 ulint descr_page_no;
00715 page_t* descr_page;
00716
00717 ut_ad(mtr);
00718 ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
00719 MTR_MEMO_X_LOCK));
00720 ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
00721 || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
00722 ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
00723
00724 limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
00725 size = mach_read_from_4(sp_header + FSP_SIZE);
00726 zip_size = dict_table_flags_to_zip_size(
00727 mach_read_from_4(sp_header + FSP_SPACE_FLAGS));
00728
00729
00730
00731 if ((offset >= size) || (offset > limit)) {
00732
00733 return(NULL);
00734 }
00735
00736
00737
00738 if (offset == limit) {
00739 fsp_fill_free_list(FALSE, space, sp_header, mtr);
00740 }
00741
00742 descr_page_no = xdes_calc_descriptor_page(zip_size, offset);
00743
00744 if (descr_page_no == 0) {
00745
00746
00747 descr_page = page_align(sp_header);
00748 } else {
00749 buf_block_t* block;
00750
00751 block = buf_page_get(space, zip_size, descr_page_no,
00752 RW_X_LATCH, mtr);
00753 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
00754
00755 descr_page = buf_block_get_frame(block);
00756 }
00757
00758 return(descr_page + XDES_ARR_OFFSET
00759 + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset));
00760 }
00761
00762
00771 static
00772 xdes_t*
00773 xdes_get_descriptor(
00774
00775 ulint space,
00776 ulint zip_size,
00778 ulint offset,
00780 mtr_t* mtr)
00781 {
00782 buf_block_t* block;
00783 fsp_header_t* sp_header;
00784
00785 block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
00786 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
00787
00788 sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
00789 return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset,
00790 mtr));
00791 }
00792
00793
00798 UNIV_INLINE
00799 xdes_t*
00800 xdes_lst_get_descriptor(
00801
00802 ulint space,
00803 ulint zip_size,
00805 fil_addr_t lst_node,
00807 mtr_t* mtr)
00808 {
00809 xdes_t* descr;
00810
00811 ut_ad(mtr);
00812 ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
00813 MTR_MEMO_X_LOCK));
00814 descr = fut_get_ptr(space, zip_size, lst_node, RW_X_LATCH, mtr)
00815 - XDES_FLST_NODE;
00816
00817 return(descr);
00818 }
00819
00820
00823 UNIV_INLINE
00824 ulint
00825 xdes_get_offset(
00826
00827 xdes_t* descr)
00828 {
00829 ut_ad(descr);
00830
00831 return(page_get_page_no(page_align(descr))
00832 + ((page_offset(descr) - XDES_ARR_OFFSET) / XDES_SIZE)
00833 * FSP_EXTENT_SIZE);
00834 }
00835 #endif
00836
00837
00839 static
00840 void
00841 fsp_init_file_page_low(
00842
00843 buf_block_t* block)
00844 {
00845 page_t* page = buf_block_get_frame(block);
00846 page_zip_des_t* page_zip= buf_block_get_page_zip(block);
00847
00848 #ifndef UNIV_HOTBACKUP
00849 block->check_index_page_at_flush = FALSE;
00850 #endif
00851
00852 if (UNIV_LIKELY_NULL(page_zip)) {
00853 memset(page, 0, UNIV_PAGE_SIZE);
00854 memset(page_zip->data, 0, page_zip_get_size(page_zip));
00855 mach_write_to_4(page + FIL_PAGE_OFFSET,
00856 buf_block_get_page_no(block));
00857 mach_write_to_4(page
00858 + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
00859 buf_block_get_space(block));
00860 memcpy(page_zip->data + FIL_PAGE_OFFSET,
00861 page + FIL_PAGE_OFFSET, 4);
00862 memcpy(page_zip->data + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
00863 page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 4);
00864 return;
00865 }
00866
00867 memset(page, 0, UNIV_PAGE_SIZE);
00868 mach_write_to_4(page + FIL_PAGE_OFFSET, buf_block_get_page_no(block));
00869 mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
00870 buf_block_get_space(block));
00871 }
00872
00873 #ifndef UNIV_HOTBACKUP
00874
00876 static
00877 void
00878 fsp_init_file_page(
00879
00880 buf_block_t* block,
00881 mtr_t* mtr)
00882 {
00883 fsp_init_file_page_low(block);
00884
00885 mlog_write_initial_log_record(buf_block_get_frame(block),
00886 MLOG_INIT_FILE_PAGE, mtr);
00887 }
00888 #endif
00889
00890
00893 UNIV_INTERN
00894 byte*
00895 fsp_parse_init_file_page(
00896
00897 byte* ptr,
00898 byte* ,
00899 buf_block_t* block)
00900 {
00901 ut_ad(ptr && end_ptr);
00902
00903 if (block) {
00904 fsp_init_file_page_low(block);
00905 }
00906
00907 return(ptr);
00908 }
00909
00910
00912 UNIV_INTERN
00913 void
00914 fsp_init(void)
00915
00916 {
00917
00918 }
00919
00920
00924 UNIV_INTERN
00925 void
00926 fsp_header_init_fields(
00927
00928 page_t* page,
00929 ulint space_id,
00930 ulint flags)
00932 {
00933
00934
00935
00936
00937 ut_a(flags != DICT_TF_COMPACT);
00938
00939 mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page,
00940 space_id);
00941 mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page,
00942 flags);
00943 }
00944
00945 #ifndef UNIV_HOTBACKUP
00946
00949 UNIV_INTERN
00950 void
00951 fsp_header_init(
00952
00953 ulint space,
00954 ulint size,
00955 mtr_t* mtr)
00956 {
00957 fsp_header_t* header;
00958 buf_block_t* block;
00959 page_t* page;
00960 ulint flags;
00961 ulint zip_size;
00962
00963 ut_ad(mtr);
00964
00965 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
00966
00967 zip_size = dict_table_flags_to_zip_size(flags);
00968 block = buf_page_create(space, 0, zip_size, mtr);
00969 buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
00970 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
00971
00972
00973
00974 fsp_init_file_page(block, mtr);
00975 page = buf_block_get_frame(block);
00976
00977 mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_FSP_HDR,
00978 MLOG_2BYTES, mtr);
00979
00980 header = FSP_HEADER_OFFSET + page;
00981
00982 mlog_write_ulint(header + FSP_SPACE_ID, space, MLOG_4BYTES, mtr);
00983 mlog_write_ulint(header + FSP_NOT_USED, 0, MLOG_4BYTES, mtr);
00984
00985 mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
00986 mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
00987 mlog_write_ulint(header + FSP_SPACE_FLAGS, flags,
00988 MLOG_4BYTES, mtr);
00989 mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);
00990
00991 flst_init(header + FSP_FREE, mtr);
00992 flst_init(header + FSP_FREE_FRAG, mtr);
00993 flst_init(header + FSP_FULL_FRAG, mtr);
00994 flst_init(header + FSP_SEG_INODES_FULL, mtr);
00995 flst_init(header + FSP_SEG_INODES_FREE, mtr);
00996
00997 mlog_write_ull(header + FSP_SEG_ID, 1, mtr);
00998 if (space == 0) {
00999 fsp_fill_free_list(FALSE, space, header, mtr);
01000 btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
01001 0, 0, DICT_IBUF_ID_MIN + space,
01002 dict_ind_redundant, mtr);
01003 } else {
01004 fsp_fill_free_list(TRUE, space, header, mtr);
01005 }
01006 }
01007 #endif
01008
01009
01012 UNIV_INTERN
01013 ulint
01014 fsp_header_get_space_id(
01015
01016 const page_t* page)
01017 {
01018 ulint fsp_id;
01019 ulint id;
01020
01021 fsp_id = mach_read_from_4(FSP_HEADER_OFFSET + page + FSP_SPACE_ID);
01022
01023 id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
01024
01025 if (id != fsp_id) {
01026 fprintf(stderr,
01027 "InnoDB: Error: space id in fsp header %lu,"
01028 " but in the page header %lu\n",
01029 (ulong) fsp_id, (ulong) id);
01030
01031 return(ULINT_UNDEFINED);
01032 }
01033
01034 return(id);
01035 }
01036
01037
01040 UNIV_INTERN
01041 ulint
01042 fsp_header_get_flags(
01043
01044 const page_t* page)
01045 {
01046 ut_ad(!page_offset(page));
01047
01048 return(mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page));
01049 }
01050
01051
01054 UNIV_INTERN
01055 ulint
01056 fsp_header_get_zip_size(
01057
01058 const page_t* page)
01059 {
01060 ulint flags = fsp_header_get_flags(page);
01061
01062 return(dict_table_flags_to_zip_size(flags));
01063 }
01064
01065 #ifndef UNIV_HOTBACKUP
01066
01068 UNIV_INTERN
01069 void
01070 fsp_header_inc_size(
01071
01072 ulint space,
01073 ulint size_inc,
01074 mtr_t* mtr)
01075 {
01076 fsp_header_t* header;
01077 ulint size;
01078 ulint flags;
01079
01080 ut_ad(mtr);
01081
01082 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
01083
01084 header = fsp_get_space_header(space,
01085 dict_table_flags_to_zip_size(flags),
01086 mtr);
01087
01088 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01089
01090 mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES,
01091 mtr);
01092 }
01093
01094
01100 UNIV_INTERN
01101 ulint
01102 fsp_header_get_free_limit(void)
01103
01104 {
01105 fsp_header_t* header;
01106 ulint limit;
01107 mtr_t mtr;
01108
01109 mtr_start(&mtr);
01110
01111 mtr_x_lock(fil_space_get_latch(0, NULL), &mtr);
01112
01113 header = fsp_get_space_header(0, 0, &mtr);
01114
01115 limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr);
01116
01117 limit /= ((1024 * 1024) / UNIV_PAGE_SIZE);
01118
01119 log_fsp_current_free_limit_set_and_checkpoint(limit);
01120
01121 mtr_commit(&mtr);
01122
01123 return(limit);
01124 }
01125
01126
01132 UNIV_INTERN
01133 ulint
01134 fsp_header_get_tablespace_size(void)
01135
01136 {
01137 fsp_header_t* header;
01138 ulint size;
01139 mtr_t mtr;
01140
01141 mtr_start(&mtr);
01142
01143 mtr_x_lock(fil_space_get_latch(0, NULL), &mtr);
01144
01145 header = fsp_get_space_header(0, 0, &mtr);
01146
01147 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
01148
01149 mtr_commit(&mtr);
01150
01151 return(size);
01152 }
01153
01154
01158 static
01159 ibool
01160 fsp_try_extend_data_file_with_pages(
01161
01162 ulint space,
01163 ulint page_no,
01164 fsp_header_t* header,
01165 mtr_t* mtr)
01166 {
01167 ibool success;
01168 ulint actual_size;
01169 ulint size;
01170
01171 ut_a(space != 0);
01172
01173 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01174
01175 ut_a(page_no >= size);
01176
01177 success = fil_extend_space_to_desired_size(&actual_size, space,
01178 page_no + 1);
01179
01180
01181
01182 mlog_write_ulint(header + FSP_SIZE, actual_size, MLOG_4BYTES, mtr);
01183
01184 return(success);
01185 }
01186
01187
01190 static
01191 ibool
01192 fsp_try_extend_data_file(
01193
01194 ulint* actual_increase,
01199 ulint space,
01200 fsp_header_t* header,
01201 mtr_t* mtr)
01202 {
01203 ulint size;
01204 ulint zip_size;
01205 ulint new_size;
01206 ulint old_size;
01207 ulint size_increase;
01208 ulint actual_size;
01209 ibool success;
01210
01211 *actual_increase = 0;
01212
01213 if (space == 0 && !srv_auto_extend_last_data_file) {
01214
01215
01216
01217
01218
01219 if (fsp_tbs_full_error_printed == FALSE) {
01220 fprintf(stderr,
01221 "InnoDB: Error: Data file(s) ran"
01222 " out of space.\n"
01223 "Please add another data file or"
01224 " use \'autoextend\' for the last"
01225 " data file.\n");
01226 fsp_tbs_full_error_printed = TRUE;
01227 }
01228 return(FALSE);
01229 }
01230
01231 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01232 zip_size = dict_table_flags_to_zip_size(
01233 mach_read_from_4(header + FSP_SPACE_FLAGS));
01234
01235 old_size = size;
01236
01237 if (space == 0) {
01238 if (!srv_last_file_size_max) {
01239 size_increase = SRV_AUTO_EXTEND_INCREMENT;
01240 } else {
01241 if (srv_last_file_size_max
01242 < srv_data_file_sizes[srv_n_data_files - 1]) {
01243
01244 fprintf(stderr,
01245 "InnoDB: Error: Last data file size"
01246 " is %lu, max size allowed %lu\n",
01247 (ulong) srv_data_file_sizes[
01248 srv_n_data_files - 1],
01249 (ulong) srv_last_file_size_max);
01250 }
01251
01252 size_increase = srv_last_file_size_max
01253 - srv_data_file_sizes[srv_n_data_files - 1];
01254 if (size_increase > SRV_AUTO_EXTEND_INCREMENT) {
01255 size_increase = SRV_AUTO_EXTEND_INCREMENT;
01256 }
01257 }
01258 } else {
01259
01260
01261
01262
01263 ulint extent_size;
01265 if (!zip_size) {
01266 extent_size = FSP_EXTENT_SIZE;
01267 } else {
01268 extent_size = FSP_EXTENT_SIZE
01269 * UNIV_PAGE_SIZE / zip_size;
01270 }
01271
01272 if (size < extent_size) {
01273
01274 success = fsp_try_extend_data_file_with_pages(
01275 space, extent_size - 1, header, mtr);
01276 if (!success) {
01277 new_size = mtr_read_ulint(header + FSP_SIZE,
01278 MLOG_4BYTES, mtr);
01279
01280 *actual_increase = new_size - old_size;
01281
01282 return(FALSE);
01283 }
01284
01285 size = extent_size;
01286 }
01287
01288 if (size < 32 * extent_size) {
01289 size_increase = extent_size;
01290 } else {
01291
01292
01293
01294 size_increase = FSP_FREE_ADD * extent_size;
01295 }
01296 }
01297
01298 if (size_increase == 0) {
01299
01300 return(TRUE);
01301 }
01302
01303 success = fil_extend_space_to_desired_size(&actual_size, space,
01304 size + size_increase);
01305
01306
01307
01308 if (!zip_size) {
01309 new_size = ut_calc_align_down(actual_size,
01310 (1024 * 1024) / UNIV_PAGE_SIZE);
01311 } else {
01312 new_size = ut_calc_align_down(actual_size,
01313 (1024 * 1024) / zip_size);
01314 }
01315 mlog_write_ulint(header + FSP_SIZE, new_size, MLOG_4BYTES, mtr);
01316
01317 *actual_increase = new_size - old_size;
01318
01319 return(TRUE);
01320 }
01321
01322
01326 static
01327 void
01328 fsp_fill_free_list(
01329
01330 ibool init_space,
01335 ulint space,
01336 fsp_header_t* header,
01337 mtr_t* mtr)
01338 {
01339 ulint limit;
01340 ulint size;
01341 ulint zip_size;
01342 xdes_t* descr;
01343 ulint count = 0;
01344 ulint frag_n_used;
01345 ulint actual_increase;
01346 ulint i;
01347 mtr_t ibuf_mtr;
01348
01349 ut_ad(header && mtr);
01350 ut_ad(page_offset(header) == FSP_HEADER_OFFSET);
01351
01352
01353 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01354 limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
01355
01356 zip_size = dict_table_flags_to_zip_size(
01357 mach_read_from_4(FSP_SPACE_FLAGS + header));
01358 ut_a(ut_is_2pow(zip_size));
01359 ut_a(zip_size <= UNIV_PAGE_SIZE);
01360 ut_a(!zip_size || zip_size >= PAGE_ZIP_MIN_SIZE);
01361
01362 if (space == 0 && srv_auto_extend_last_data_file
01363 && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
01364
01365
01366 fsp_try_extend_data_file(&actual_increase, space, header, mtr);
01367 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01368 }
01369
01370 if (space != 0 && !init_space
01371 && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
01372
01373
01374 fsp_try_extend_data_file(&actual_increase, space, header, mtr);
01375 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01376 }
01377
01378 i = limit;
01379
01380 while ((init_space && i < 1)
01381 || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
01382
01383 ibool init_xdes;
01384 if (zip_size) {
01385 init_xdes = ut_2pow_remainder(i, zip_size) == 0;
01386 } else {
01387 init_xdes = ut_2pow_remainder(i, UNIV_PAGE_SIZE) == 0;
01388 }
01389
01390 mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
01391 MLOG_4BYTES, mtr);
01392
01393
01394
01395 if (space == 0) {
01396 ut_a(!zip_size);
01397 log_fsp_current_free_limit_set_and_checkpoint(
01398 (i + FSP_EXTENT_SIZE)
01399 / ((1024 * 1024) / UNIV_PAGE_SIZE));
01400 }
01401
01402 if (UNIV_UNLIKELY(init_xdes)) {
01403
01404 buf_block_t* block;
01405
01406
01407
01408
01409
01410 if (i > 0) {
01411 block = buf_page_create(
01412 space, i, zip_size, mtr);
01413 buf_page_get(space, zip_size, i,
01414 RW_X_LATCH, mtr);
01415 buf_block_dbg_add_level(block,
01416 SYNC_FSP_PAGE);
01417
01418 fsp_init_file_page(block, mtr);
01419 mlog_write_ulint(buf_block_get_frame(block)
01420 + FIL_PAGE_TYPE,
01421 FIL_PAGE_TYPE_XDES,
01422 MLOG_2BYTES, mtr);
01423 }
01424
01425
01426
01427
01428
01429
01430 mtr_start(&ibuf_mtr);
01431
01432 block = buf_page_create(space,
01433 i + FSP_IBUF_BITMAP_OFFSET,
01434 zip_size, &ibuf_mtr);
01435 buf_page_get(space, zip_size,
01436 i + FSP_IBUF_BITMAP_OFFSET,
01437 RW_X_LATCH, &ibuf_mtr);
01438 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01439
01440 fsp_init_file_page(block, &ibuf_mtr);
01441
01442 ibuf_bitmap_page_init(block, &ibuf_mtr);
01443
01444 mtr_commit(&ibuf_mtr);
01445 }
01446
01447 descr = xdes_get_descriptor_with_space_hdr(header, space, i,
01448 mtr);
01449 xdes_init(descr, mtr);
01450
01451 if (UNIV_UNLIKELY(init_xdes)) {
01452
01453
01454
01455
01456
01457 xdes_set_bit(descr, XDES_FREE_BIT, 0, FALSE, mtr);
01458 xdes_set_bit(descr, XDES_FREE_BIT,
01459 FSP_IBUF_BITMAP_OFFSET, FALSE, mtr);
01460 xdes_set_state(descr, XDES_FREE_FRAG, mtr);
01461
01462 flst_add_last(header + FSP_FREE_FRAG,
01463 descr + XDES_FLST_NODE, mtr);
01464 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
01465 MLOG_4BYTES, mtr);
01466 mlog_write_ulint(header + FSP_FRAG_N_USED,
01467 frag_n_used + 2, MLOG_4BYTES, mtr);
01468 } else {
01469 flst_add_last(header + FSP_FREE,
01470 descr + XDES_FLST_NODE, mtr);
01471 count++;
01472 }
01473
01474 i += FSP_EXTENT_SIZE;
01475 }
01476 }
01477
01478
01481 static
01482 xdes_t*
01483 fsp_alloc_free_extent(
01484
01485 ulint space,
01486 ulint zip_size,
01488 ulint hint,
01491 mtr_t* mtr)
01492 {
01493 fsp_header_t* header;
01494 fil_addr_t first;
01495 xdes_t* descr;
01496
01497 ut_ad(mtr);
01498
01499 header = fsp_get_space_header(space, zip_size, mtr);
01500
01501 descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
01502
01503 if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) {
01504
01505 } else {
01506
01507 first = flst_get_first(header + FSP_FREE, mtr);
01508
01509 if (fil_addr_is_null(first)) {
01510 fsp_fill_free_list(FALSE, space, header, mtr);
01511
01512 first = flst_get_first(header + FSP_FREE, mtr);
01513 }
01514
01515 if (fil_addr_is_null(first)) {
01516
01517 return(NULL);
01518 }
01519
01520 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
01521 }
01522
01523 flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
01524
01525 return(descr);
01526 }
01527
01528
01531 static
01532 ulint
01533 fsp_alloc_free_page(
01534
01535 ulint space,
01536 ulint zip_size,
01538 ulint hint,
01539 mtr_t* mtr)
01540 {
01541 fsp_header_t* header;
01542 fil_addr_t first;
01543 xdes_t* descr;
01544 buf_block_t* block;
01545 ulint free;
01546 ulint frag_n_used;
01547 ulint page_no;
01548 ulint space_size;
01549 ibool success;
01550
01551 ut_ad(mtr);
01552
01553 header = fsp_get_space_header(space, zip_size, mtr);
01554
01555
01556 descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
01557
01558 if (descr && (xdes_get_state(descr, mtr) == XDES_FREE_FRAG)) {
01559
01560 } else {
01561
01562 first = flst_get_first(header + FSP_FREE_FRAG, mtr);
01563
01564 if (fil_addr_is_null(first)) {
01565
01566
01567
01568
01569
01570
01571
01572 descr = fsp_alloc_free_extent(space, zip_size,
01573 hint, mtr);
01574
01575 if (descr == NULL) {
01576
01577
01578 return(FIL_NULL);
01579 }
01580
01581 xdes_set_state(descr, XDES_FREE_FRAG, mtr);
01582 flst_add_last(header + FSP_FREE_FRAG,
01583 descr + XDES_FLST_NODE, mtr);
01584 } else {
01585 descr = xdes_lst_get_descriptor(space, zip_size,
01586 first, mtr);
01587 }
01588
01589
01590 hint = 0;
01591 }
01592
01593
01594
01595
01596 free = xdes_find_bit(descr, XDES_FREE_BIT, TRUE,
01597 hint % FSP_EXTENT_SIZE, mtr);
01598 if (free == ULINT_UNDEFINED) {
01599
01600 ut_print_buf(stderr, ((byte*)descr) - 500, 1000);
01601 putc('\n', stderr);
01602
01603 ut_error;
01604 }
01605
01606 page_no = xdes_get_offset(descr) + free;
01607
01608 space_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01609
01610 if (space_size <= page_no) {
01611
01612
01613
01614 ut_a(space != 0);
01615 if (page_no >= FSP_EXTENT_SIZE) {
01616 fprintf(stderr,
01617 "InnoDB: Error: trying to extend a"
01618 " single-table tablespace %lu\n"
01619 "InnoDB: by single page(s) though the"
01620 " space size %lu. Page no %lu.\n",
01621 (ulong) space, (ulong) space_size,
01622 (ulong) page_no);
01623 return(FIL_NULL);
01624 }
01625 success = fsp_try_extend_data_file_with_pages(space, page_no,
01626 header, mtr);
01627 if (!success) {
01628
01629 return(FIL_NULL);
01630 }
01631 }
01632
01633 xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
01634
01635
01636 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
01637 mtr);
01638 frag_n_used++;
01639 mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
01640 mtr);
01641 if (xdes_is_full(descr, mtr)) {
01642
01643 flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
01644 mtr);
01645 xdes_set_state(descr, XDES_FULL_FRAG, mtr);
01646
01647 flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
01648 mtr);
01649 mlog_write_ulint(header + FSP_FRAG_N_USED,
01650 frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
01651 mtr);
01652 }
01653
01654
01655
01656
01657
01658 buf_page_create(space, page_no, zip_size, mtr);
01659
01660 block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
01661 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01662
01663
01664 fsp_init_file_page(block, mtr);
01665
01666 return(page_no);
01667 }
01668
01669
01671 static
01672 void
01673 fsp_free_page(
01674
01675 ulint space,
01676 ulint zip_size,
01678 ulint page,
01679 mtr_t* mtr)
01680 {
01681 fsp_header_t* header;
01682 xdes_t* descr;
01683 ulint state;
01684 ulint frag_n_used;
01685
01686 ut_ad(mtr);
01687
01688
01689
01690 header = fsp_get_space_header(space, zip_size, mtr);
01691
01692 descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
01693
01694 state = xdes_get_state(descr, mtr);
01695
01696 if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) {
01697 fprintf(stderr,
01698 "InnoDB: Error: File space extent descriptor"
01699 " of page %lu has state %lu\n",
01700 (ulong) page,
01701 (ulong) state);
01702 fputs("InnoDB: Dump of descriptor: ", stderr);
01703 ut_print_buf(stderr, ((byte*)descr) - 50, 200);
01704 putc('\n', stderr);
01705
01706 if (state == XDES_FREE) {
01707
01708
01709
01710 return;
01711 }
01712
01713 ut_error;
01714 }
01715
01716 if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
01717 fprintf(stderr,
01718 "InnoDB: Error: File space extent descriptor"
01719 " of page %lu says it is free\n"
01720 "InnoDB: Dump of descriptor: ", (ulong) page);
01721 ut_print_buf(stderr, ((byte*)descr) - 50, 200);
01722 putc('\n', stderr);
01723
01724
01725
01726
01727 return;
01728 }
01729
01730 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
01731 xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
01732
01733 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
01734 mtr);
01735 if (state == XDES_FULL_FRAG) {
01736
01737 flst_remove(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
01738 mtr);
01739 xdes_set_state(descr, XDES_FREE_FRAG, mtr);
01740 flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
01741 mtr);
01742 mlog_write_ulint(header + FSP_FRAG_N_USED,
01743 frag_n_used + FSP_EXTENT_SIZE - 1,
01744 MLOG_4BYTES, mtr);
01745 } else {
01746 ut_a(frag_n_used > 0);
01747 mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used - 1,
01748 MLOG_4BYTES, mtr);
01749 }
01750
01751 if (xdes_is_free(descr, mtr)) {
01752
01753 flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
01754 mtr);
01755 fsp_free_extent(space, zip_size, page, mtr);
01756 }
01757 }
01758
01759
01761 static
01762 void
01763 fsp_free_extent(
01764
01765 ulint space,
01766 ulint zip_size,
01768 ulint page,
01769 mtr_t* mtr)
01770 {
01771 fsp_header_t* header;
01772 xdes_t* descr;
01773
01774 ut_ad(mtr);
01775
01776 header = fsp_get_space_header(space, zip_size, mtr);
01777
01778 descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
01779
01780 if (xdes_get_state(descr, mtr) == XDES_FREE) {
01781
01782 ut_print_buf(stderr, (byte*)descr - 500, 1000);
01783 putc('\n', stderr);
01784
01785 ut_error;
01786 }
01787
01788 xdes_init(descr, mtr);
01789
01790 flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
01791 }
01792
01793
01796 UNIV_INLINE
01797 fseg_inode_t*
01798 fsp_seg_inode_page_get_nth_inode(
01799
01800 page_t* page,
01801 ulint i,
01802 ulint ,
01804 mtr_t* )
01806 {
01807 ut_ad(i < FSP_SEG_INODES_PER_PAGE(zip_size));
01808 ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
01809
01810 return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);
01811 }
01812
01813
01816 static
01817 ulint
01818 fsp_seg_inode_page_find_used(
01819
01820 page_t* page,
01821 ulint zip_size,
01822 mtr_t* mtr)
01823 {
01824 ulint i;
01825 fseg_inode_t* inode;
01826
01827 for (i = 0; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
01828
01829 inode = fsp_seg_inode_page_get_nth_inode(
01830 page, i, zip_size, mtr);
01831
01832 if (mach_read_from_8(inode + FSEG_ID)) {
01833
01834
01835 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
01836 == FSEG_MAGIC_N_VALUE);
01837 return(i);
01838 }
01839 }
01840
01841 return(ULINT_UNDEFINED);
01842 }
01843
01844
01847 static
01848 ulint
01849 fsp_seg_inode_page_find_free(
01850
01851 page_t* page,
01852 ulint i,
01853 ulint zip_size,
01854 mtr_t* mtr)
01855 {
01856 fseg_inode_t* inode;
01857
01858 for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
01859
01860 inode = fsp_seg_inode_page_get_nth_inode(
01861 page, i, zip_size, mtr);
01862
01863 if (!mach_read_from_8(inode + FSEG_ID)) {
01864
01865
01866 return(i);
01867 }
01868
01869 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
01870 == FSEG_MAGIC_N_VALUE);
01871 }
01872
01873 return(ULINT_UNDEFINED);
01874 }
01875
01876
01879 static
01880 ibool
01881 fsp_alloc_seg_inode_page(
01882
01883 fsp_header_t* space_header,
01884 mtr_t* mtr)
01885 {
01886 fseg_inode_t* inode;
01887 buf_block_t* block;
01888 page_t* page;
01889 ulint page_no;
01890 ulint space;
01891 ulint zip_size;
01892 ulint i;
01893
01894 ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
01895
01896 space = page_get_space_id(page_align(space_header));
01897 zip_size = dict_table_flags_to_zip_size(
01898 mach_read_from_4(FSP_SPACE_FLAGS + space_header));
01899
01900 page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
01901
01902 if (page_no == FIL_NULL) {
01903
01904 return(FALSE);
01905 }
01906
01907 block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
01908 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01909
01910 block->check_index_page_at_flush = FALSE;
01911
01912 page = buf_block_get_frame(block);
01913
01914 mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_INODE,
01915 MLOG_2BYTES, mtr);
01916
01917 for (i = 0; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
01918
01919 inode = fsp_seg_inode_page_get_nth_inode(page, i,
01920 zip_size, mtr);
01921
01922 mlog_write_ull(inode + FSEG_ID, 0, mtr);
01923 }
01924
01925 flst_add_last(space_header + FSP_SEG_INODES_FREE,
01926 page + FSEG_INODE_PAGE_NODE, mtr);
01927 return(TRUE);
01928 }
01929
01930
01933 static
01934 fseg_inode_t*
01935 fsp_alloc_seg_inode(
01936
01937 fsp_header_t* space_header,
01938 mtr_t* mtr)
01939 {
01940 ulint page_no;
01941 buf_block_t* block;
01942 page_t* page;
01943 fseg_inode_t* inode;
01944 ibool success;
01945 ulint zip_size;
01946 ulint n;
01947
01948 ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
01949
01950 if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) {
01951
01952
01953 success = fsp_alloc_seg_inode_page(space_header, mtr);
01954
01955 if (!success) {
01956
01957 return(NULL);
01958 }
01959 }
01960
01961 page_no = flst_get_first(space_header + FSP_SEG_INODES_FREE, mtr).page;
01962
01963 zip_size = dict_table_flags_to_zip_size(
01964 mach_read_from_4(FSP_SPACE_FLAGS + space_header));
01965 block = buf_page_get(page_get_space_id(page_align(space_header)),
01966 zip_size, page_no, RW_X_LATCH, mtr);
01967 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01968
01969 page = buf_block_get_frame(block);
01970
01971 n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr);
01972
01973 ut_a(n != ULINT_UNDEFINED);
01974
01975 inode = fsp_seg_inode_page_get_nth_inode(page, n, zip_size, mtr);
01976
01977 if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
01978 zip_size, mtr)) {
01979
01980
01981
01982 flst_remove(space_header + FSP_SEG_INODES_FREE,
01983 page + FSEG_INODE_PAGE_NODE, mtr);
01984
01985 flst_add_last(space_header + FSP_SEG_INODES_FULL,
01986 page + FSEG_INODE_PAGE_NODE, mtr);
01987 }
01988
01989 ut_ad(!mach_read_from_8(inode + FSEG_ID)
01990 || mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
01991 return(inode);
01992 }
01993
01994
01996 static
01997 void
01998 fsp_free_seg_inode(
01999
02000 ulint space,
02001 ulint zip_size,
02003 fseg_inode_t* inode,
02004 mtr_t* mtr)
02005 {
02006 page_t* page;
02007 fsp_header_t* space_header;
02008
02009 page = page_align(inode);
02010
02011 space_header = fsp_get_space_header(space, zip_size, mtr);
02012
02013 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02014
02015 if (ULINT_UNDEFINED
02016 == fsp_seg_inode_page_find_free(page, 0, zip_size, mtr)) {
02017
02018
02019
02020 flst_remove(space_header + FSP_SEG_INODES_FULL,
02021 page + FSEG_INODE_PAGE_NODE, mtr);
02022
02023 flst_add_last(space_header + FSP_SEG_INODES_FREE,
02024 page + FSEG_INODE_PAGE_NODE, mtr);
02025 }
02026
02027 mlog_write_ull(inode + FSEG_ID, 0, mtr);
02028 mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
02029
02030 if (ULINT_UNDEFINED
02031 == fsp_seg_inode_page_find_used(page, zip_size, mtr)) {
02032
02033
02034
02035 flst_remove(space_header + FSP_SEG_INODES_FREE,
02036 page + FSEG_INODE_PAGE_NODE, mtr);
02037
02038 fsp_free_page(space, zip_size, page_get_page_no(page), mtr);
02039 }
02040 }
02041
02042
02045 static
02046 fseg_inode_t*
02047 fseg_inode_try_get(
02048
02049 fseg_header_t* header,
02050 ulint space,
02051 ulint zip_size,
02053 mtr_t* mtr)
02054 {
02055 fil_addr_t inode_addr;
02056 fseg_inode_t* inode;
02057
02058 inode_addr.page = mach_read_from_4(header + FSEG_HDR_PAGE_NO);
02059 inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET);
02060 ut_ad(space == mach_read_from_4(header + FSEG_HDR_SPACE));
02061
02062 inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
02063
02064 if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
02065
02066 inode = NULL;
02067 } else {
02068 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
02069 == FSEG_MAGIC_N_VALUE);
02070 }
02071
02072 return(inode);
02073 }
02074
02075
02078 static
02079 fseg_inode_t*
02080 fseg_inode_get(
02081
02082 fseg_header_t* header,
02083 ulint space,
02084 ulint zip_size,
02086 mtr_t* mtr)
02087 {
02088 fseg_inode_t* inode
02089 = fseg_inode_try_get(header, space, zip_size, mtr);
02090 ut_a(inode);
02091 return(inode);
02092 }
02093
02094
02097 UNIV_INLINE
02098 ulint
02099 fseg_get_nth_frag_page_no(
02100
02101 fseg_inode_t* inode,
02102 ulint n,
02103 mtr_t* )
02104 {
02105 ut_ad(inode && mtr);
02106 ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
02107 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
02108 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02109 return(mach_read_from_4(inode + FSEG_FRAG_ARR
02110 + n * FSEG_FRAG_SLOT_SIZE));
02111 }
02112
02113
02115 UNIV_INLINE
02116 void
02117 fseg_set_nth_frag_page_no(
02118
02119 fseg_inode_t* inode,
02120 ulint n,
02121 ulint page_no,
02122 mtr_t* mtr)
02123 {
02124 ut_ad(inode && mtr);
02125 ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
02126 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
02127 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02128
02129 mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
02130 page_no, MLOG_4BYTES, mtr);
02131 }
02132
02133
02136 static
02137 ulint
02138 fseg_find_free_frag_page_slot(
02139
02140 fseg_inode_t* inode,
02141 mtr_t* mtr)
02142 {
02143 ulint i;
02144 ulint page_no;
02145
02146 ut_ad(inode && mtr);
02147
02148 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02149 page_no = fseg_get_nth_frag_page_no(inode, i, mtr);
02150
02151 if (page_no == FIL_NULL) {
02152
02153 return(i);
02154 }
02155 }
02156
02157 return(ULINT_UNDEFINED);
02158 }
02159
02160
02163 static
02164 ulint
02165 fseg_find_last_used_frag_page_slot(
02166
02167 fseg_inode_t* inode,
02168 mtr_t* mtr)
02169 {
02170 ulint i;
02171 ulint page_no;
02172
02173 ut_ad(inode && mtr);
02174
02175 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02176 page_no = fseg_get_nth_frag_page_no(
02177 inode, FSEG_FRAG_ARR_N_SLOTS - i - 1, mtr);
02178
02179 if (page_no != FIL_NULL) {
02180
02181 return(FSEG_FRAG_ARR_N_SLOTS - i - 1);
02182 }
02183 }
02184
02185 return(ULINT_UNDEFINED);
02186 }
02187
02188
02191 static
02192 ulint
02193 fseg_get_n_frag_pages(
02194
02195 fseg_inode_t* inode,
02196 mtr_t* mtr)
02197 {
02198 ulint i;
02199 ulint count = 0;
02200
02201 ut_ad(inode && mtr);
02202
02203 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02204 if (FIL_NULL != fseg_get_nth_frag_page_no(inode, i, mtr)) {
02205 count++;
02206 }
02207 }
02208
02209 return(count);
02210 }
02211
02212
02216 UNIV_INTERN
02217 buf_block_t*
02218 fseg_create_general(
02219
02220 ulint space,
02221 ulint page,
02225 ulint byte_offset,
02227 ibool has_done_reservation,
02233 mtr_t* mtr)
02234 {
02235 ulint flags;
02236 ulint zip_size;
02237 fsp_header_t* space_header;
02238 fseg_inode_t* inode;
02239 ib_id_t seg_id;
02240 buf_block_t* block = 0;
02241 fseg_header_t* header = 0;
02242 rw_lock_t* latch;
02243 ibool success;
02244 ulint n_reserved;
02245 ulint i;
02246
02247 ut_ad(mtr);
02248 ut_ad(byte_offset + FSEG_HEADER_SIZE
02249 <= UNIV_PAGE_SIZE - FIL_PAGE_DATA_END);
02250
02251 latch = fil_space_get_latch(space, &flags);
02252 zip_size = dict_table_flags_to_zip_size(flags);
02253
02254 if (page != 0) {
02255 block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
02256 header = byte_offset + buf_block_get_frame(block);
02257 }
02258
02259 ut_ad(!mutex_own(&kernel_mutex)
02260 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02261
02262 mtr_x_lock(latch, mtr);
02263
02264 if (rw_lock_get_x_lock_count(latch) == 1) {
02265
02266
02267
02268 if (space == IBUF_SPACE_ID) {
02269 ibuf_free_excess_pages();
02270 }
02271 }
02272
02273 if (!has_done_reservation) {
02274 success = fsp_reserve_free_extents(&n_reserved, space, 2,
02275 FSP_NORMAL, mtr);
02276 if (!success) {
02277 return(NULL);
02278 }
02279 }
02280
02281 space_header = fsp_get_space_header(space, zip_size, mtr);
02282
02283 inode = fsp_alloc_seg_inode(space_header, mtr);
02284
02285 if (inode == NULL) {
02286
02287 goto funct_exit;
02288 }
02289
02290
02291
02292
02293 seg_id = mach_read_from_8(space_header + FSP_SEG_ID);
02294
02295 mlog_write_ull(space_header + FSP_SEG_ID, seg_id + 1, mtr);
02296
02297 mlog_write_ull(inode + FSEG_ID, seg_id, mtr);
02298 mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr);
02299
02300 flst_init(inode + FSEG_FREE, mtr);
02301 flst_init(inode + FSEG_NOT_FULL, mtr);
02302 flst_init(inode + FSEG_FULL, mtr);
02303
02304 mlog_write_ulint(inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE,
02305 MLOG_4BYTES, mtr);
02306 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02307 fseg_set_nth_frag_page_no(inode, i, FIL_NULL, mtr);
02308 }
02309
02310 if (page == 0) {
02311 page = fseg_alloc_free_page_low(space, zip_size,
02312 inode, 0, FSP_UP, mtr);
02313
02314 if (page == FIL_NULL) {
02315
02316 fsp_free_seg_inode(space, zip_size, inode, mtr);
02317
02318 goto funct_exit;
02319 }
02320
02321 block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
02322 header = byte_offset + buf_block_get_frame(block);
02323 mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE,
02324 FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
02325 }
02326
02327 mlog_write_ulint(header + FSEG_HDR_OFFSET,
02328 page_offset(inode), MLOG_2BYTES, mtr);
02329
02330 mlog_write_ulint(header + FSEG_HDR_PAGE_NO,
02331 page_get_page_no(page_align(inode)),
02332 MLOG_4BYTES, mtr);
02333
02334 mlog_write_ulint(header + FSEG_HDR_SPACE, space, MLOG_4BYTES, mtr);
02335
02336 funct_exit:
02337 if (!has_done_reservation) {
02338
02339 fil_space_release_free_extents(space, n_reserved);
02340 }
02341
02342 return(block);
02343 }
02344
02345
02349 UNIV_INTERN
02350 buf_block_t*
02351 fseg_create(
02352
02353 ulint space,
02354 ulint page,
02358 ulint byte_offset,
02360 mtr_t* mtr)
02361 {
02362 return(fseg_create_general(space, page, byte_offset, FALSE, mtr));
02363 }
02364
02365
02369 static
02370 ulint
02371 fseg_n_reserved_pages_low(
02372
02373 fseg_inode_t* inode,
02374 ulint* used,
02376 mtr_t* mtr)
02377 {
02378 ulint ret;
02379
02380 ut_ad(inode && used && mtr);
02381 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
02382
02383 *used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr)
02384 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL, mtr)
02385 + fseg_get_n_frag_pages(inode, mtr);
02386
02387 ret = fseg_get_n_frag_pages(inode, mtr)
02388 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FREE, mtr)
02389 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_NOT_FULL, mtr)
02390 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL, mtr);
02391
02392 return(ret);
02393 }
02394
02395
02399 UNIV_INTERN
02400 ulint
02401 fseg_n_reserved_pages(
02402
02403 fseg_header_t* header,
02404 ulint* used,
02405 mtr_t* mtr)
02406 {
02407 ulint ret;
02408 fseg_inode_t* inode;
02409 ulint space;
02410 ulint flags;
02411 ulint zip_size;
02412 rw_lock_t* latch;
02413
02414 space = page_get_space_id(page_align(header));
02415 latch = fil_space_get_latch(space, &flags);
02416 zip_size = dict_table_flags_to_zip_size(flags);
02417
02418 ut_ad(!mutex_own(&kernel_mutex)
02419 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02420
02421 mtr_x_lock(latch, mtr);
02422
02423 inode = fseg_inode_get(header, space, zip_size, mtr);
02424
02425 ret = fseg_n_reserved_pages_low(inode, used, mtr);
02426
02427 return(ret);
02428 }
02429
02430
02435 static
02436 void
02437 fseg_fill_free_list(
02438
02439 fseg_inode_t* inode,
02440 ulint space,
02441 ulint zip_size,
02443 ulint hint,
02445 mtr_t* mtr)
02446 {
02447 xdes_t* descr;
02448 ulint i;
02449 ib_id_t seg_id;
02450 ulint reserved;
02451 ulint used;
02452
02453 ut_ad(inode && mtr);
02454 ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
02455
02456 reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
02457
02458 if (reserved < FSEG_FREE_LIST_LIMIT * FSP_EXTENT_SIZE) {
02459
02460
02461
02462 return;
02463 }
02464
02465 if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
02466
02467
02468 return;
02469 }
02470
02471 for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) {
02472 descr = xdes_get_descriptor(space, zip_size, hint, mtr);
02473
02474 if ((descr == NULL)
02475 || (XDES_FREE != xdes_get_state(descr, mtr))) {
02476
02477
02478
02479 return;
02480 }
02481
02482 descr = fsp_alloc_free_extent(space, zip_size, hint, mtr);
02483
02484 xdes_set_state(descr, XDES_FSEG, mtr);
02485
02486 seg_id = mach_read_from_8(inode + FSEG_ID);
02487 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
02488 == FSEG_MAGIC_N_VALUE);
02489 mlog_write_ull(descr + XDES_ID, seg_id, mtr);
02490
02491 flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
02492 hint += FSP_EXTENT_SIZE;
02493 }
02494 }
02495
02496
02502 static
02503 xdes_t*
02504 fseg_alloc_free_extent(
02505
02506 fseg_inode_t* inode,
02507 ulint space,
02508 ulint zip_size,
02510 mtr_t* mtr)
02511 {
02512 xdes_t* descr;
02513 ib_id_t seg_id;
02514 fil_addr_t first;
02515
02516 ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
02517 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02518
02519 if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
02520
02521
02522 first = flst_get_first(inode + FSEG_FREE, mtr);
02523
02524 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
02525 } else {
02526
02527 descr = fsp_alloc_free_extent(space, zip_size, 0, mtr);
02528
02529 if (descr == NULL) {
02530
02531 return(NULL);
02532 }
02533
02534 seg_id = mach_read_from_8(inode + FSEG_ID);
02535
02536 xdes_set_state(descr, XDES_FSEG, mtr);
02537 mlog_write_ull(descr + XDES_ID, seg_id, mtr);
02538 flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
02539
02540
02541 fseg_fill_free_list(inode, space, zip_size,
02542 xdes_get_offset(descr) + FSP_EXTENT_SIZE,
02543 mtr);
02544 }
02545
02546 return(descr);
02547 }
02548
02549
02554 static
02555 ulint
02556 fseg_alloc_free_page_low(
02557
02558 ulint space,
02559 ulint zip_size,
02561 fseg_inode_t* seg_inode,
02562 ulint hint,
02563 byte direction,
02568 mtr_t* mtr)
02569 {
02570 fsp_header_t* space_header;
02571 ulint space_size;
02572 ib_id_t seg_id;
02573 ulint used;
02574 ulint reserved;
02575 xdes_t* descr;
02576 ulint ret_page;
02578 xdes_t* ret_descr;
02579 ibool frag_page_allocated = FALSE;
02580 ibool success;
02581 ulint n;
02582
02583 ut_ad(mtr);
02584 ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR));
02585 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
02586 == FSEG_MAGIC_N_VALUE);
02587 ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
02588 seg_id = mach_read_from_8(seg_inode + FSEG_ID);
02589
02590 ut_ad(seg_id);
02591
02592 reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
02593
02594 space_header = fsp_get_space_header(space, zip_size, mtr);
02595
02596 descr = xdes_get_descriptor_with_space_hdr(space_header, space,
02597 hint, mtr);
02598 if (descr == NULL) {
02599
02600
02601 hint = 0;
02602 descr = xdes_get_descriptor(space, zip_size, hint, mtr);
02603 }
02604
02605
02606
02607 if ((xdes_get_state(descr, mtr) == XDES_FSEG)
02608 && mach_read_from_8(descr + XDES_ID) == seg_id
02609 && (xdes_get_bit(descr, XDES_FREE_BIT,
02610 hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
02611
02612
02613
02614 ret_descr = descr;
02615 ret_page = hint;
02616
02617 } else if ((xdes_get_state(descr, mtr) == XDES_FREE)
02618 && ((reserved - used) < reserved / FSEG_FILLFACTOR)
02619 && (used >= FSEG_FRAG_LIMIT)) {
02620
02621
02622
02623
02624
02625 ret_descr = fsp_alloc_free_extent(space, zip_size, hint, mtr);
02626
02627 ut_a(ret_descr == descr);
02628
02629 xdes_set_state(ret_descr, XDES_FSEG, mtr);
02630 mlog_write_ull(ret_descr + XDES_ID, seg_id, mtr);
02631 flst_add_last(seg_inode + FSEG_FREE,
02632 ret_descr + XDES_FLST_NODE, mtr);
02633
02634
02635 fseg_fill_free_list(seg_inode, space, zip_size,
02636 hint + FSP_EXTENT_SIZE, mtr);
02637 ret_page = hint;
02638
02639 } else if ((direction != FSP_NO_DIR)
02640 && ((reserved - used) < reserved / FSEG_FILLFACTOR)
02641 && (used >= FSEG_FRAG_LIMIT)
02642 && (!!(ret_descr
02643 = fseg_alloc_free_extent(seg_inode,
02644 space, zip_size, mtr)))) {
02645
02646
02647
02648
02649
02650
02651
02652 ret_page = xdes_get_offset(ret_descr);
02653
02654 if (direction == FSP_DOWN) {
02655 ret_page += FSP_EXTENT_SIZE - 1;
02656 }
02657
02658 } else if ((xdes_get_state(descr, mtr) == XDES_FSEG)
02659 && mach_read_from_8(descr + XDES_ID) == seg_id
02660 && (!xdes_is_full(descr, mtr))) {
02661
02662
02663
02664
02665
02666
02667
02668 ret_descr = descr;
02669 ret_page = xdes_get_offset(ret_descr)
02670 + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
02671 hint % FSP_EXTENT_SIZE, mtr);
02672
02673 } else if (reserved - used > 0) {
02674
02675
02676 fil_addr_t first;
02677
02678 if (flst_get_len(seg_inode + FSEG_NOT_FULL, mtr) > 0) {
02679 first = flst_get_first(seg_inode + FSEG_NOT_FULL,
02680 mtr);
02681 } else if (flst_get_len(seg_inode + FSEG_FREE, mtr) > 0) {
02682 first = flst_get_first(seg_inode + FSEG_FREE, mtr);
02683 } else {
02684 ut_error;
02685 return(FIL_NULL);
02686 }
02687
02688 ret_descr = xdes_lst_get_descriptor(space, zip_size,
02689 first, mtr);
02690 ret_page = xdes_get_offset(ret_descr)
02691 + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
02692 0, mtr);
02693
02694 } else if (used < FSEG_FRAG_LIMIT) {
02695
02696
02697 ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
02698 ret_descr = NULL;
02699
02700 frag_page_allocated = TRUE;
02701
02702 if (ret_page != FIL_NULL) {
02703
02704
02705 n = fseg_find_free_frag_page_slot(seg_inode, mtr);
02706 ut_a(n != FIL_NULL);
02707
02708 fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
02709 mtr);
02710 }
02711
02712 } else {
02713
02714
02715 ret_descr = fseg_alloc_free_extent(seg_inode,
02716 space, zip_size, mtr);
02717
02718 if (ret_descr == NULL) {
02719 ret_page = FIL_NULL;
02720 } else {
02721 ret_page = xdes_get_offset(ret_descr);
02722 }
02723 }
02724
02725 if (ret_page == FIL_NULL) {
02726
02727
02728 return(FIL_NULL);
02729 }
02730
02731 if (space != 0) {
02732 space_size = fil_space_get_size(space);
02733
02734 if (space_size <= ret_page) {
02735
02736
02737
02738 if (ret_page >= FSP_EXTENT_SIZE) {
02739 fprintf(stderr,
02740 "InnoDB: Error (2): trying to extend"
02741 " a single-table tablespace %lu\n"
02742 "InnoDB: by single page(s) though"
02743 " the space size %lu. Page no %lu.\n",
02744 (ulong) space, (ulong) space_size,
02745 (ulong) ret_page);
02746 return(FIL_NULL);
02747 }
02748
02749 success = fsp_try_extend_data_file_with_pages(
02750 space, ret_page, space_header, mtr);
02751 if (!success) {
02752
02753 return(FIL_NULL);
02754 }
02755 }
02756 }
02757
02758 if (!frag_page_allocated) {
02759
02760
02761
02762 buf_block_t* block;
02763 ulint page_zip_size = dict_table_flags_to_zip_size(
02764 mach_read_from_4(FSP_SPACE_FLAGS + space_header));
02765
02766 block = buf_page_create(space, ret_page, page_zip_size, mtr);
02767 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
02768
02769 if (UNIV_UNLIKELY(block != buf_page_get(space, page_zip_size,
02770 ret_page, RW_X_LATCH,
02771 mtr))) {
02772 ut_error;
02773 }
02774
02775
02776 fsp_init_file_page(block, mtr);
02777
02778
02779
02780
02781
02782 ut_ad(xdes_get_descriptor(space, page_zip_size, ret_page, mtr)
02783 == ret_descr);
02784 ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT,
02785 ret_page % FSP_EXTENT_SIZE, mtr) == TRUE);
02786
02787 fseg_mark_page_used(seg_inode, space, page_zip_size, ret_page, mtr);
02788 }
02789
02790 buf_reset_check_index_page_at_flush(space, ret_page);
02791
02792 return(ret_page);
02793 }
02794
02795
02800 UNIV_INTERN
02801 ulint
02802 fseg_alloc_free_page_general(
02803
02804 fseg_header_t* seg_header,
02805 ulint hint,
02806 byte direction,
02811 ibool has_done_reservation,
02816 mtr_t* mtr)
02817 {
02818 fseg_inode_t* inode;
02819 ulint space;
02820 ulint flags;
02821 ulint zip_size;
02822 rw_lock_t* latch;
02823 ibool success;
02824 ulint page_no;
02825 ulint n_reserved;
02826
02827 space = page_get_space_id(page_align(seg_header));
02828
02829 latch = fil_space_get_latch(space, &flags);
02830
02831 zip_size = dict_table_flags_to_zip_size(flags);
02832
02833 ut_ad(!mutex_own(&kernel_mutex)
02834 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02835
02836 mtr_x_lock(latch, mtr);
02837
02838 if (rw_lock_get_x_lock_count(latch) == 1) {
02839
02840
02841
02842 if (space == IBUF_SPACE_ID) {
02843 ibuf_free_excess_pages();
02844 }
02845 }
02846
02847 inode = fseg_inode_get(seg_header, space, zip_size, mtr);
02848
02849 if (!has_done_reservation) {
02850 success = fsp_reserve_free_extents(&n_reserved, space, 2,
02851 FSP_NORMAL, mtr);
02852 if (!success) {
02853 return(FIL_NULL);
02854 }
02855 }
02856
02857 page_no = fseg_alloc_free_page_low(space, zip_size,
02858 inode, hint, direction, mtr);
02859 if (!has_done_reservation) {
02860 fil_space_release_free_extents(space, n_reserved);
02861 }
02862
02863 return(page_no);
02864 }
02865
02866
02871 UNIV_INTERN
02872 ulint
02873 fseg_alloc_free_page(
02874
02875 fseg_header_t* seg_header,
02876 ulint hint,
02877 byte direction,
02882 mtr_t* mtr)
02883 {
02884 return(fseg_alloc_free_page_general(seg_header, hint, direction,
02885 FALSE, mtr));
02886 }
02887
02888
02895 static
02896 ibool
02897 fsp_reserve_free_pages(
02898
02899 ulint space,
02900 fsp_header_t* space_header,
02902 ulint size,
02904 mtr_t* mtr)
02905 {
02906 xdes_t* descr;
02907 ulint n_used;
02908
02909 ut_a(space != 0);
02910 ut_a(size < FSP_EXTENT_SIZE / 2);
02911
02912 descr = xdes_get_descriptor_with_space_hdr(space_header, space, 0,
02913 mtr);
02914 n_used = xdes_get_n_used(descr, mtr);
02915
02916 ut_a(n_used <= size);
02917
02918 if (size >= n_used + 2) {
02919
02920 return(TRUE);
02921 }
02922
02923 return(fsp_try_extend_data_file_with_pages(space, n_used + 1,
02924 space_header, mtr));
02925 }
02926
02927
02953 UNIV_INTERN
02954 ibool
02955 fsp_reserve_free_extents(
02956
02957 ulint* n_reserved,
02960 ulint space,
02961 ulint n_ext,
02962 ulint alloc_type,
02963 mtr_t* mtr)
02964 {
02965 fsp_header_t* space_header;
02966 rw_lock_t* latch;
02967 ulint n_free_list_ext;
02968 ulint free_limit;
02969 ulint size;
02970 ulint flags;
02971 ulint zip_size;
02972 ulint n_free;
02973 ulint n_free_up;
02974 ulint reserve;
02975 ibool success;
02976 ulint n_pages_added;
02977
02978 ut_ad(mtr);
02979 *n_reserved = n_ext;
02980
02981 latch = fil_space_get_latch(space, &flags);
02982 zip_size = dict_table_flags_to_zip_size(flags);
02983
02984 ut_ad(!mutex_own(&kernel_mutex)
02985 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02986
02987 mtr_x_lock(latch, mtr);
02988
02989 space_header = fsp_get_space_header(space, zip_size, mtr);
02990 try_again:
02991 size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr);
02992
02993 if (size < FSP_EXTENT_SIZE / 2) {
02994
02995 *n_reserved = 0;
02996 return(fsp_reserve_free_pages(space, space_header, size, mtr));
02997 }
02998
02999 n_free_list_ext = flst_get_len(space_header + FSP_FREE, mtr);
03000
03001 free_limit = mtr_read_ulint(space_header + FSP_FREE_LIMIT,
03002 MLOG_4BYTES, mtr);
03003
03004
03005
03006
03007
03008 n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
03009
03010 if (n_free_up > 0) {
03011 n_free_up--;
03012 if (!zip_size) {
03013 n_free_up -= n_free_up
03014 / (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE);
03015 } else {
03016 n_free_up -= n_free_up
03017 / (zip_size / FSP_EXTENT_SIZE);
03018 }
03019 }
03020
03021 n_free = n_free_list_ext + n_free_up;
03022
03023 if (alloc_type == FSP_NORMAL) {
03024
03025
03026
03027
03028 reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
03029
03030 if (n_free <= reserve + n_ext) {
03031
03032 goto try_to_extend;
03033 }
03034 } else if (alloc_type == FSP_UNDO) {
03035
03036
03037 reserve = 1 + ((size / FSP_EXTENT_SIZE) * 1) / 200;
03038
03039 if (n_free <= reserve + n_ext) {
03040
03041 goto try_to_extend;
03042 }
03043 } else {
03044 ut_a(alloc_type == FSP_CLEANING);
03045 }
03046
03047 success = fil_space_reserve_free_extents(space, n_free, n_ext);
03048
03049 if (success) {
03050 return(TRUE);
03051 }
03052 try_to_extend:
03053 success = fsp_try_extend_data_file(&n_pages_added, space,
03054 space_header, mtr);
03055 if (success && n_pages_added > 0) {
03056
03057 goto try_again;
03058 }
03059
03060 return(FALSE);
03061 }
03062
03063
03069 UNIV_INTERN
03070 ullint
03071 fsp_get_available_space_in_free_extents(
03072
03073 ulint space)
03074 {
03075 fsp_header_t* space_header;
03076 ulint n_free_list_ext;
03077 ulint free_limit;
03078 ulint size;
03079 ulint flags;
03080 ulint zip_size;
03081 ulint n_free;
03082 ulint n_free_up;
03083 ulint reserve;
03084 rw_lock_t* latch;
03085 mtr_t mtr;
03086
03087 ut_ad(!mutex_own(&kernel_mutex));
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104 mutex_enter(&dict_sys->mutex);
03105
03106
03107
03108
03109 if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) {
03110
03111 mutex_exit(&dict_sys->mutex);
03112
03113 return(ULLINT_UNDEFINED);
03114 }
03115
03116 mtr_start(&mtr);
03117
03118 latch = fil_space_get_latch(space, &flags);
03119
03120
03121
03122
03123
03124 zip_size = dict_table_flags_to_zip_size(flags);
03125
03126 mtr_x_lock(latch, &mtr);
03127
03128 mutex_exit(&dict_sys->mutex);
03129
03130
03131
03132
03133
03134
03135 if (fil_tablespace_is_being_deleted(space)) {
03136
03137 mtr_commit(&mtr);
03138
03139 return(ULLINT_UNDEFINED);
03140 }
03141
03142
03143
03144
03145
03146 space_header = fsp_get_space_header(space, zip_size, &mtr);
03147
03148 size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, &mtr);
03149
03150 n_free_list_ext = flst_get_len(space_header + FSP_FREE, &mtr);
03151
03152 free_limit = mtr_read_ulint(space_header + FSP_FREE_LIMIT,
03153 MLOG_4BYTES, &mtr);
03154 mtr_commit(&mtr);
03155
03156 if (size < FSP_EXTENT_SIZE) {
03157 ut_a(space != 0);
03158
03159
03160 return(0);
03161
03162 }
03163
03164
03165
03166
03167
03168 n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
03169
03170 if (n_free_up > 0) {
03171 n_free_up--;
03172 if (!zip_size) {
03173 n_free_up -= n_free_up
03174 / (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE);
03175 } else {
03176 n_free_up -= n_free_up
03177 / (zip_size / FSP_EXTENT_SIZE);
03178 }
03179 }
03180
03181 n_free = n_free_list_ext + n_free_up;
03182
03183
03184
03185
03186
03187 reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
03188
03189 if (reserve > n_free) {
03190 return(0);
03191 }
03192
03193 if (!zip_size) {
03194 return((ullint) (n_free - reserve)
03195 * FSP_EXTENT_SIZE
03196 * (UNIV_PAGE_SIZE / 1024));
03197 } else {
03198 return((ullint) (n_free - reserve)
03199 * FSP_EXTENT_SIZE
03200 * (zip_size / 1024));
03201 }
03202 }
03203
03204
03207 static
03208 void
03209 fseg_mark_page_used(
03210
03211 fseg_inode_t* seg_inode,
03212 ulint space,
03213 ulint zip_size,
03215 ulint page,
03216 mtr_t* mtr)
03217 {
03218 xdes_t* descr;
03219 ulint not_full_n_used;
03220
03221 ut_ad(seg_inode && mtr);
03222 ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
03223 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
03224 == FSEG_MAGIC_N_VALUE);
03225
03226 descr = xdes_get_descriptor(space, zip_size, page, mtr);
03227
03228 ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr)
03229 == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr));
03230
03231 if (xdes_is_free(descr, mtr)) {
03232
03233
03234 flst_remove(seg_inode + FSEG_FREE, descr + XDES_FLST_NODE,
03235 mtr);
03236 flst_add_last(seg_inode + FSEG_NOT_FULL,
03237 descr + XDES_FLST_NODE, mtr);
03238 }
03239
03240 ut_ad(xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
03241 == TRUE);
03242
03243 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, FALSE, mtr);
03244
03245 not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03246 MLOG_4BYTES, mtr);
03247 not_full_n_used++;
03248 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED, not_full_n_used,
03249 MLOG_4BYTES, mtr);
03250 if (xdes_is_full(descr, mtr)) {
03251
03252
03253 flst_remove(seg_inode + FSEG_NOT_FULL,
03254 descr + XDES_FLST_NODE, mtr);
03255 flst_add_last(seg_inode + FSEG_FULL,
03256 descr + XDES_FLST_NODE, mtr);
03257
03258 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03259 not_full_n_used - FSP_EXTENT_SIZE,
03260 MLOG_4BYTES, mtr);
03261 }
03262 }
03263
03264
03266 static
03267 void
03268 fseg_free_page_low(
03269
03270 fseg_inode_t* seg_inode,
03271 ulint space,
03272 ulint zip_size,
03274 ulint page,
03275 mtr_t* mtr)
03276 {
03277 xdes_t* descr;
03278 ulint not_full_n_used;
03279 ulint state;
03280 ib_id_t descr_id;
03281 ib_id_t seg_id;
03282 ulint i;
03283
03284 ut_ad(seg_inode && mtr);
03285 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
03286 == FSEG_MAGIC_N_VALUE);
03287 ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
03288
03289
03290
03291
03292 btr_search_drop_page_hash_when_freed(space, zip_size, page);
03293
03294 descr = xdes_get_descriptor(space, zip_size, page, mtr);
03295
03296 ut_a(descr);
03297 if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
03298 fputs("InnoDB: Dump of the tablespace extent descriptor: ",
03299 stderr);
03300 ut_print_buf(stderr, descr, 40);
03301
03302 fprintf(stderr, "\n"
03303 "InnoDB: Serious error! InnoDB is trying to"
03304 " free page %lu\n"
03305 "InnoDB: though it is already marked as free"
03306 " in the tablespace!\n"
03307 "InnoDB: The tablespace free space info is corrupt.\n"
03308 "InnoDB: You may need to dump your"
03309 " InnoDB tables and recreate the whole\n"
03310 "InnoDB: database!\n", (ulong) page);
03311 crash:
03312 fputs("InnoDB: Please refer to\n"
03313 "InnoDB: " REFMAN "forcing-recovery.html\n"
03314 "InnoDB: about forcing recovery.\n", stderr);
03315 ut_error;
03316 }
03317
03318 state = xdes_get_state(descr, mtr);
03319
03320 if (state != XDES_FSEG) {
03321
03322
03323 for (i = 0;; i++) {
03324 if (fseg_get_nth_frag_page_no(seg_inode, i, mtr)
03325 == page) {
03326
03327 fseg_set_nth_frag_page_no(seg_inode, i,
03328 FIL_NULL, mtr);
03329 break;
03330 }
03331 }
03332
03333 fsp_free_page(space, zip_size, page, mtr);
03334
03335 return;
03336 }
03337
03338
03339
03340 descr_id = mach_read_from_8(descr + XDES_ID);
03341 seg_id = mach_read_from_8(seg_inode + FSEG_ID);
03342 #if 0
03343 fprintf(stderr,
03344 "InnoDB: InnoDB is freeing space %lu page %lu,\n"
03345 "InnoDB: which belongs to descr seg %llu\n"
03346 "InnoDB: segment %llu.\n",
03347 (ulong) space, (ulong) page,
03348 (ullint) descr_id,
03349 (ullint) seg_id);
03350 #endif
03351 if (UNIV_UNLIKELY(descr_id != seg_id)) {
03352 fputs("InnoDB: Dump of the tablespace extent descriptor: ",
03353 stderr);
03354 ut_print_buf(stderr, descr, 40);
03355 fputs("\nInnoDB: Dump of the segment inode: ", stderr);
03356 ut_print_buf(stderr, seg_inode, 40);
03357 putc('\n', stderr);
03358
03359 fprintf(stderr,
03360 "InnoDB: Serious error: InnoDB is trying to"
03361 " free space %lu page %lu,\n"
03362 "InnoDB: which does not belong to"
03363 " segment %llu but belongs\n"
03364 "InnoDB: to segment %llu.\n",
03365 (ulong) space, (ulong) page,
03366 (ullint) descr_id,
03367 (ullint) seg_id);
03368 goto crash;
03369 }
03370
03371 not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03372 MLOG_4BYTES, mtr);
03373 if (xdes_is_full(descr, mtr)) {
03374
03375 flst_remove(seg_inode + FSEG_FULL,
03376 descr + XDES_FLST_NODE, mtr);
03377 flst_add_last(seg_inode + FSEG_NOT_FULL,
03378 descr + XDES_FLST_NODE, mtr);
03379 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03380 not_full_n_used + FSP_EXTENT_SIZE - 1,
03381 MLOG_4BYTES, mtr);
03382 } else {
03383 ut_a(not_full_n_used > 0);
03384 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03385 not_full_n_used - 1, MLOG_4BYTES, mtr);
03386 }
03387
03388 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
03389 xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
03390
03391 if (xdes_is_free(descr, mtr)) {
03392
03393 flst_remove(seg_inode + FSEG_NOT_FULL,
03394 descr + XDES_FLST_NODE, mtr);
03395 fsp_free_extent(space, zip_size, page, mtr);
03396 }
03397 }
03398
03399
03401 UNIV_INTERN
03402 void
03403 fseg_free_page(
03404
03405 fseg_header_t* seg_header,
03406 ulint space,
03407 ulint page,
03408 mtr_t* mtr)
03409 {
03410 ulint flags;
03411 ulint zip_size;
03412 fseg_inode_t* seg_inode;
03413 rw_lock_t* latch;
03414
03415 latch = fil_space_get_latch(space, &flags);
03416 zip_size = dict_table_flags_to_zip_size(flags);
03417
03418 ut_ad(!mutex_own(&kernel_mutex)
03419 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
03420
03421 mtr_x_lock(latch, mtr);
03422
03423 seg_inode = fseg_inode_get(seg_header, space, zip_size, mtr);
03424
03425 fseg_free_page_low(seg_inode, space, zip_size, page, mtr);
03426
03427 #ifdef UNIV_DEBUG_FILE_ACCESSES
03428 buf_page_set_file_page_was_freed(space, page);
03429 #endif
03430 }
03431
03432
03434 static
03435 void
03436 fseg_free_extent(
03437
03438 fseg_inode_t* seg_inode,
03439 ulint space,
03440 ulint zip_size,
03442 ulint page,
03443 mtr_t* mtr)
03444 {
03445 ulint first_page_in_extent;
03446 xdes_t* descr;
03447 ulint not_full_n_used;
03448 ulint descr_n_used;
03449 ulint i;
03450
03451 ut_ad(seg_inode && mtr);
03452
03453 descr = xdes_get_descriptor(space, zip_size, page, mtr);
03454
03455 ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
03456 ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
03457 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
03458 == FSEG_MAGIC_N_VALUE);
03459
03460 first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
03461
03462 for (i = 0; i < FSP_EXTENT_SIZE; i++) {
03463 if (FALSE == xdes_get_bit(descr, XDES_FREE_BIT, i, mtr)) {
03464
03465
03466
03467
03468 btr_search_drop_page_hash_when_freed(
03469 space, zip_size, first_page_in_extent + i);
03470 }
03471 }
03472
03473 if (xdes_is_full(descr, mtr)) {
03474 flst_remove(seg_inode + FSEG_FULL,
03475 descr + XDES_FLST_NODE, mtr);
03476 } else if (xdes_is_free(descr, mtr)) {
03477 flst_remove(seg_inode + FSEG_FREE,
03478 descr + XDES_FLST_NODE, mtr);
03479 } else {
03480 flst_remove(seg_inode + FSEG_NOT_FULL,
03481 descr + XDES_FLST_NODE, mtr);
03482
03483 not_full_n_used = mtr_read_ulint(
03484 seg_inode + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr);
03485
03486 descr_n_used = xdes_get_n_used(descr, mtr);
03487 ut_a(not_full_n_used >= descr_n_used);
03488 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03489 not_full_n_used - descr_n_used,
03490 MLOG_4BYTES, mtr);
03491 }
03492
03493 fsp_free_extent(space, zip_size, page, mtr);
03494
03495 #ifdef UNIV_DEBUG_FILE_ACCESSES
03496 for (i = 0; i < FSP_EXTENT_SIZE; i++) {
03497
03498 buf_page_set_file_page_was_freed(space,
03499 first_page_in_extent + i);
03500 }
03501 #endif
03502 }
03503
03504
03510 UNIV_INTERN
03511 ibool
03512 fseg_free_step(
03513
03514 fseg_header_t* header,
03518 mtr_t* mtr)
03519 {
03520 ulint n;
03521 ulint page;
03522 xdes_t* descr;
03523 fseg_inode_t* inode;
03524 ulint space;
03525 ulint flags;
03526 ulint zip_size;
03527 ulint header_page;
03528 rw_lock_t* latch;
03529
03530 space = page_get_space_id(page_align(header));
03531 header_page = page_get_page_no(page_align(header));
03532
03533 latch = fil_space_get_latch(space, &flags);
03534 zip_size = dict_table_flags_to_zip_size(flags);
03535
03536 ut_ad(!mutex_own(&kernel_mutex)
03537 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
03538
03539 mtr_x_lock(latch, mtr);
03540
03541 descr = xdes_get_descriptor(space, zip_size, header_page, mtr);
03542
03543
03544
03545
03546 ut_a(descr);
03547 ut_a(xdes_get_bit(descr, XDES_FREE_BIT,
03548 header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
03549 inode = fseg_inode_try_get(header, space, zip_size, mtr);
03550
03551 if (UNIV_UNLIKELY(inode == NULL)) {
03552 fprintf(stderr, "double free of inode from %u:%u\n",
03553 (unsigned) space, (unsigned) header_page);
03554 return(TRUE);
03555 }
03556
03557 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
03558
03559 if (descr != NULL) {
03560
03561 page = xdes_get_offset(descr);
03562
03563 fseg_free_extent(inode, space, zip_size, page, mtr);
03564
03565 return(FALSE);
03566 }
03567
03568
03569 n = fseg_find_last_used_frag_page_slot(inode, mtr);
03570
03571 if (n == ULINT_UNDEFINED) {
03572
03573 fsp_free_seg_inode(space, zip_size, inode, mtr);
03574
03575 return(TRUE);
03576 }
03577
03578 fseg_free_page_low(inode, space, zip_size,
03579 fseg_get_nth_frag_page_no(inode, n, mtr), mtr);
03580
03581 n = fseg_find_last_used_frag_page_slot(inode, mtr);
03582
03583 if (n == ULINT_UNDEFINED) {
03584
03585 fsp_free_seg_inode(space, zip_size, inode, mtr);
03586
03587 return(TRUE);
03588 }
03589
03590 return(FALSE);
03591 }
03592
03593
03597 UNIV_INTERN
03598 ibool
03599 fseg_free_step_not_header(
03600
03601 fseg_header_t* header,
03603 mtr_t* mtr)
03604 {
03605 ulint n;
03606 ulint page;
03607 xdes_t* descr;
03608 fseg_inode_t* inode;
03609 ulint space;
03610 ulint flags;
03611 ulint zip_size;
03612 ulint page_no;
03613 rw_lock_t* latch;
03614
03615 space = page_get_space_id(page_align(header));
03616
03617 latch = fil_space_get_latch(space, &flags);
03618 zip_size = dict_table_flags_to_zip_size(flags);
03619
03620 ut_ad(!mutex_own(&kernel_mutex)
03621 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
03622
03623 mtr_x_lock(latch, mtr);
03624
03625 inode = fseg_inode_get(header, space, zip_size, mtr);
03626
03627 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
03628
03629 if (descr != NULL) {
03630
03631 page = xdes_get_offset(descr);
03632
03633 fseg_free_extent(inode, space, zip_size, page, mtr);
03634
03635 return(FALSE);
03636 }
03637
03638
03639
03640 n = fseg_find_last_used_frag_page_slot(inode, mtr);
03641
03642 if (n == ULINT_UNDEFINED) {
03643 ut_error;
03644 }
03645
03646 page_no = fseg_get_nth_frag_page_no(inode, n, mtr);
03647
03648 if (page_no == page_get_page_no(page_align(header))) {
03649
03650 return(TRUE);
03651 }
03652
03653 fseg_free_page_low(inode, space, zip_size, page_no, mtr);
03654
03655 return(FALSE);
03656 }
03657
03658
03663 static
03664 xdes_t*
03665 fseg_get_first_extent(
03666
03667 fseg_inode_t* inode,
03668 ulint space,
03669 ulint zip_size,
03671 mtr_t* mtr)
03672 {
03673 fil_addr_t first;
03674 xdes_t* descr;
03675
03676 ut_ad(inode && mtr);
03677
03678 ut_ad(space == page_get_space_id(page_align(inode)));
03679 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
03680
03681 first = fil_addr_null;
03682
03683 if (flst_get_len(inode + FSEG_FULL, mtr) > 0) {
03684
03685 first = flst_get_first(inode + FSEG_FULL, mtr);
03686
03687 } else if (flst_get_len(inode + FSEG_NOT_FULL, mtr) > 0) {
03688
03689 first = flst_get_first(inode + FSEG_NOT_FULL, mtr);
03690
03691 } else if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
03692
03693 first = flst_get_first(inode + FSEG_FREE, mtr);
03694 }
03695
03696 if (first.page == FIL_NULL) {
03697
03698 return(NULL);
03699 }
03700 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
03701
03702 return(descr);
03703 }
03704
03705
03708 static
03709 ibool
03710 fseg_validate_low(
03711
03712 fseg_inode_t* inode,
03713 mtr_t* mtr2)
03714 {
03715 ulint space;
03716 ib_id_t seg_id;
03717 mtr_t mtr;
03718 xdes_t* descr;
03719 fil_addr_t node_addr;
03720 ulint n_used = 0;
03721 ulint n_used2 = 0;
03722
03723 ut_ad(mtr_memo_contains_page(mtr2, inode, MTR_MEMO_PAGE_X_FIX));
03724 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
03725
03726 space = page_get_space_id(page_align(inode));
03727
03728 seg_id = mach_read_from_8(inode + FSEG_ID);
03729 n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
03730 MLOG_4BYTES, mtr2);
03731 flst_validate(inode + FSEG_FREE, mtr2);
03732 flst_validate(inode + FSEG_NOT_FULL, mtr2);
03733 flst_validate(inode + FSEG_FULL, mtr2);
03734
03735
03736 node_addr = flst_get_first(inode + FSEG_FREE, mtr2);
03737
03738 while (!fil_addr_is_null(node_addr)) {
03739 ulint flags;
03740 ulint zip_size;
03741
03742 mtr_start(&mtr);
03743 mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
03744 zip_size = dict_table_flags_to_zip_size(flags);
03745
03746 descr = xdes_lst_get_descriptor(space, zip_size,
03747 node_addr, &mtr);
03748
03749 ut_a(xdes_get_n_used(descr, &mtr) == 0);
03750 ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
03751 ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
03752
03753 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
03754 mtr_commit(&mtr);
03755 }
03756
03757
03758
03759 node_addr = flst_get_first(inode + FSEG_NOT_FULL, mtr2);
03760
03761 while (!fil_addr_is_null(node_addr)) {
03762 ulint flags;
03763 ulint zip_size;
03764
03765 mtr_start(&mtr);
03766 mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
03767 zip_size = dict_table_flags_to_zip_size(flags);
03768
03769 descr = xdes_lst_get_descriptor(space, zip_size,
03770 node_addr, &mtr);
03771
03772 ut_a(xdes_get_n_used(descr, &mtr) > 0);
03773 ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
03774 ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
03775 ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
03776
03777 n_used2 += xdes_get_n_used(descr, &mtr);
03778
03779 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
03780 mtr_commit(&mtr);
03781 }
03782
03783
03784
03785 node_addr = flst_get_first(inode + FSEG_FULL, mtr2);
03786
03787 while (!fil_addr_is_null(node_addr)) {
03788 ulint flags;
03789 ulint zip_size;
03790
03791 mtr_start(&mtr);
03792 mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
03793 zip_size = dict_table_flags_to_zip_size(flags);
03794
03795 descr = xdes_lst_get_descriptor(space, zip_size,
03796 node_addr, &mtr);
03797
03798 ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
03799 ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
03800 ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
03801
03802 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
03803 mtr_commit(&mtr);
03804 }
03805
03806 ut_a(n_used == n_used2);
03807
03808 return(TRUE);
03809 }
03810
03811 #ifdef UNIV_DEBUG
03812
03815 UNIV_INTERN
03816 ibool
03817 fseg_validate(
03818
03819 fseg_header_t* header,
03820 mtr_t* mtr)
03821 {
03822 fseg_inode_t* inode;
03823 ibool ret;
03824 ulint space;
03825 ulint flags;
03826 ulint zip_size;
03827
03828 space = page_get_space_id(page_align(header));
03829
03830 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
03831 zip_size = dict_table_flags_to_zip_size(flags);
03832
03833 inode = fseg_inode_get(header, space, zip_size, mtr);
03834
03835 ret = fseg_validate_low(inode, mtr);
03836
03837 return(ret);
03838 }
03839 #endif
03840
03841
03843 static
03844 void
03845 fseg_print_low(
03846
03847 fseg_inode_t* inode,
03848 mtr_t* mtr)
03849 {
03850 ulint space;
03851 ulint n_used;
03852 ulint n_frag;
03853 ulint n_free;
03854 ulint n_not_full;
03855 ulint n_full;
03856 ulint reserved;
03857 ulint used;
03858 ulint page_no;
03859 ib_id_t seg_id;
03860
03861 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
03862 space = page_get_space_id(page_align(inode));
03863 page_no = page_get_page_no(page_align(inode));
03864
03865 reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
03866
03867 seg_id = mach_read_from_8(inode + FSEG_ID);
03868
03869 n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
03870 MLOG_4BYTES, mtr);
03871 n_frag = fseg_get_n_frag_pages(inode, mtr);
03872 n_free = flst_get_len(inode + FSEG_FREE, mtr);
03873 n_not_full = flst_get_len(inode + FSEG_NOT_FULL, mtr);
03874 n_full = flst_get_len(inode + FSEG_FULL, mtr);
03875
03876 fprintf(stderr,
03877 "SEGMENT id %llu space %lu; page %lu;"
03878 " res %lu used %lu; full ext %lu\n"
03879 "fragm pages %lu; free extents %lu;"
03880 " not full extents %lu: pages %lu\n",
03881 (ullint) seg_id,
03882 (ulong) space, (ulong) page_no,
03883 (ulong) reserved, (ulong) used, (ulong) n_full,
03884 (ulong) n_frag, (ulong) n_free, (ulong) n_not_full,
03885 (ulong) n_used);
03886 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
03887 }
03888
03889 #ifdef UNIV_BTR_PRINT
03890
03892 UNIV_INTERN
03893 void
03894 fseg_print(
03895
03896 fseg_header_t* header,
03897 mtr_t* mtr)
03898 {
03899 fseg_inode_t* inode;
03900 ulint space;
03901 ulint flags;
03902 ulint zip_size;
03903
03904 space = page_get_space_id(page_align(header));
03905
03906 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
03907 zip_size = dict_table_flags_to_zip_size(flags);
03908
03909 inode = fseg_inode_get(header, space, zip_size, mtr);
03910
03911 fseg_print_low(inode, mtr);
03912 }
03913 #endif
03914
03915
03918 UNIV_INTERN
03919 ibool
03920 fsp_validate(
03921
03922 ulint space)
03923 {
03924 fsp_header_t* header;
03925 fseg_inode_t* seg_inode;
03926 page_t* seg_inode_page;
03927 rw_lock_t* latch;
03928 ulint size;
03929 ulint flags;
03930 ulint zip_size;
03931 ulint free_limit;
03932 ulint frag_n_used;
03933 mtr_t mtr;
03934 mtr_t mtr2;
03935 xdes_t* descr;
03936 fil_addr_t node_addr;
03937 fil_addr_t next_node_addr;
03938 ulint descr_count = 0;
03939 ulint n_used = 0;
03940 ulint n_used2 = 0;
03941 ulint n_full_frag_pages;
03942 ulint n;
03943 ulint seg_inode_len_free;
03944 ulint seg_inode_len_full;
03945
03946 latch = fil_space_get_latch(space, &flags);
03947 zip_size = dict_table_flags_to_zip_size(flags);
03948 ut_a(ut_is_2pow(zip_size));
03949 ut_a(zip_size <= UNIV_PAGE_SIZE);
03950 ut_a(!zip_size || zip_size >= PAGE_ZIP_MIN_SIZE);
03951
03952
03953
03954 mtr_start(&mtr2);
03955 mtr_x_lock(latch, &mtr2);
03956
03957 mtr_start(&mtr);
03958 mtr_x_lock(latch, &mtr);
03959
03960 header = fsp_get_space_header(space, zip_size, &mtr);
03961
03962 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
03963 free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT,
03964 MLOG_4BYTES, &mtr);
03965 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
03966 MLOG_4BYTES, &mtr);
03967
03968 n_full_frag_pages = FSP_EXTENT_SIZE
03969 * flst_get_len(header + FSP_FULL_FRAG, &mtr);
03970
03971 if (UNIV_UNLIKELY(free_limit > size)) {
03972
03973 ut_a(space != 0);
03974 ut_a(size < FSP_EXTENT_SIZE);
03975 }
03976
03977 flst_validate(header + FSP_FREE, &mtr);
03978 flst_validate(header + FSP_FREE_FRAG, &mtr);
03979 flst_validate(header + FSP_FULL_FRAG, &mtr);
03980
03981 mtr_commit(&mtr);
03982
03983
03984 mtr_start(&mtr);
03985 mtr_x_lock(latch, &mtr);
03986
03987 header = fsp_get_space_header(space, zip_size, &mtr);
03988 node_addr = flst_get_first(header + FSP_FREE, &mtr);
03989
03990 mtr_commit(&mtr);
03991
03992 while (!fil_addr_is_null(node_addr)) {
03993 mtr_start(&mtr);
03994 mtr_x_lock(latch, &mtr);
03995
03996 descr_count++;
03997 descr = xdes_lst_get_descriptor(space, zip_size,
03998 node_addr, &mtr);
03999
04000 ut_a(xdes_get_n_used(descr, &mtr) == 0);
04001 ut_a(xdes_get_state(descr, &mtr) == XDES_FREE);
04002
04003 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
04004 mtr_commit(&mtr);
04005 }
04006
04007
04008 mtr_start(&mtr);
04009 mtr_x_lock(latch, &mtr);
04010
04011 header = fsp_get_space_header(space, zip_size, &mtr);
04012 node_addr = flst_get_first(header + FSP_FREE_FRAG, &mtr);
04013
04014 mtr_commit(&mtr);
04015
04016 while (!fil_addr_is_null(node_addr)) {
04017 mtr_start(&mtr);
04018 mtr_x_lock(latch, &mtr);
04019
04020 descr_count++;
04021 descr = xdes_lst_get_descriptor(space, zip_size,
04022 node_addr, &mtr);
04023
04024 ut_a(xdes_get_n_used(descr, &mtr) > 0);
04025 ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
04026 ut_a(xdes_get_state(descr, &mtr) == XDES_FREE_FRAG);
04027
04028 n_used += xdes_get_n_used(descr, &mtr);
04029 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
04030
04031 mtr_commit(&mtr);
04032 }
04033
04034
04035 mtr_start(&mtr);
04036 mtr_x_lock(latch, &mtr);
04037
04038 header = fsp_get_space_header(space, zip_size, &mtr);
04039 node_addr = flst_get_first(header + FSP_FULL_FRAG, &mtr);
04040
04041 mtr_commit(&mtr);
04042
04043 while (!fil_addr_is_null(node_addr)) {
04044 mtr_start(&mtr);
04045 mtr_x_lock(latch, &mtr);
04046
04047 descr_count++;
04048 descr = xdes_lst_get_descriptor(space, zip_size,
04049 node_addr, &mtr);
04050
04051 ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
04052 ut_a(xdes_get_state(descr, &mtr) == XDES_FULL_FRAG);
04053
04054 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
04055 mtr_commit(&mtr);
04056 }
04057
04058
04059 mtr_start(&mtr);
04060 mtr_x_lock(latch, &mtr);
04061
04062 header = fsp_get_space_header(space, zip_size, &mtr);
04063
04064 node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr);
04065
04066 seg_inode_len_full = flst_get_len(header + FSP_SEG_INODES_FULL, &mtr);
04067
04068 mtr_commit(&mtr);
04069
04070 while (!fil_addr_is_null(node_addr)) {
04071
04072 n = 0;
04073 do {
04074 mtr_start(&mtr);
04075 mtr_x_lock(latch, &mtr);
04076
04077 seg_inode_page = fut_get_ptr(
04078 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04079 - FSEG_INODE_PAGE_NODE;
04080
04081 seg_inode = fsp_seg_inode_page_get_nth_inode(
04082 seg_inode_page, n, zip_size, &mtr);
04083 ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
04084 fseg_validate_low(seg_inode, &mtr);
04085
04086 descr_count += flst_get_len(seg_inode + FSEG_FREE,
04087 &mtr);
04088 descr_count += flst_get_len(seg_inode + FSEG_FULL,
04089 &mtr);
04090 descr_count += flst_get_len(seg_inode + FSEG_NOT_FULL,
04091 &mtr);
04092
04093 n_used2 += fseg_get_n_frag_pages(seg_inode, &mtr);
04094
04095 next_node_addr = flst_get_next_addr(
04096 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04097 mtr_commit(&mtr);
04098 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04099
04100 node_addr = next_node_addr;
04101 }
04102
04103 mtr_start(&mtr);
04104 mtr_x_lock(latch, &mtr);
04105
04106 header = fsp_get_space_header(space, zip_size, &mtr);
04107
04108 node_addr = flst_get_first(header + FSP_SEG_INODES_FREE, &mtr);
04109
04110 seg_inode_len_free = flst_get_len(header + FSP_SEG_INODES_FREE, &mtr);
04111
04112 mtr_commit(&mtr);
04113
04114 while (!fil_addr_is_null(node_addr)) {
04115
04116 n = 0;
04117
04118 do {
04119 mtr_start(&mtr);
04120 mtr_x_lock(latch, &mtr);
04121
04122 seg_inode_page = fut_get_ptr(
04123 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04124 - FSEG_INODE_PAGE_NODE;
04125
04126 seg_inode = fsp_seg_inode_page_get_nth_inode(
04127 seg_inode_page, n, zip_size, &mtr);
04128 if (mach_read_from_8(seg_inode + FSEG_ID)) {
04129 fseg_validate_low(seg_inode, &mtr);
04130
04131 descr_count += flst_get_len(
04132 seg_inode + FSEG_FREE, &mtr);
04133 descr_count += flst_get_len(
04134 seg_inode + FSEG_FULL, &mtr);
04135 descr_count += flst_get_len(
04136 seg_inode + FSEG_NOT_FULL, &mtr);
04137 n_used2 += fseg_get_n_frag_pages(
04138 seg_inode, &mtr);
04139 }
04140
04141 next_node_addr = flst_get_next_addr(
04142 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04143 mtr_commit(&mtr);
04144 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04145
04146 node_addr = next_node_addr;
04147 }
04148
04149 ut_a(descr_count * FSP_EXTENT_SIZE == free_limit);
04150 if (!zip_size) {
04151 ut_a(n_used + n_full_frag_pages
04152 == n_used2 + 2 * ((free_limit + (UNIV_PAGE_SIZE - 1))
04153 / UNIV_PAGE_SIZE)
04154 + seg_inode_len_full + seg_inode_len_free);
04155 } else {
04156 ut_a(n_used + n_full_frag_pages
04157 == n_used2 + 2 * ((free_limit + (zip_size - 1))
04158 / zip_size)
04159 + seg_inode_len_full + seg_inode_len_free);
04160 }
04161 ut_a(frag_n_used == n_used);
04162
04163 mtr_commit(&mtr2);
04164
04165 return(TRUE);
04166 }
04167
04168
04170 UNIV_INTERN
04171 void
04172 fsp_print(
04173
04174 ulint space)
04175 {
04176 fsp_header_t* header;
04177 fseg_inode_t* seg_inode;
04178 page_t* seg_inode_page;
04179 rw_lock_t* latch;
04180 ulint flags;
04181 ulint zip_size;
04182 ulint size;
04183 ulint free_limit;
04184 ulint frag_n_used;
04185 fil_addr_t node_addr;
04186 fil_addr_t next_node_addr;
04187 ulint n_free;
04188 ulint n_free_frag;
04189 ulint n_full_frag;
04190 ib_id_t seg_id;
04191 ulint n;
04192 ulint n_segs = 0;
04193 mtr_t mtr;
04194 mtr_t mtr2;
04195
04196 latch = fil_space_get_latch(space, &flags);
04197 zip_size = dict_table_flags_to_zip_size(flags);
04198
04199
04200
04201
04202 mtr_start(&mtr2);
04203
04204 mtr_x_lock(latch, &mtr2);
04205
04206 mtr_start(&mtr);
04207
04208 mtr_x_lock(latch, &mtr);
04209
04210 header = fsp_get_space_header(space, zip_size, &mtr);
04211
04212 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
04213
04214 free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES,
04215 &mtr);
04216 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
04217 &mtr);
04218 n_free = flst_get_len(header + FSP_FREE, &mtr);
04219 n_free_frag = flst_get_len(header + FSP_FREE_FRAG, &mtr);
04220 n_full_frag = flst_get_len(header + FSP_FULL_FRAG, &mtr);
04221
04222 seg_id = mach_read_from_8(header + FSP_SEG_ID);
04223
04224 fprintf(stderr,
04225 "FILE SPACE INFO: id %lu\n"
04226 "size %lu, free limit %lu, free extents %lu\n"
04227 "not full frag extents %lu: used pages %lu,"
04228 " full frag extents %lu\n"
04229 "first seg id not used %llu\n",
04230 (ulong) space,
04231 (ulong) size, (ulong) free_limit, (ulong) n_free,
04232 (ulong) n_free_frag, (ulong) frag_n_used, (ulong) n_full_frag,
04233 (ullint) seg_id);
04234
04235 mtr_commit(&mtr);
04236
04237
04238
04239 mtr_start(&mtr);
04240 mtr_x_lock(latch, &mtr);
04241
04242 header = fsp_get_space_header(space, zip_size, &mtr);
04243
04244 node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr);
04245
04246 mtr_commit(&mtr);
04247
04248 while (!fil_addr_is_null(node_addr)) {
04249
04250 n = 0;
04251
04252 do {
04253
04254 mtr_start(&mtr);
04255 mtr_x_lock(latch, &mtr);
04256
04257 seg_inode_page = fut_get_ptr(
04258 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04259 - FSEG_INODE_PAGE_NODE;
04260
04261 seg_inode = fsp_seg_inode_page_get_nth_inode(
04262 seg_inode_page, n, zip_size, &mtr);
04263 ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
04264 fseg_print_low(seg_inode, &mtr);
04265
04266 n_segs++;
04267
04268 next_node_addr = flst_get_next_addr(
04269 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04270 mtr_commit(&mtr);
04271 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04272
04273 node_addr = next_node_addr;
04274 }
04275
04276 mtr_start(&mtr);
04277 mtr_x_lock(latch, &mtr);
04278
04279 header = fsp_get_space_header(space, zip_size, &mtr);
04280
04281 node_addr = flst_get_first(header + FSP_SEG_INODES_FREE, &mtr);
04282
04283 mtr_commit(&mtr);
04284
04285 while (!fil_addr_is_null(node_addr)) {
04286
04287 n = 0;
04288
04289 do {
04290
04291 mtr_start(&mtr);
04292 mtr_x_lock(latch, &mtr);
04293
04294 seg_inode_page = fut_get_ptr(
04295 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04296 - FSEG_INODE_PAGE_NODE;
04297
04298 seg_inode = fsp_seg_inode_page_get_nth_inode(
04299 seg_inode_page, n, zip_size, &mtr);
04300 if (mach_read_from_8(seg_inode + FSEG_ID)) {
04301
04302 fseg_print_low(seg_inode, &mtr);
04303 n_segs++;
04304 }
04305
04306 next_node_addr = flst_get_next_addr(
04307 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04308 mtr_commit(&mtr);
04309 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04310
04311 node_addr = next_node_addr;
04312 }
04313
04314 mtr_commit(&mtr2);
04315
04316 fprintf(stderr, "NUMBER of file segments: %lu\n", (ulong) n_segs);
04317 }
04318 #endif