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 #ifndef DOXYGEN
00654 # if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET \
00655 + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
00656 # error
00657 # endif
00658 # if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
00659 + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
00660 # error
00661 # endif
00662 #endif
00663 ut_ad(ut_is_2pow(zip_size));
00664
00665 if (!zip_size) {
00666 return(ut_2pow_round(offset, UNIV_PAGE_SIZE));
00667 } else {
00668 ut_ad(zip_size > XDES_ARR_OFFSET
00669 + (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE);
00670 return(ut_2pow_round(offset, zip_size));
00671 }
00672 }
00673
00674
00677 UNIV_INLINE
00678 ulint
00679 xdes_calc_descriptor_index(
00680
00681 ulint zip_size,
00683 ulint offset)
00684 {
00685 ut_ad(ut_is_2pow(zip_size));
00686
00687 if (!zip_size) {
00688 return(ut_2pow_remainder(offset, UNIV_PAGE_SIZE)
00689 / FSP_EXTENT_SIZE);
00690 } else {
00691 return(ut_2pow_remainder(offset, zip_size) / FSP_EXTENT_SIZE);
00692 }
00693 }
00694
00695
00703 UNIV_INLINE
00704 xdes_t*
00705 xdes_get_descriptor_with_space_hdr(
00706
00707 fsp_header_t* sp_header,
00708 ulint space,
00709 ulint offset,
00713 mtr_t* mtr)
00714 {
00715 ulint limit;
00716 ulint size;
00717 ulint zip_size;
00718 ulint descr_page_no;
00719 page_t* descr_page;
00720
00721 ut_ad(mtr);
00722 ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
00723 MTR_MEMO_X_LOCK));
00724 ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
00725 || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
00726 ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
00727
00728 limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
00729 size = mach_read_from_4(sp_header + FSP_SIZE);
00730 zip_size = dict_table_flags_to_zip_size(
00731 mach_read_from_4(sp_header + FSP_SPACE_FLAGS));
00732
00733
00734
00735 if ((offset >= size) || (offset > limit)) {
00736
00737 return(NULL);
00738 }
00739
00740
00741
00742 if (offset == limit) {
00743 fsp_fill_free_list(FALSE, space, sp_header, mtr);
00744 }
00745
00746 descr_page_no = xdes_calc_descriptor_page(zip_size, offset);
00747
00748 if (descr_page_no == 0) {
00749
00750
00751 descr_page = page_align(sp_header);
00752 } else {
00753 buf_block_t* block;
00754
00755 block = buf_page_get(space, zip_size, descr_page_no,
00756 RW_X_LATCH, mtr);
00757 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
00758
00759 descr_page = buf_block_get_frame(block);
00760 }
00761
00762 return(descr_page + XDES_ARR_OFFSET
00763 + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset));
00764 }
00765
00766
00775 static
00776 xdes_t*
00777 xdes_get_descriptor(
00778
00779 ulint space,
00780 ulint zip_size,
00782 ulint offset,
00784 mtr_t* mtr)
00785 {
00786 buf_block_t* block;
00787 fsp_header_t* sp_header;
00788
00789 block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
00790 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
00791
00792 sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
00793 return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset,
00794 mtr));
00795 }
00796
00797
00802 UNIV_INLINE
00803 xdes_t*
00804 xdes_lst_get_descriptor(
00805
00806 ulint space,
00807 ulint zip_size,
00809 fil_addr_t lst_node,
00811 mtr_t* mtr)
00812 {
00813 xdes_t* descr;
00814
00815 ut_ad(mtr);
00816 ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
00817 MTR_MEMO_X_LOCK));
00818 descr = fut_get_ptr(space, zip_size, lst_node, RW_X_LATCH, mtr)
00819 - XDES_FLST_NODE;
00820
00821 return(descr);
00822 }
00823
00824
00827 UNIV_INLINE
00828 ulint
00829 xdes_get_offset(
00830
00831 xdes_t* descr)
00832 {
00833 ut_ad(descr);
00834
00835 return(page_get_page_no(page_align(descr))
00836 + ((page_offset(descr) - XDES_ARR_OFFSET) / XDES_SIZE)
00837 * FSP_EXTENT_SIZE);
00838 }
00839 #endif
00840
00841
00843 static
00844 void
00845 fsp_init_file_page_low(
00846
00847 buf_block_t* block)
00848 {
00849 page_t* page = buf_block_get_frame(block);
00850 page_zip_des_t* page_zip= buf_block_get_page_zip(block);
00851
00852 #ifndef UNIV_HOTBACKUP
00853 block->check_index_page_at_flush = FALSE;
00854 #endif
00855
00856 if (UNIV_LIKELY_NULL(page_zip)) {
00857 memset(page, 0, UNIV_PAGE_SIZE);
00858 memset(page_zip->data, 0, page_zip_get_size(page_zip));
00859 mach_write_to_4(page + FIL_PAGE_OFFSET,
00860 buf_block_get_page_no(block));
00861 mach_write_to_4(page
00862 + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
00863 buf_block_get_space(block));
00864 memcpy(page_zip->data + FIL_PAGE_OFFSET,
00865 page + FIL_PAGE_OFFSET, 4);
00866 memcpy(page_zip->data + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
00867 page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 4);
00868 return;
00869 }
00870
00871 memset(page, 0, UNIV_PAGE_SIZE);
00872 mach_write_to_4(page + FIL_PAGE_OFFSET, buf_block_get_page_no(block));
00873 mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
00874 buf_block_get_space(block));
00875 }
00876
00877 #ifndef UNIV_HOTBACKUP
00878
00880 static
00881 void
00882 fsp_init_file_page(
00883
00884 buf_block_t* block,
00885 mtr_t* mtr)
00886 {
00887 fsp_init_file_page_low(block);
00888
00889 mlog_write_initial_log_record(buf_block_get_frame(block),
00890 MLOG_INIT_FILE_PAGE, mtr);
00891 }
00892 #endif
00893
00894
00897 UNIV_INTERN
00898 byte*
00899 fsp_parse_init_file_page(
00900
00901 byte* ptr,
00902 byte* ,
00903 buf_block_t* block)
00904 {
00905 ut_ad(ptr && end_ptr);
00906
00907 if (block) {
00908 fsp_init_file_page_low(block);
00909 }
00910
00911 return(ptr);
00912 }
00913
00914
00916 UNIV_INTERN
00917 void
00918 fsp_init(void)
00919
00920 {
00921
00922 }
00923
00924
00928 UNIV_INTERN
00929 void
00930 fsp_header_init_fields(
00931
00932 page_t* page,
00933 ulint space_id,
00934 ulint flags)
00936 {
00937
00938
00939
00940
00941 ut_a(flags != DICT_TF_COMPACT);
00942
00943 mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page,
00944 space_id);
00945 mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page,
00946 flags);
00947 }
00948
00949 #ifndef UNIV_HOTBACKUP
00950
00953 UNIV_INTERN
00954 void
00955 fsp_header_init(
00956
00957 ulint space,
00958 ulint size,
00959 mtr_t* mtr)
00960 {
00961 fsp_header_t* header;
00962 buf_block_t* block;
00963 page_t* page;
00964 ulint flags;
00965 ulint zip_size;
00966
00967 ut_ad(mtr);
00968
00969 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
00970
00971 zip_size = dict_table_flags_to_zip_size(flags);
00972 block = buf_page_create(space, 0, zip_size, mtr);
00973 buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
00974 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
00975
00976
00977
00978 fsp_init_file_page(block, mtr);
00979 page = buf_block_get_frame(block);
00980
00981 mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_FSP_HDR,
00982 MLOG_2BYTES, mtr);
00983
00984 header = FSP_HEADER_OFFSET + page;
00985
00986 mlog_write_ulint(header + FSP_SPACE_ID, space, MLOG_4BYTES, mtr);
00987 mlog_write_ulint(header + FSP_NOT_USED, 0, MLOG_4BYTES, mtr);
00988
00989 mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr);
00990 mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr);
00991 mlog_write_ulint(header + FSP_SPACE_FLAGS, flags,
00992 MLOG_4BYTES, mtr);
00993 mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr);
00994
00995 flst_init(header + FSP_FREE, mtr);
00996 flst_init(header + FSP_FREE_FRAG, mtr);
00997 flst_init(header + FSP_FULL_FRAG, mtr);
00998 flst_init(header + FSP_SEG_INODES_FULL, mtr);
00999 flst_init(header + FSP_SEG_INODES_FREE, mtr);
01000
01001 mlog_write_ull(header + FSP_SEG_ID, 1, mtr);
01002 if (space == 0) {
01003 fsp_fill_free_list(FALSE, space, header, mtr);
01004 btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
01005 0, 0, DICT_IBUF_ID_MIN + space,
01006 dict_ind_redundant, mtr);
01007 } else {
01008 fsp_fill_free_list(TRUE, space, header, mtr);
01009 }
01010 }
01011 #endif
01012
01013
01016 UNIV_INTERN
01017 ulint
01018 fsp_header_get_space_id(
01019
01020 const page_t* page)
01021 {
01022 ulint fsp_id;
01023 ulint id;
01024
01025 fsp_id = mach_read_from_4(FSP_HEADER_OFFSET + page + FSP_SPACE_ID);
01026
01027 id = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
01028
01029 if (id != fsp_id) {
01030 fprintf(stderr,
01031 "InnoDB: Error: space id in fsp header %lu,"
01032 " but in the page header %lu\n",
01033 (ulong) fsp_id, (ulong) id);
01034
01035 return(ULINT_UNDEFINED);
01036 }
01037
01038 return(id);
01039 }
01040
01041
01044 UNIV_INTERN
01045 ulint
01046 fsp_header_get_flags(
01047
01048 const page_t* page)
01049 {
01050 ut_ad(!page_offset(page));
01051
01052 return(mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page));
01053 }
01054
01055
01058 UNIV_INTERN
01059 ulint
01060 fsp_header_get_zip_size(
01061
01062 const page_t* page)
01063 {
01064 ulint flags = fsp_header_get_flags(page);
01065
01066 return(dict_table_flags_to_zip_size(flags));
01067 }
01068
01069 #ifndef UNIV_HOTBACKUP
01070
01072 UNIV_INTERN
01073 void
01074 fsp_header_inc_size(
01075
01076 ulint space,
01077 ulint size_inc,
01078 mtr_t* mtr)
01079 {
01080 fsp_header_t* header;
01081 ulint size;
01082 ulint flags;
01083
01084 ut_ad(mtr);
01085
01086 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
01087
01088 header = fsp_get_space_header(space,
01089 dict_table_flags_to_zip_size(flags),
01090 mtr);
01091
01092 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01093
01094 mlog_write_ulint(header + FSP_SIZE, size + size_inc, MLOG_4BYTES,
01095 mtr);
01096 }
01097
01098
01104 UNIV_INTERN
01105 ulint
01106 fsp_header_get_free_limit(void)
01107
01108 {
01109 fsp_header_t* header;
01110 ulint limit;
01111 mtr_t mtr;
01112
01113 mtr_start(&mtr);
01114
01115 mtr_x_lock(fil_space_get_latch(0, NULL), &mtr);
01116
01117 header = fsp_get_space_header(0, 0, &mtr);
01118
01119 limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, &mtr);
01120
01121 limit /= ((1024 * 1024) / UNIV_PAGE_SIZE);
01122
01123 log_fsp_current_free_limit_set_and_checkpoint(limit);
01124
01125 mtr_commit(&mtr);
01126
01127 return(limit);
01128 }
01129
01130
01136 UNIV_INTERN
01137 ulint
01138 fsp_header_get_tablespace_size(void)
01139
01140 {
01141 fsp_header_t* header;
01142 ulint size;
01143 mtr_t mtr;
01144
01145 mtr_start(&mtr);
01146
01147 mtr_x_lock(fil_space_get_latch(0, NULL), &mtr);
01148
01149 header = fsp_get_space_header(0, 0, &mtr);
01150
01151 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
01152
01153 mtr_commit(&mtr);
01154
01155 return(size);
01156 }
01157
01158
01162 static
01163 ibool
01164 fsp_try_extend_data_file_with_pages(
01165
01166 ulint space,
01167 ulint page_no,
01168 fsp_header_t* header,
01169 mtr_t* mtr)
01170 {
01171 ibool success;
01172 ulint actual_size;
01173 ulint size;
01174
01175 ut_a(space != 0);
01176
01177 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01178
01179 ut_a(page_no >= size);
01180
01181 success = fil_extend_space_to_desired_size(&actual_size, space,
01182 page_no + 1);
01183
01184
01185
01186 mlog_write_ulint(header + FSP_SIZE, actual_size, MLOG_4BYTES, mtr);
01187
01188 return(success);
01189 }
01190
01191
01194 static
01195 ibool
01196 fsp_try_extend_data_file(
01197
01198 ulint* actual_increase,
01203 ulint space,
01204 fsp_header_t* header,
01205 mtr_t* mtr)
01206 {
01207 ulint size;
01208 ulint zip_size;
01209 ulint new_size;
01210 ulint old_size;
01211 ulint size_increase;
01212 ulint actual_size;
01213 ibool success;
01214
01215 *actual_increase = 0;
01216
01217 if (space == 0 && !srv_auto_extend_last_data_file) {
01218
01219
01220
01221
01222
01223 if (fsp_tbs_full_error_printed == FALSE) {
01224 fprintf(stderr,
01225 "InnoDB: Error: Data file(s) ran"
01226 " out of space.\n"
01227 "Please add another data file or"
01228 " use \'autoextend\' for the last"
01229 " data file.\n");
01230 fsp_tbs_full_error_printed = TRUE;
01231 }
01232 return(FALSE);
01233 }
01234
01235 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01236 zip_size = dict_table_flags_to_zip_size(
01237 mach_read_from_4(header + FSP_SPACE_FLAGS));
01238
01239 old_size = size;
01240
01241 if (space == 0) {
01242 if (!srv_last_file_size_max) {
01243 size_increase = SRV_AUTO_EXTEND_INCREMENT;
01244 } else {
01245 if (srv_last_file_size_max
01246 < srv_data_file_sizes[srv_n_data_files - 1]) {
01247
01248 fprintf(stderr,
01249 "InnoDB: Error: Last data file size"
01250 " is %lu, max size allowed %lu\n",
01251 (ulong) srv_data_file_sizes[
01252 srv_n_data_files - 1],
01253 (ulong) srv_last_file_size_max);
01254 }
01255
01256 size_increase = srv_last_file_size_max
01257 - srv_data_file_sizes[srv_n_data_files - 1];
01258 if (size_increase > SRV_AUTO_EXTEND_INCREMENT) {
01259 size_increase = SRV_AUTO_EXTEND_INCREMENT;
01260 }
01261 }
01262 } else {
01263
01264
01265
01266
01267 ulint extent_size;
01269 if (!zip_size) {
01270 extent_size = FSP_EXTENT_SIZE;
01271 } else {
01272 extent_size = FSP_EXTENT_SIZE
01273 * UNIV_PAGE_SIZE / zip_size;
01274 }
01275
01276 if (size < extent_size) {
01277
01278 success = fsp_try_extend_data_file_with_pages(
01279 space, extent_size - 1, header, mtr);
01280 if (!success) {
01281 new_size = mtr_read_ulint(header + FSP_SIZE,
01282 MLOG_4BYTES, mtr);
01283
01284 *actual_increase = new_size - old_size;
01285
01286 return(FALSE);
01287 }
01288
01289 size = extent_size;
01290 }
01291
01292 if (size < 32 * extent_size) {
01293 size_increase = extent_size;
01294 } else {
01295
01296
01297
01298 size_increase = FSP_FREE_ADD * extent_size;
01299 }
01300 }
01301
01302 if (size_increase == 0) {
01303
01304 return(TRUE);
01305 }
01306
01307 success = fil_extend_space_to_desired_size(&actual_size, space,
01308 size + size_increase);
01309
01310
01311
01312 if (!zip_size) {
01313 new_size = ut_calc_align_down(actual_size,
01314 (1024 * 1024) / UNIV_PAGE_SIZE);
01315 } else {
01316 new_size = ut_calc_align_down(actual_size,
01317 (1024 * 1024) / zip_size);
01318 }
01319 mlog_write_ulint(header + FSP_SIZE, new_size, MLOG_4BYTES, mtr);
01320
01321 *actual_increase = new_size - old_size;
01322
01323 return(TRUE);
01324 }
01325
01326
01330 static
01331 void
01332 fsp_fill_free_list(
01333
01334 ibool init_space,
01339 ulint space,
01340 fsp_header_t* header,
01341 mtr_t* mtr)
01342 {
01343 ulint limit;
01344 ulint size;
01345 ulint zip_size;
01346 xdes_t* descr;
01347 ulint count = 0;
01348 ulint frag_n_used;
01349 ulint actual_increase;
01350 ulint i;
01351 mtr_t ibuf_mtr;
01352
01353 ut_ad(header && mtr);
01354 ut_ad(page_offset(header) == FSP_HEADER_OFFSET);
01355
01356
01357 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01358 limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr);
01359
01360 zip_size = dict_table_flags_to_zip_size(
01361 mach_read_from_4(FSP_SPACE_FLAGS + header));
01362 ut_a(ut_is_2pow(zip_size));
01363 ut_a(zip_size <= UNIV_PAGE_SIZE);
01364 ut_a(!zip_size || zip_size >= PAGE_ZIP_MIN_SIZE);
01365
01366 if (space == 0 && srv_auto_extend_last_data_file
01367 && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
01368
01369
01370 fsp_try_extend_data_file(&actual_increase, space, header, mtr);
01371 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01372 }
01373
01374 if (space != 0 && !init_space
01375 && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
01376
01377
01378 fsp_try_extend_data_file(&actual_increase, space, header, mtr);
01379 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01380 }
01381
01382 i = limit;
01383
01384 while ((init_space && i < 1)
01385 || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
01386
01387 ibool init_xdes;
01388 if (zip_size) {
01389 init_xdes = ut_2pow_remainder(i, zip_size) == 0;
01390 } else {
01391 init_xdes = ut_2pow_remainder(i, UNIV_PAGE_SIZE) == 0;
01392 }
01393
01394 mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
01395 MLOG_4BYTES, mtr);
01396
01397
01398
01399 if (space == 0) {
01400 ut_a(!zip_size);
01401 log_fsp_current_free_limit_set_and_checkpoint(
01402 (i + FSP_EXTENT_SIZE)
01403 / ((1024 * 1024) / UNIV_PAGE_SIZE));
01404 }
01405
01406 if (UNIV_UNLIKELY(init_xdes)) {
01407
01408 buf_block_t* block;
01409
01410
01411
01412
01413
01414 if (i > 0) {
01415 block = buf_page_create(
01416 space, i, zip_size, mtr);
01417 buf_page_get(space, zip_size, i,
01418 RW_X_LATCH, mtr);
01419 buf_block_dbg_add_level(block,
01420 SYNC_FSP_PAGE);
01421
01422 fsp_init_file_page(block, mtr);
01423 mlog_write_ulint(buf_block_get_frame(block)
01424 + FIL_PAGE_TYPE,
01425 FIL_PAGE_TYPE_XDES,
01426 MLOG_2BYTES, mtr);
01427 }
01428
01429
01430
01431
01432
01433
01434 mtr_start(&ibuf_mtr);
01435
01436 block = buf_page_create(space,
01437 i + FSP_IBUF_BITMAP_OFFSET,
01438 zip_size, &ibuf_mtr);
01439 buf_page_get(space, zip_size,
01440 i + FSP_IBUF_BITMAP_OFFSET,
01441 RW_X_LATCH, &ibuf_mtr);
01442 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01443
01444 fsp_init_file_page(block, &ibuf_mtr);
01445
01446 ibuf_bitmap_page_init(block, &ibuf_mtr);
01447
01448 mtr_commit(&ibuf_mtr);
01449 }
01450
01451 descr = xdes_get_descriptor_with_space_hdr(header, space, i,
01452 mtr);
01453 xdes_init(descr, mtr);
01454
01455 #if UNIV_PAGE_SIZE % FSP_EXTENT_SIZE
01456 # error "UNIV_PAGE_SIZE % FSP_EXTENT_SIZE != 0"
01457 #endif
01458 #if PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE
01459 # error "PAGE_ZIP_MIN_SIZE % FSP_EXTENT_SIZE != 0"
01460 #endif
01461
01462 if (UNIV_UNLIKELY(init_xdes)) {
01463
01464
01465
01466
01467
01468 xdes_set_bit(descr, XDES_FREE_BIT, 0, FALSE, mtr);
01469 xdes_set_bit(descr, XDES_FREE_BIT,
01470 FSP_IBUF_BITMAP_OFFSET, FALSE, mtr);
01471 xdes_set_state(descr, XDES_FREE_FRAG, mtr);
01472
01473 flst_add_last(header + FSP_FREE_FRAG,
01474 descr + XDES_FLST_NODE, mtr);
01475 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
01476 MLOG_4BYTES, mtr);
01477 mlog_write_ulint(header + FSP_FRAG_N_USED,
01478 frag_n_used + 2, MLOG_4BYTES, mtr);
01479 } else {
01480 flst_add_last(header + FSP_FREE,
01481 descr + XDES_FLST_NODE, mtr);
01482 count++;
01483 }
01484
01485 i += FSP_EXTENT_SIZE;
01486 }
01487 }
01488
01489
01492 static
01493 xdes_t*
01494 fsp_alloc_free_extent(
01495
01496 ulint space,
01497 ulint zip_size,
01499 ulint hint,
01502 mtr_t* mtr)
01503 {
01504 fsp_header_t* header;
01505 fil_addr_t first;
01506 xdes_t* descr;
01507
01508 ut_ad(mtr);
01509
01510 header = fsp_get_space_header(space, zip_size, mtr);
01511
01512 descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
01513
01514 if (descr && (xdes_get_state(descr, mtr) == XDES_FREE)) {
01515
01516 } else {
01517
01518 first = flst_get_first(header + FSP_FREE, mtr);
01519
01520 if (fil_addr_is_null(first)) {
01521 fsp_fill_free_list(FALSE, space, header, mtr);
01522
01523 first = flst_get_first(header + FSP_FREE, mtr);
01524 }
01525
01526 if (fil_addr_is_null(first)) {
01527
01528 return(NULL);
01529 }
01530
01531 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
01532 }
01533
01534 flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
01535
01536 return(descr);
01537 }
01538
01539
01542 static
01543 ulint
01544 fsp_alloc_free_page(
01545
01546 ulint space,
01547 ulint zip_size,
01549 ulint hint,
01550 mtr_t* mtr)
01551 {
01552 fsp_header_t* header;
01553 fil_addr_t first;
01554 xdes_t* descr;
01555 buf_block_t* block;
01556 ulint free;
01557 ulint frag_n_used;
01558 ulint page_no;
01559 ulint space_size;
01560 ibool success;
01561
01562 ut_ad(mtr);
01563
01564 header = fsp_get_space_header(space, zip_size, mtr);
01565
01566
01567 descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
01568
01569 if (descr && (xdes_get_state(descr, mtr) == XDES_FREE_FRAG)) {
01570
01571 } else {
01572
01573 first = flst_get_first(header + FSP_FREE_FRAG, mtr);
01574
01575 if (fil_addr_is_null(first)) {
01576
01577
01578
01579
01580
01581
01582
01583 descr = fsp_alloc_free_extent(space, zip_size,
01584 hint, mtr);
01585
01586 if (descr == NULL) {
01587
01588
01589 return(FIL_NULL);
01590 }
01591
01592 xdes_set_state(descr, XDES_FREE_FRAG, mtr);
01593 flst_add_last(header + FSP_FREE_FRAG,
01594 descr + XDES_FLST_NODE, mtr);
01595 } else {
01596 descr = xdes_lst_get_descriptor(space, zip_size,
01597 first, mtr);
01598 }
01599
01600
01601 hint = 0;
01602 }
01603
01604
01605
01606
01607 free = xdes_find_bit(descr, XDES_FREE_BIT, TRUE,
01608 hint % FSP_EXTENT_SIZE, mtr);
01609 if (free == ULINT_UNDEFINED) {
01610
01611 ut_print_buf(stderr, ((byte*)descr) - 500, 1000);
01612 putc('\n', stderr);
01613
01614 ut_error;
01615 }
01616
01617 page_no = xdes_get_offset(descr) + free;
01618
01619 space_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
01620
01621 if (space_size <= page_no) {
01622
01623
01624
01625 ut_a(space != 0);
01626 if (page_no >= FSP_EXTENT_SIZE) {
01627 fprintf(stderr,
01628 "InnoDB: Error: trying to extend a"
01629 " single-table tablespace %lu\n"
01630 "InnoDB: by single page(s) though the"
01631 " space size %lu. Page no %lu.\n",
01632 (ulong) space, (ulong) space_size,
01633 (ulong) page_no);
01634 return(FIL_NULL);
01635 }
01636 success = fsp_try_extend_data_file_with_pages(space, page_no,
01637 header, mtr);
01638 if (!success) {
01639
01640 return(FIL_NULL);
01641 }
01642 }
01643
01644 xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
01645
01646
01647 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
01648 mtr);
01649 frag_n_used++;
01650 mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
01651 mtr);
01652 if (xdes_is_full(descr, mtr)) {
01653
01654 flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
01655 mtr);
01656 xdes_set_state(descr, XDES_FULL_FRAG, mtr);
01657
01658 flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
01659 mtr);
01660 mlog_write_ulint(header + FSP_FRAG_N_USED,
01661 frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
01662 mtr);
01663 }
01664
01665
01666
01667
01668
01669 buf_page_create(space, page_no, zip_size, mtr);
01670
01671 block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
01672 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01673
01674
01675 fsp_init_file_page(block, mtr);
01676
01677 return(page_no);
01678 }
01679
01680
01682 static
01683 void
01684 fsp_free_page(
01685
01686 ulint space,
01687 ulint zip_size,
01689 ulint page,
01690 mtr_t* mtr)
01691 {
01692 fsp_header_t* header;
01693 xdes_t* descr;
01694 ulint state;
01695 ulint frag_n_used;
01696
01697 ut_ad(mtr);
01698
01699
01700
01701 header = fsp_get_space_header(space, zip_size, mtr);
01702
01703 descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
01704
01705 state = xdes_get_state(descr, mtr);
01706
01707 if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) {
01708 fprintf(stderr,
01709 "InnoDB: Error: File space extent descriptor"
01710 " of page %lu has state %lu\n",
01711 (ulong) page,
01712 (ulong) state);
01713 fputs("InnoDB: Dump of descriptor: ", stderr);
01714 ut_print_buf(stderr, ((byte*)descr) - 50, 200);
01715 putc('\n', stderr);
01716
01717 if (state == XDES_FREE) {
01718
01719
01720
01721 return;
01722 }
01723
01724 ut_error;
01725 }
01726
01727 if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
01728 fprintf(stderr,
01729 "InnoDB: Error: File space extent descriptor"
01730 " of page %lu says it is free\n"
01731 "InnoDB: Dump of descriptor: ", (ulong) page);
01732 ut_print_buf(stderr, ((byte*)descr) - 50, 200);
01733 putc('\n', stderr);
01734
01735
01736
01737
01738 return;
01739 }
01740
01741 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
01742 xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
01743
01744 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
01745 mtr);
01746 if (state == XDES_FULL_FRAG) {
01747
01748 flst_remove(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
01749 mtr);
01750 xdes_set_state(descr, XDES_FREE_FRAG, mtr);
01751 flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
01752 mtr);
01753 mlog_write_ulint(header + FSP_FRAG_N_USED,
01754 frag_n_used + FSP_EXTENT_SIZE - 1,
01755 MLOG_4BYTES, mtr);
01756 } else {
01757 ut_a(frag_n_used > 0);
01758 mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used - 1,
01759 MLOG_4BYTES, mtr);
01760 }
01761
01762 if (xdes_is_free(descr, mtr)) {
01763
01764 flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
01765 mtr);
01766 fsp_free_extent(space, zip_size, page, mtr);
01767 }
01768 }
01769
01770
01772 static
01773 void
01774 fsp_free_extent(
01775
01776 ulint space,
01777 ulint zip_size,
01779 ulint page,
01780 mtr_t* mtr)
01781 {
01782 fsp_header_t* header;
01783 xdes_t* descr;
01784
01785 ut_ad(mtr);
01786
01787 header = fsp_get_space_header(space, zip_size, mtr);
01788
01789 descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
01790
01791 if (xdes_get_state(descr, mtr) == XDES_FREE) {
01792
01793 ut_print_buf(stderr, (byte*)descr - 500, 1000);
01794 putc('\n', stderr);
01795
01796 ut_error;
01797 }
01798
01799 xdes_init(descr, mtr);
01800
01801 flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
01802 }
01803
01804
01807 UNIV_INLINE
01808 fseg_inode_t*
01809 fsp_seg_inode_page_get_nth_inode(
01810
01811 page_t* page,
01812 ulint i,
01813 ulint ,
01815 mtr_t* )
01817 {
01818 ut_ad(i < FSP_SEG_INODES_PER_PAGE(zip_size));
01819 ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
01820
01821 return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);
01822 }
01823
01824
01827 static
01828 ulint
01829 fsp_seg_inode_page_find_used(
01830
01831 page_t* page,
01832 ulint zip_size,
01833 mtr_t* mtr)
01834 {
01835 ulint i;
01836 fseg_inode_t* inode;
01837
01838 for (i = 0; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
01839
01840 inode = fsp_seg_inode_page_get_nth_inode(
01841 page, i, zip_size, mtr);
01842
01843 if (mach_read_from_8(inode + FSEG_ID)) {
01844
01845
01846 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
01847 == FSEG_MAGIC_N_VALUE);
01848 return(i);
01849 }
01850 }
01851
01852 return(ULINT_UNDEFINED);
01853 }
01854
01855
01858 static
01859 ulint
01860 fsp_seg_inode_page_find_free(
01861
01862 page_t* page,
01863 ulint i,
01864 ulint zip_size,
01865 mtr_t* mtr)
01866 {
01867 fseg_inode_t* inode;
01868
01869 for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
01870
01871 inode = fsp_seg_inode_page_get_nth_inode(
01872 page, i, zip_size, mtr);
01873
01874 if (!mach_read_from_8(inode + FSEG_ID)) {
01875
01876
01877 return(i);
01878 }
01879
01880 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
01881 == FSEG_MAGIC_N_VALUE);
01882 }
01883
01884 return(ULINT_UNDEFINED);
01885 }
01886
01887
01890 static
01891 ibool
01892 fsp_alloc_seg_inode_page(
01893
01894 fsp_header_t* space_header,
01895 mtr_t* mtr)
01896 {
01897 fseg_inode_t* inode;
01898 buf_block_t* block;
01899 page_t* page;
01900 ulint page_no;
01901 ulint space;
01902 ulint zip_size;
01903 ulint i;
01904
01905 ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
01906
01907 space = page_get_space_id(page_align(space_header));
01908 zip_size = dict_table_flags_to_zip_size(
01909 mach_read_from_4(FSP_SPACE_FLAGS + space_header));
01910
01911 page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
01912
01913 if (page_no == FIL_NULL) {
01914
01915 return(FALSE);
01916 }
01917
01918 block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
01919 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01920
01921 block->check_index_page_at_flush = FALSE;
01922
01923 page = buf_block_get_frame(block);
01924
01925 mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_INODE,
01926 MLOG_2BYTES, mtr);
01927
01928 for (i = 0; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
01929
01930 inode = fsp_seg_inode_page_get_nth_inode(page, i,
01931 zip_size, mtr);
01932
01933 mlog_write_ull(inode + FSEG_ID, 0, mtr);
01934 }
01935
01936 flst_add_last(space_header + FSP_SEG_INODES_FREE,
01937 page + FSEG_INODE_PAGE_NODE, mtr);
01938 return(TRUE);
01939 }
01940
01941
01944 static
01945 fseg_inode_t*
01946 fsp_alloc_seg_inode(
01947
01948 fsp_header_t* space_header,
01949 mtr_t* mtr)
01950 {
01951 ulint page_no;
01952 buf_block_t* block;
01953 page_t* page;
01954 fseg_inode_t* inode;
01955 ibool success;
01956 ulint zip_size;
01957 ulint n;
01958
01959 ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
01960
01961 if (flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) {
01962
01963
01964 success = fsp_alloc_seg_inode_page(space_header, mtr);
01965
01966 if (!success) {
01967
01968 return(NULL);
01969 }
01970 }
01971
01972 page_no = flst_get_first(space_header + FSP_SEG_INODES_FREE, mtr).page;
01973
01974 zip_size = dict_table_flags_to_zip_size(
01975 mach_read_from_4(FSP_SPACE_FLAGS + space_header));
01976 block = buf_page_get(page_get_space_id(page_align(space_header)),
01977 zip_size, page_no, RW_X_LATCH, mtr);
01978 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
01979
01980 page = buf_block_get_frame(block);
01981
01982 n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr);
01983
01984 ut_a(n != ULINT_UNDEFINED);
01985
01986 inode = fsp_seg_inode_page_get_nth_inode(page, n, zip_size, mtr);
01987
01988 if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
01989 zip_size, mtr)) {
01990
01991
01992
01993 flst_remove(space_header + FSP_SEG_INODES_FREE,
01994 page + FSEG_INODE_PAGE_NODE, mtr);
01995
01996 flst_add_last(space_header + FSP_SEG_INODES_FULL,
01997 page + FSEG_INODE_PAGE_NODE, mtr);
01998 }
01999
02000 ut_ad(!mach_read_from_8(inode + FSEG_ID)
02001 || mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02002 return(inode);
02003 }
02004
02005
02007 static
02008 void
02009 fsp_free_seg_inode(
02010
02011 ulint space,
02012 ulint zip_size,
02014 fseg_inode_t* inode,
02015 mtr_t* mtr)
02016 {
02017 page_t* page;
02018 fsp_header_t* space_header;
02019
02020 page = page_align(inode);
02021
02022 space_header = fsp_get_space_header(space, zip_size, mtr);
02023
02024 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02025
02026 if (ULINT_UNDEFINED
02027 == fsp_seg_inode_page_find_free(page, 0, zip_size, mtr)) {
02028
02029
02030
02031 flst_remove(space_header + FSP_SEG_INODES_FULL,
02032 page + FSEG_INODE_PAGE_NODE, mtr);
02033
02034 flst_add_last(space_header + FSP_SEG_INODES_FREE,
02035 page + FSEG_INODE_PAGE_NODE, mtr);
02036 }
02037
02038 mlog_write_ull(inode + FSEG_ID, 0, mtr);
02039 mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
02040
02041 if (ULINT_UNDEFINED
02042 == fsp_seg_inode_page_find_used(page, zip_size, mtr)) {
02043
02044
02045
02046 flst_remove(space_header + FSP_SEG_INODES_FREE,
02047 page + FSEG_INODE_PAGE_NODE, mtr);
02048
02049 fsp_free_page(space, zip_size, page_get_page_no(page), mtr);
02050 }
02051 }
02052
02053
02056 static
02057 fseg_inode_t*
02058 fseg_inode_try_get(
02059
02060 fseg_header_t* header,
02061 ulint space,
02062 ulint zip_size,
02064 mtr_t* mtr)
02065 {
02066 fil_addr_t inode_addr;
02067 fseg_inode_t* inode;
02068
02069 inode_addr.page = mach_read_from_4(header + FSEG_HDR_PAGE_NO);
02070 inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET);
02071 ut_ad(space == mach_read_from_4(header + FSEG_HDR_SPACE));
02072
02073 inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
02074
02075 if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
02076
02077 inode = NULL;
02078 } else {
02079 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
02080 == FSEG_MAGIC_N_VALUE);
02081 }
02082
02083 return(inode);
02084 }
02085
02086
02089 static
02090 fseg_inode_t*
02091 fseg_inode_get(
02092
02093 fseg_header_t* header,
02094 ulint space,
02095 ulint zip_size,
02097 mtr_t* mtr)
02098 {
02099 fseg_inode_t* inode
02100 = fseg_inode_try_get(header, space, zip_size, mtr);
02101 ut_a(inode);
02102 return(inode);
02103 }
02104
02105
02108 UNIV_INLINE
02109 ulint
02110 fseg_get_nth_frag_page_no(
02111
02112 fseg_inode_t* inode,
02113 ulint n,
02114 mtr_t* )
02115 {
02116 ut_ad(inode && mtr);
02117 ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
02118 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
02119 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02120 return(mach_read_from_4(inode + FSEG_FRAG_ARR
02121 + n * FSEG_FRAG_SLOT_SIZE));
02122 }
02123
02124
02126 UNIV_INLINE
02127 void
02128 fseg_set_nth_frag_page_no(
02129
02130 fseg_inode_t* inode,
02131 ulint n,
02132 ulint page_no,
02133 mtr_t* mtr)
02134 {
02135 ut_ad(inode && mtr);
02136 ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
02137 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
02138 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02139
02140 mlog_write_ulint(inode + FSEG_FRAG_ARR + n * FSEG_FRAG_SLOT_SIZE,
02141 page_no, MLOG_4BYTES, mtr);
02142 }
02143
02144
02147 static
02148 ulint
02149 fseg_find_free_frag_page_slot(
02150
02151 fseg_inode_t* inode,
02152 mtr_t* mtr)
02153 {
02154 ulint i;
02155 ulint page_no;
02156
02157 ut_ad(inode && mtr);
02158
02159 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02160 page_no = fseg_get_nth_frag_page_no(inode, i, mtr);
02161
02162 if (page_no == FIL_NULL) {
02163
02164 return(i);
02165 }
02166 }
02167
02168 return(ULINT_UNDEFINED);
02169 }
02170
02171
02174 static
02175 ulint
02176 fseg_find_last_used_frag_page_slot(
02177
02178 fseg_inode_t* inode,
02179 mtr_t* mtr)
02180 {
02181 ulint i;
02182 ulint page_no;
02183
02184 ut_ad(inode && mtr);
02185
02186 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02187 page_no = fseg_get_nth_frag_page_no(
02188 inode, FSEG_FRAG_ARR_N_SLOTS - i - 1, mtr);
02189
02190 if (page_no != FIL_NULL) {
02191
02192 return(FSEG_FRAG_ARR_N_SLOTS - i - 1);
02193 }
02194 }
02195
02196 return(ULINT_UNDEFINED);
02197 }
02198
02199
02202 static
02203 ulint
02204 fseg_get_n_frag_pages(
02205
02206 fseg_inode_t* inode,
02207 mtr_t* mtr)
02208 {
02209 ulint i;
02210 ulint count = 0;
02211
02212 ut_ad(inode && mtr);
02213
02214 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02215 if (FIL_NULL != fseg_get_nth_frag_page_no(inode, i, mtr)) {
02216 count++;
02217 }
02218 }
02219
02220 return(count);
02221 }
02222
02223
02227 UNIV_INTERN
02228 buf_block_t*
02229 fseg_create_general(
02230
02231 ulint space,
02232 ulint page,
02236 ulint byte_offset,
02238 ibool has_done_reservation,
02244 mtr_t* mtr)
02245 {
02246 ulint flags;
02247 ulint zip_size;
02248 fsp_header_t* space_header;
02249 fseg_inode_t* inode;
02250 ib_id_t seg_id;
02251 buf_block_t* block = 0;
02252 fseg_header_t* header = 0;
02253 rw_lock_t* latch;
02254 ibool success;
02255 ulint n_reserved;
02256 ulint i;
02257
02258 ut_ad(mtr);
02259 ut_ad(byte_offset + FSEG_HEADER_SIZE
02260 <= UNIV_PAGE_SIZE - FIL_PAGE_DATA_END);
02261
02262 latch = fil_space_get_latch(space, &flags);
02263 zip_size = dict_table_flags_to_zip_size(flags);
02264
02265 if (page != 0) {
02266 block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
02267 header = byte_offset + buf_block_get_frame(block);
02268 }
02269
02270 ut_ad(!mutex_own(&kernel_mutex)
02271 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02272
02273 mtr_x_lock(latch, mtr);
02274
02275 if (rw_lock_get_x_lock_count(latch) == 1) {
02276
02277
02278
02279 if (space == IBUF_SPACE_ID) {
02280 ibuf_free_excess_pages();
02281 }
02282 }
02283
02284 if (!has_done_reservation) {
02285 success = fsp_reserve_free_extents(&n_reserved, space, 2,
02286 FSP_NORMAL, mtr);
02287 if (!success) {
02288 return(NULL);
02289 }
02290 }
02291
02292 space_header = fsp_get_space_header(space, zip_size, mtr);
02293
02294 inode = fsp_alloc_seg_inode(space_header, mtr);
02295
02296 if (inode == NULL) {
02297
02298 goto funct_exit;
02299 }
02300
02301
02302
02303
02304 seg_id = mach_read_from_8(space_header + FSP_SEG_ID);
02305
02306 mlog_write_ull(space_header + FSP_SEG_ID, seg_id + 1, mtr);
02307
02308 mlog_write_ull(inode + FSEG_ID, seg_id, mtr);
02309 mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr);
02310
02311 flst_init(inode + FSEG_FREE, mtr);
02312 flst_init(inode + FSEG_NOT_FULL, mtr);
02313 flst_init(inode + FSEG_FULL, mtr);
02314
02315 mlog_write_ulint(inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE,
02316 MLOG_4BYTES, mtr);
02317 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
02318 fseg_set_nth_frag_page_no(inode, i, FIL_NULL, mtr);
02319 }
02320
02321 if (page == 0) {
02322 page = fseg_alloc_free_page_low(space, zip_size,
02323 inode, 0, FSP_UP, mtr);
02324
02325 if (page == FIL_NULL) {
02326
02327 fsp_free_seg_inode(space, zip_size, inode, mtr);
02328
02329 goto funct_exit;
02330 }
02331
02332 block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
02333 header = byte_offset + buf_block_get_frame(block);
02334 mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE,
02335 FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
02336 }
02337
02338 mlog_write_ulint(header + FSEG_HDR_OFFSET,
02339 page_offset(inode), MLOG_2BYTES, mtr);
02340
02341 mlog_write_ulint(header + FSEG_HDR_PAGE_NO,
02342 page_get_page_no(page_align(inode)),
02343 MLOG_4BYTES, mtr);
02344
02345 mlog_write_ulint(header + FSEG_HDR_SPACE, space, MLOG_4BYTES, mtr);
02346
02347 funct_exit:
02348 if (!has_done_reservation) {
02349
02350 fil_space_release_free_extents(space, n_reserved);
02351 }
02352
02353 return(block);
02354 }
02355
02356
02360 UNIV_INTERN
02361 buf_block_t*
02362 fseg_create(
02363
02364 ulint space,
02365 ulint page,
02369 ulint byte_offset,
02371 mtr_t* mtr)
02372 {
02373 return(fseg_create_general(space, page, byte_offset, FALSE, mtr));
02374 }
02375
02376
02380 static
02381 ulint
02382 fseg_n_reserved_pages_low(
02383
02384 fseg_inode_t* inode,
02385 ulint* used,
02387 mtr_t* mtr)
02388 {
02389 ulint ret;
02390
02391 ut_ad(inode && used && mtr);
02392 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
02393
02394 *used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr)
02395 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL, mtr)
02396 + fseg_get_n_frag_pages(inode, mtr);
02397
02398 ret = fseg_get_n_frag_pages(inode, mtr)
02399 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FREE, mtr)
02400 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_NOT_FULL, mtr)
02401 + FSP_EXTENT_SIZE * flst_get_len(inode + FSEG_FULL, mtr);
02402
02403 return(ret);
02404 }
02405
02406
02410 UNIV_INTERN
02411 ulint
02412 fseg_n_reserved_pages(
02413
02414 fseg_header_t* header,
02415 ulint* used,
02416 mtr_t* mtr)
02417 {
02418 ulint ret;
02419 fseg_inode_t* inode;
02420 ulint space;
02421 ulint flags;
02422 ulint zip_size;
02423 rw_lock_t* latch;
02424
02425 space = page_get_space_id(page_align(header));
02426 latch = fil_space_get_latch(space, &flags);
02427 zip_size = dict_table_flags_to_zip_size(flags);
02428
02429 ut_ad(!mutex_own(&kernel_mutex)
02430 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02431
02432 mtr_x_lock(latch, mtr);
02433
02434 inode = fseg_inode_get(header, space, zip_size, mtr);
02435
02436 ret = fseg_n_reserved_pages_low(inode, used, mtr);
02437
02438 return(ret);
02439 }
02440
02441
02446 static
02447 void
02448 fseg_fill_free_list(
02449
02450 fseg_inode_t* inode,
02451 ulint space,
02452 ulint zip_size,
02454 ulint hint,
02456 mtr_t* mtr)
02457 {
02458 xdes_t* descr;
02459 ulint i;
02460 ib_id_t seg_id;
02461 ulint reserved;
02462 ulint used;
02463
02464 ut_ad(inode && mtr);
02465 ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
02466
02467 reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
02468
02469 if (reserved < FSEG_FREE_LIST_LIMIT * FSP_EXTENT_SIZE) {
02470
02471
02472
02473 return;
02474 }
02475
02476 if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
02477
02478
02479 return;
02480 }
02481
02482 for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) {
02483 descr = xdes_get_descriptor(space, zip_size, hint, mtr);
02484
02485 if ((descr == NULL)
02486 || (XDES_FREE != xdes_get_state(descr, mtr))) {
02487
02488
02489
02490 return;
02491 }
02492
02493 descr = fsp_alloc_free_extent(space, zip_size, hint, mtr);
02494
02495 xdes_set_state(descr, XDES_FSEG, mtr);
02496
02497 seg_id = mach_read_from_8(inode + FSEG_ID);
02498 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
02499 == FSEG_MAGIC_N_VALUE);
02500 mlog_write_ull(descr + XDES_ID, seg_id, mtr);
02501
02502 flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
02503 hint += FSP_EXTENT_SIZE;
02504 }
02505 }
02506
02507
02513 static
02514 xdes_t*
02515 fseg_alloc_free_extent(
02516
02517 fseg_inode_t* inode,
02518 ulint space,
02519 ulint zip_size,
02521 mtr_t* mtr)
02522 {
02523 xdes_t* descr;
02524 ib_id_t seg_id;
02525 fil_addr_t first;
02526
02527 ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
02528 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
02529
02530 if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
02531
02532
02533 first = flst_get_first(inode + FSEG_FREE, mtr);
02534
02535 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
02536 } else {
02537
02538 descr = fsp_alloc_free_extent(space, zip_size, 0, mtr);
02539
02540 if (descr == NULL) {
02541
02542 return(NULL);
02543 }
02544
02545 seg_id = mach_read_from_8(inode + FSEG_ID);
02546
02547 xdes_set_state(descr, XDES_FSEG, mtr);
02548 mlog_write_ull(descr + XDES_ID, seg_id, mtr);
02549 flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
02550
02551
02552 fseg_fill_free_list(inode, space, zip_size,
02553 xdes_get_offset(descr) + FSP_EXTENT_SIZE,
02554 mtr);
02555 }
02556
02557 return(descr);
02558 }
02559
02560
02565 static
02566 ulint
02567 fseg_alloc_free_page_low(
02568
02569 ulint space,
02570 ulint zip_size,
02572 fseg_inode_t* seg_inode,
02573 ulint hint,
02574 byte direction,
02579 mtr_t* mtr)
02580 {
02581 fsp_header_t* space_header;
02582 ulint space_size;
02583 ib_id_t seg_id;
02584 ulint used;
02585 ulint reserved;
02586 xdes_t* descr;
02587 ulint ret_page;
02589 xdes_t* ret_descr;
02590 ibool frag_page_allocated = FALSE;
02591 ibool success;
02592 ulint n;
02593
02594 ut_ad(mtr);
02595 ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR));
02596 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
02597 == FSEG_MAGIC_N_VALUE);
02598 ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
02599 seg_id = mach_read_from_8(seg_inode + FSEG_ID);
02600
02601 ut_ad(seg_id);
02602
02603 reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
02604
02605 space_header = fsp_get_space_header(space, zip_size, mtr);
02606
02607 descr = xdes_get_descriptor_with_space_hdr(space_header, space,
02608 hint, mtr);
02609 if (descr == NULL) {
02610
02611
02612 hint = 0;
02613 descr = xdes_get_descriptor(space, zip_size, hint, mtr);
02614 }
02615
02616
02617
02618 if ((xdes_get_state(descr, mtr) == XDES_FSEG)
02619 && mach_read_from_8(descr + XDES_ID) == seg_id
02620 && (xdes_get_bit(descr, XDES_FREE_BIT,
02621 hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
02622
02623
02624
02625 ret_descr = descr;
02626 ret_page = hint;
02627
02628 } else if ((xdes_get_state(descr, mtr) == XDES_FREE)
02629 && ((reserved - used) < reserved / FSEG_FILLFACTOR)
02630 && (used >= FSEG_FRAG_LIMIT)) {
02631
02632
02633
02634
02635
02636 ret_descr = fsp_alloc_free_extent(space, zip_size, hint, mtr);
02637
02638 ut_a(ret_descr == descr);
02639
02640 xdes_set_state(ret_descr, XDES_FSEG, mtr);
02641 mlog_write_ull(ret_descr + XDES_ID, seg_id, mtr);
02642 flst_add_last(seg_inode + FSEG_FREE,
02643 ret_descr + XDES_FLST_NODE, mtr);
02644
02645
02646 fseg_fill_free_list(seg_inode, space, zip_size,
02647 hint + FSP_EXTENT_SIZE, mtr);
02648 ret_page = hint;
02649
02650 } else if ((direction != FSP_NO_DIR)
02651 && ((reserved - used) < reserved / FSEG_FILLFACTOR)
02652 && (used >= FSEG_FRAG_LIMIT)
02653 && (!!(ret_descr
02654 = fseg_alloc_free_extent(seg_inode,
02655 space, zip_size, mtr)))) {
02656
02657
02658
02659
02660
02661
02662
02663 ret_page = xdes_get_offset(ret_descr);
02664
02665 if (direction == FSP_DOWN) {
02666 ret_page += FSP_EXTENT_SIZE - 1;
02667 }
02668
02669 } else if ((xdes_get_state(descr, mtr) == XDES_FSEG)
02670 && mach_read_from_8(descr + XDES_ID) == seg_id
02671 && (!xdes_is_full(descr, mtr))) {
02672
02673
02674
02675
02676
02677
02678
02679 ret_descr = descr;
02680 ret_page = xdes_get_offset(ret_descr)
02681 + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
02682 hint % FSP_EXTENT_SIZE, mtr);
02683
02684 } else if (reserved - used > 0) {
02685
02686
02687 fil_addr_t first;
02688
02689 if (flst_get_len(seg_inode + FSEG_NOT_FULL, mtr) > 0) {
02690 first = flst_get_first(seg_inode + FSEG_NOT_FULL,
02691 mtr);
02692 } else if (flst_get_len(seg_inode + FSEG_FREE, mtr) > 0) {
02693 first = flst_get_first(seg_inode + FSEG_FREE, mtr);
02694 } else {
02695 ut_error;
02696 return(FIL_NULL);
02697 }
02698
02699 ret_descr = xdes_lst_get_descriptor(space, zip_size,
02700 first, mtr);
02701 ret_page = xdes_get_offset(ret_descr)
02702 + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
02703 0, mtr);
02704
02705 } else if (used < FSEG_FRAG_LIMIT) {
02706
02707
02708 ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
02709 ret_descr = NULL;
02710
02711 frag_page_allocated = TRUE;
02712
02713 if (ret_page != FIL_NULL) {
02714
02715
02716 n = fseg_find_free_frag_page_slot(seg_inode, mtr);
02717 ut_a(n != FIL_NULL);
02718
02719 fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
02720 mtr);
02721 }
02722
02723 } else {
02724
02725
02726 ret_descr = fseg_alloc_free_extent(seg_inode,
02727 space, zip_size, mtr);
02728
02729 if (ret_descr == NULL) {
02730 ret_page = FIL_NULL;
02731 } else {
02732 ret_page = xdes_get_offset(ret_descr);
02733 }
02734 }
02735
02736 if (ret_page == FIL_NULL) {
02737
02738
02739 return(FIL_NULL);
02740 }
02741
02742 if (space != 0) {
02743 space_size = fil_space_get_size(space);
02744
02745 if (space_size <= ret_page) {
02746
02747
02748
02749 if (ret_page >= FSP_EXTENT_SIZE) {
02750 fprintf(stderr,
02751 "InnoDB: Error (2): trying to extend"
02752 " a single-table tablespace %lu\n"
02753 "InnoDB: by single page(s) though"
02754 " the space size %lu. Page no %lu.\n",
02755 (ulong) space, (ulong) space_size,
02756 (ulong) ret_page);
02757 return(FIL_NULL);
02758 }
02759
02760 success = fsp_try_extend_data_file_with_pages(
02761 space, ret_page, space_header, mtr);
02762 if (!success) {
02763
02764 return(FIL_NULL);
02765 }
02766 }
02767 }
02768
02769 if (!frag_page_allocated) {
02770
02771
02772
02773 buf_block_t* block;
02774 ulint page_zip_size = dict_table_flags_to_zip_size(
02775 mach_read_from_4(FSP_SPACE_FLAGS + space_header));
02776
02777 block = buf_page_create(space, ret_page, page_zip_size, mtr);
02778 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
02779
02780 if (UNIV_UNLIKELY(block != buf_page_get(space, page_zip_size,
02781 ret_page, RW_X_LATCH,
02782 mtr))) {
02783 ut_error;
02784 }
02785
02786
02787 fsp_init_file_page(block, mtr);
02788
02789
02790
02791
02792
02793 ut_ad(xdes_get_descriptor(space, page_zip_size, ret_page, mtr)
02794 == ret_descr);
02795 ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT,
02796 ret_page % FSP_EXTENT_SIZE, mtr) == TRUE);
02797
02798 fseg_mark_page_used(seg_inode, space, page_zip_size, ret_page, mtr);
02799 }
02800
02801 buf_reset_check_index_page_at_flush(space, ret_page);
02802
02803 return(ret_page);
02804 }
02805
02806
02811 UNIV_INTERN
02812 ulint
02813 fseg_alloc_free_page_general(
02814
02815 fseg_header_t* seg_header,
02816 ulint hint,
02817 byte direction,
02822 ibool has_done_reservation,
02827 mtr_t* mtr)
02828 {
02829 fseg_inode_t* inode;
02830 ulint space;
02831 ulint flags;
02832 ulint zip_size;
02833 rw_lock_t* latch;
02834 ibool success;
02835 ulint page_no;
02836 ulint n_reserved;
02837
02838 space = page_get_space_id(page_align(seg_header));
02839
02840 latch = fil_space_get_latch(space, &flags);
02841
02842 zip_size = dict_table_flags_to_zip_size(flags);
02843
02844 ut_ad(!mutex_own(&kernel_mutex)
02845 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02846
02847 mtr_x_lock(latch, mtr);
02848
02849 if (rw_lock_get_x_lock_count(latch) == 1) {
02850
02851
02852
02853 if (space == IBUF_SPACE_ID) {
02854 ibuf_free_excess_pages();
02855 }
02856 }
02857
02858 inode = fseg_inode_get(seg_header, space, zip_size, mtr);
02859
02860 if (!has_done_reservation) {
02861 success = fsp_reserve_free_extents(&n_reserved, space, 2,
02862 FSP_NORMAL, mtr);
02863 if (!success) {
02864 return(FIL_NULL);
02865 }
02866 }
02867
02868 page_no = fseg_alloc_free_page_low(space, zip_size,
02869 inode, hint, direction, mtr);
02870 if (!has_done_reservation) {
02871 fil_space_release_free_extents(space, n_reserved);
02872 }
02873
02874 return(page_no);
02875 }
02876
02877
02882 UNIV_INTERN
02883 ulint
02884 fseg_alloc_free_page(
02885
02886 fseg_header_t* seg_header,
02887 ulint hint,
02888 byte direction,
02893 mtr_t* mtr)
02894 {
02895 return(fseg_alloc_free_page_general(seg_header, hint, direction,
02896 FALSE, mtr));
02897 }
02898
02899
02906 static
02907 ibool
02908 fsp_reserve_free_pages(
02909
02910 ulint space,
02911 fsp_header_t* space_header,
02913 ulint size,
02915 mtr_t* mtr)
02916 {
02917 xdes_t* descr;
02918 ulint n_used;
02919
02920 ut_a(space != 0);
02921 ut_a(size < FSP_EXTENT_SIZE / 2);
02922
02923 descr = xdes_get_descriptor_with_space_hdr(space_header, space, 0,
02924 mtr);
02925 n_used = xdes_get_n_used(descr, mtr);
02926
02927 ut_a(n_used <= size);
02928
02929 if (size >= n_used + 2) {
02930
02931 return(TRUE);
02932 }
02933
02934 return(fsp_try_extend_data_file_with_pages(space, n_used + 1,
02935 space_header, mtr));
02936 }
02937
02938
02964 UNIV_INTERN
02965 ibool
02966 fsp_reserve_free_extents(
02967
02968 ulint* n_reserved,
02971 ulint space,
02972 ulint n_ext,
02973 ulint alloc_type,
02974 mtr_t* mtr)
02975 {
02976 fsp_header_t* space_header;
02977 rw_lock_t* latch;
02978 ulint n_free_list_ext;
02979 ulint free_limit;
02980 ulint size;
02981 ulint flags;
02982 ulint zip_size;
02983 ulint n_free;
02984 ulint n_free_up;
02985 ulint reserve;
02986 ibool success;
02987 ulint n_pages_added;
02988
02989 ut_ad(mtr);
02990 *n_reserved = n_ext;
02991
02992 latch = fil_space_get_latch(space, &flags);
02993 zip_size = dict_table_flags_to_zip_size(flags);
02994
02995 ut_ad(!mutex_own(&kernel_mutex)
02996 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
02997
02998 mtr_x_lock(latch, mtr);
02999
03000 space_header = fsp_get_space_header(space, zip_size, mtr);
03001 try_again:
03002 size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, mtr);
03003
03004 if (size < FSP_EXTENT_SIZE / 2) {
03005
03006 *n_reserved = 0;
03007 return(fsp_reserve_free_pages(space, space_header, size, mtr));
03008 }
03009
03010 n_free_list_ext = flst_get_len(space_header + FSP_FREE, mtr);
03011
03012 free_limit = mtr_read_ulint(space_header + FSP_FREE_LIMIT,
03013 MLOG_4BYTES, mtr);
03014
03015
03016
03017
03018
03019 n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
03020
03021 if (n_free_up > 0) {
03022 n_free_up--;
03023 if (!zip_size) {
03024 n_free_up -= n_free_up
03025 / (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE);
03026 } else {
03027 n_free_up -= n_free_up
03028 / (zip_size / FSP_EXTENT_SIZE);
03029 }
03030 }
03031
03032 n_free = n_free_list_ext + n_free_up;
03033
03034 if (alloc_type == FSP_NORMAL) {
03035
03036
03037
03038
03039 reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
03040
03041 if (n_free <= reserve + n_ext) {
03042
03043 goto try_to_extend;
03044 }
03045 } else if (alloc_type == FSP_UNDO) {
03046
03047
03048 reserve = 1 + ((size / FSP_EXTENT_SIZE) * 1) / 200;
03049
03050 if (n_free <= reserve + n_ext) {
03051
03052 goto try_to_extend;
03053 }
03054 } else {
03055 ut_a(alloc_type == FSP_CLEANING);
03056 }
03057
03058 success = fil_space_reserve_free_extents(space, n_free, n_ext);
03059
03060 if (success) {
03061 return(TRUE);
03062 }
03063 try_to_extend:
03064 success = fsp_try_extend_data_file(&n_pages_added, space,
03065 space_header, mtr);
03066 if (success && n_pages_added > 0) {
03067
03068 goto try_again;
03069 }
03070
03071 return(FALSE);
03072 }
03073
03074
03080 UNIV_INTERN
03081 ullint
03082 fsp_get_available_space_in_free_extents(
03083
03084 ulint space)
03085 {
03086 fsp_header_t* space_header;
03087 ulint n_free_list_ext;
03088 ulint free_limit;
03089 ulint size;
03090 ulint flags;
03091 ulint zip_size;
03092 ulint n_free;
03093 ulint n_free_up;
03094 ulint reserve;
03095 rw_lock_t* latch;
03096 mtr_t mtr;
03097
03098 ut_ad(!mutex_own(&kernel_mutex));
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 mutex_enter(&dict_sys->mutex);
03116
03117
03118
03119
03120 if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) {
03121
03122 mutex_exit(&dict_sys->mutex);
03123
03124 return(ULLINT_UNDEFINED);
03125 }
03126
03127 mtr_start(&mtr);
03128
03129 latch = fil_space_get_latch(space, &flags);
03130
03131
03132
03133
03134
03135 zip_size = dict_table_flags_to_zip_size(flags);
03136
03137 mtr_x_lock(latch, &mtr);
03138
03139 mutex_exit(&dict_sys->mutex);
03140
03141
03142
03143
03144
03145
03146 if (fil_tablespace_is_being_deleted(space)) {
03147
03148 mtr_commit(&mtr);
03149
03150 return(ULLINT_UNDEFINED);
03151 }
03152
03153
03154
03155
03156
03157 space_header = fsp_get_space_header(space, zip_size, &mtr);
03158
03159 size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, &mtr);
03160
03161 n_free_list_ext = flst_get_len(space_header + FSP_FREE, &mtr);
03162
03163 free_limit = mtr_read_ulint(space_header + FSP_FREE_LIMIT,
03164 MLOG_4BYTES, &mtr);
03165 mtr_commit(&mtr);
03166
03167 if (size < FSP_EXTENT_SIZE) {
03168 ut_a(space != 0);
03169
03170
03171 return(0);
03172
03173 }
03174
03175
03176
03177
03178
03179 n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
03180
03181 if (n_free_up > 0) {
03182 n_free_up--;
03183 if (!zip_size) {
03184 n_free_up -= n_free_up
03185 / (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE);
03186 } else {
03187 n_free_up -= n_free_up
03188 / (zip_size / FSP_EXTENT_SIZE);
03189 }
03190 }
03191
03192 n_free = n_free_list_ext + n_free_up;
03193
03194
03195
03196
03197
03198 reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
03199
03200 if (reserve > n_free) {
03201 return(0);
03202 }
03203
03204 if (!zip_size) {
03205 return((ullint) (n_free - reserve)
03206 * FSP_EXTENT_SIZE
03207 * (UNIV_PAGE_SIZE / 1024));
03208 } else {
03209 return((ullint) (n_free - reserve)
03210 * FSP_EXTENT_SIZE
03211 * (zip_size / 1024));
03212 }
03213 }
03214
03215
03218 static
03219 void
03220 fseg_mark_page_used(
03221
03222 fseg_inode_t* seg_inode,
03223 ulint space,
03224 ulint zip_size,
03226 ulint page,
03227 mtr_t* mtr)
03228 {
03229 xdes_t* descr;
03230 ulint not_full_n_used;
03231
03232 ut_ad(seg_inode && mtr);
03233 ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
03234 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
03235 == FSEG_MAGIC_N_VALUE);
03236
03237 descr = xdes_get_descriptor(space, zip_size, page, mtr);
03238
03239 ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr)
03240 == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr));
03241
03242 if (xdes_is_free(descr, mtr)) {
03243
03244
03245 flst_remove(seg_inode + FSEG_FREE, descr + XDES_FLST_NODE,
03246 mtr);
03247 flst_add_last(seg_inode + FSEG_NOT_FULL,
03248 descr + XDES_FLST_NODE, mtr);
03249 }
03250
03251 ut_ad(xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)
03252 == TRUE);
03253
03254 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, FALSE, mtr);
03255
03256 not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03257 MLOG_4BYTES, mtr);
03258 not_full_n_used++;
03259 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED, not_full_n_used,
03260 MLOG_4BYTES, mtr);
03261 if (xdes_is_full(descr, mtr)) {
03262
03263
03264 flst_remove(seg_inode + FSEG_NOT_FULL,
03265 descr + XDES_FLST_NODE, mtr);
03266 flst_add_last(seg_inode + FSEG_FULL,
03267 descr + XDES_FLST_NODE, mtr);
03268
03269 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03270 not_full_n_used - FSP_EXTENT_SIZE,
03271 MLOG_4BYTES, mtr);
03272 }
03273 }
03274
03275
03277 static
03278 void
03279 fseg_free_page_low(
03280
03281 fseg_inode_t* seg_inode,
03282 ulint space,
03283 ulint zip_size,
03285 ulint page,
03286 mtr_t* mtr)
03287 {
03288 xdes_t* descr;
03289 ulint not_full_n_used;
03290 ulint state;
03291 ib_id_t descr_id;
03292 ib_id_t seg_id;
03293 ulint i;
03294
03295 ut_ad(seg_inode && mtr);
03296 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
03297 == FSEG_MAGIC_N_VALUE);
03298 ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
03299
03300
03301
03302
03303 btr_search_drop_page_hash_when_freed(space, zip_size, page);
03304
03305 descr = xdes_get_descriptor(space, zip_size, page, mtr);
03306
03307 ut_a(descr);
03308 if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
03309 fputs("InnoDB: Dump of the tablespace extent descriptor: ",
03310 stderr);
03311 ut_print_buf(stderr, descr, 40);
03312
03313 fprintf(stderr, "\n"
03314 "InnoDB: Serious error! InnoDB is trying to"
03315 " free page %lu\n"
03316 "InnoDB: though it is already marked as free"
03317 " in the tablespace!\n"
03318 "InnoDB: The tablespace free space info is corrupt.\n"
03319 "InnoDB: You may need to dump your"
03320 " InnoDB tables and recreate the whole\n"
03321 "InnoDB: database!\n", (ulong) page);
03322 crash:
03323 fputs("InnoDB: Please refer to\n"
03324 "InnoDB: " REFMAN "forcing-recovery.html\n"
03325 "InnoDB: about forcing recovery.\n", stderr);
03326 ut_error;
03327 }
03328
03329 state = xdes_get_state(descr, mtr);
03330
03331 if (state != XDES_FSEG) {
03332
03333
03334 for (i = 0;; i++) {
03335 if (fseg_get_nth_frag_page_no(seg_inode, i, mtr)
03336 == page) {
03337
03338 fseg_set_nth_frag_page_no(seg_inode, i,
03339 FIL_NULL, mtr);
03340 break;
03341 }
03342 }
03343
03344 fsp_free_page(space, zip_size, page, mtr);
03345
03346 return;
03347 }
03348
03349
03350
03351 descr_id = mach_read_from_8(descr + XDES_ID);
03352 seg_id = mach_read_from_8(seg_inode + FSEG_ID);
03353 #if 0
03354 fprintf(stderr,
03355 "InnoDB: InnoDB is freeing space %lu page %lu,\n"
03356 "InnoDB: which belongs to descr seg %llu\n"
03357 "InnoDB: segment %llu.\n",
03358 (ulong) space, (ulong) page,
03359 (ullint) descr_id,
03360 (ullint) seg_id);
03361 #endif
03362 if (UNIV_UNLIKELY(descr_id != seg_id)) {
03363 fputs("InnoDB: Dump of the tablespace extent descriptor: ",
03364 stderr);
03365 ut_print_buf(stderr, descr, 40);
03366 fputs("\nInnoDB: Dump of the segment inode: ", stderr);
03367 ut_print_buf(stderr, seg_inode, 40);
03368 putc('\n', stderr);
03369
03370 fprintf(stderr,
03371 "InnoDB: Serious error: InnoDB is trying to"
03372 " free space %lu page %lu,\n"
03373 "InnoDB: which does not belong to"
03374 " segment %llu but belongs\n"
03375 "InnoDB: to segment %llu.\n",
03376 (ulong) space, (ulong) page,
03377 (ullint) descr_id,
03378 (ullint) seg_id);
03379 goto crash;
03380 }
03381
03382 not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03383 MLOG_4BYTES, mtr);
03384 if (xdes_is_full(descr, mtr)) {
03385
03386 flst_remove(seg_inode + FSEG_FULL,
03387 descr + XDES_FLST_NODE, mtr);
03388 flst_add_last(seg_inode + FSEG_NOT_FULL,
03389 descr + XDES_FLST_NODE, mtr);
03390 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03391 not_full_n_used + FSP_EXTENT_SIZE - 1,
03392 MLOG_4BYTES, mtr);
03393 } else {
03394 ut_a(not_full_n_used > 0);
03395 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03396 not_full_n_used - 1, MLOG_4BYTES, mtr);
03397 }
03398
03399 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
03400 xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
03401
03402 if (xdes_is_free(descr, mtr)) {
03403
03404 flst_remove(seg_inode + FSEG_NOT_FULL,
03405 descr + XDES_FLST_NODE, mtr);
03406 fsp_free_extent(space, zip_size, page, mtr);
03407 }
03408 }
03409
03410
03412 UNIV_INTERN
03413 void
03414 fseg_free_page(
03415
03416 fseg_header_t* seg_header,
03417 ulint space,
03418 ulint page,
03419 mtr_t* mtr)
03420 {
03421 ulint flags;
03422 ulint zip_size;
03423 fseg_inode_t* seg_inode;
03424 rw_lock_t* latch;
03425
03426 latch = fil_space_get_latch(space, &flags);
03427 zip_size = dict_table_flags_to_zip_size(flags);
03428
03429 ut_ad(!mutex_own(&kernel_mutex)
03430 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
03431
03432 mtr_x_lock(latch, mtr);
03433
03434 seg_inode = fseg_inode_get(seg_header, space, zip_size, mtr);
03435
03436 fseg_free_page_low(seg_inode, space, zip_size, page, mtr);
03437
03438 #ifdef UNIV_DEBUG_FILE_ACCESSES
03439 buf_page_set_file_page_was_freed(space, page);
03440 #endif
03441 }
03442
03443
03445 static
03446 void
03447 fseg_free_extent(
03448
03449 fseg_inode_t* seg_inode,
03450 ulint space,
03451 ulint zip_size,
03453 ulint page,
03454 mtr_t* mtr)
03455 {
03456 ulint first_page_in_extent;
03457 xdes_t* descr;
03458 ulint not_full_n_used;
03459 ulint descr_n_used;
03460 ulint i;
03461
03462 ut_ad(seg_inode && mtr);
03463
03464 descr = xdes_get_descriptor(space, zip_size, page, mtr);
03465
03466 ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
03467 ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
03468 ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
03469 == FSEG_MAGIC_N_VALUE);
03470
03471 first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
03472
03473 for (i = 0; i < FSP_EXTENT_SIZE; i++) {
03474 if (FALSE == xdes_get_bit(descr, XDES_FREE_BIT, i, mtr)) {
03475
03476
03477
03478
03479 btr_search_drop_page_hash_when_freed(
03480 space, zip_size, first_page_in_extent + i);
03481 }
03482 }
03483
03484 if (xdes_is_full(descr, mtr)) {
03485 flst_remove(seg_inode + FSEG_FULL,
03486 descr + XDES_FLST_NODE, mtr);
03487 } else if (xdes_is_free(descr, mtr)) {
03488 flst_remove(seg_inode + FSEG_FREE,
03489 descr + XDES_FLST_NODE, mtr);
03490 } else {
03491 flst_remove(seg_inode + FSEG_NOT_FULL,
03492 descr + XDES_FLST_NODE, mtr);
03493
03494 not_full_n_used = mtr_read_ulint(
03495 seg_inode + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr);
03496
03497 descr_n_used = xdes_get_n_used(descr, mtr);
03498 ut_a(not_full_n_used >= descr_n_used);
03499 mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
03500 not_full_n_used - descr_n_used,
03501 MLOG_4BYTES, mtr);
03502 }
03503
03504 fsp_free_extent(space, zip_size, page, mtr);
03505
03506 #ifdef UNIV_DEBUG_FILE_ACCESSES
03507 for (i = 0; i < FSP_EXTENT_SIZE; i++) {
03508
03509 buf_page_set_file_page_was_freed(space,
03510 first_page_in_extent + i);
03511 }
03512 #endif
03513 }
03514
03515
03521 UNIV_INTERN
03522 ibool
03523 fseg_free_step(
03524
03525 fseg_header_t* header,
03529 mtr_t* mtr)
03530 {
03531 ulint n;
03532 ulint page;
03533 xdes_t* descr;
03534 fseg_inode_t* inode;
03535 ulint space;
03536 ulint flags;
03537 ulint zip_size;
03538 ulint header_page;
03539 rw_lock_t* latch;
03540
03541 space = page_get_space_id(page_align(header));
03542 header_page = page_get_page_no(page_align(header));
03543
03544 latch = fil_space_get_latch(space, &flags);
03545 zip_size = dict_table_flags_to_zip_size(flags);
03546
03547 ut_ad(!mutex_own(&kernel_mutex)
03548 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
03549
03550 mtr_x_lock(latch, mtr);
03551
03552 descr = xdes_get_descriptor(space, zip_size, header_page, mtr);
03553
03554
03555
03556
03557 ut_a(descr);
03558 ut_a(xdes_get_bit(descr, XDES_FREE_BIT,
03559 header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
03560 inode = fseg_inode_try_get(header, space, zip_size, mtr);
03561
03562 if (UNIV_UNLIKELY(inode == NULL)) {
03563 fprintf(stderr, "double free of inode from %u:%u\n",
03564 (unsigned) space, (unsigned) header_page);
03565 return(TRUE);
03566 }
03567
03568 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
03569
03570 if (descr != NULL) {
03571
03572 page = xdes_get_offset(descr);
03573
03574 fseg_free_extent(inode, space, zip_size, page, mtr);
03575
03576 return(FALSE);
03577 }
03578
03579
03580 n = fseg_find_last_used_frag_page_slot(inode, mtr);
03581
03582 if (n == ULINT_UNDEFINED) {
03583
03584 fsp_free_seg_inode(space, zip_size, inode, mtr);
03585
03586 return(TRUE);
03587 }
03588
03589 fseg_free_page_low(inode, space, zip_size,
03590 fseg_get_nth_frag_page_no(inode, n, mtr), mtr);
03591
03592 n = fseg_find_last_used_frag_page_slot(inode, mtr);
03593
03594 if (n == ULINT_UNDEFINED) {
03595
03596 fsp_free_seg_inode(space, zip_size, inode, mtr);
03597
03598 return(TRUE);
03599 }
03600
03601 return(FALSE);
03602 }
03603
03604
03608 UNIV_INTERN
03609 ibool
03610 fseg_free_step_not_header(
03611
03612 fseg_header_t* header,
03614 mtr_t* mtr)
03615 {
03616 ulint n;
03617 ulint page;
03618 xdes_t* descr;
03619 fseg_inode_t* inode;
03620 ulint space;
03621 ulint flags;
03622 ulint zip_size;
03623 ulint page_no;
03624 rw_lock_t* latch;
03625
03626 space = page_get_space_id(page_align(header));
03627
03628 latch = fil_space_get_latch(space, &flags);
03629 zip_size = dict_table_flags_to_zip_size(flags);
03630
03631 ut_ad(!mutex_own(&kernel_mutex)
03632 || mtr_memo_contains(mtr, latch, MTR_MEMO_X_LOCK));
03633
03634 mtr_x_lock(latch, mtr);
03635
03636 inode = fseg_inode_get(header, space, zip_size, mtr);
03637
03638 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
03639
03640 if (descr != NULL) {
03641
03642 page = xdes_get_offset(descr);
03643
03644 fseg_free_extent(inode, space, zip_size, page, mtr);
03645
03646 return(FALSE);
03647 }
03648
03649
03650
03651 n = fseg_find_last_used_frag_page_slot(inode, mtr);
03652
03653 if (n == ULINT_UNDEFINED) {
03654 ut_error;
03655 }
03656
03657 page_no = fseg_get_nth_frag_page_no(inode, n, mtr);
03658
03659 if (page_no == page_get_page_no(page_align(header))) {
03660
03661 return(TRUE);
03662 }
03663
03664 fseg_free_page_low(inode, space, zip_size, page_no, mtr);
03665
03666 return(FALSE);
03667 }
03668
03669
03674 static
03675 xdes_t*
03676 fseg_get_first_extent(
03677
03678 fseg_inode_t* inode,
03679 ulint space,
03680 ulint zip_size,
03682 mtr_t* mtr)
03683 {
03684 fil_addr_t first;
03685 xdes_t* descr;
03686
03687 ut_ad(inode && mtr);
03688
03689 ut_ad(space == page_get_space_id(page_align(inode)));
03690 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
03691
03692 first = fil_addr_null;
03693
03694 if (flst_get_len(inode + FSEG_FULL, mtr) > 0) {
03695
03696 first = flst_get_first(inode + FSEG_FULL, mtr);
03697
03698 } else if (flst_get_len(inode + FSEG_NOT_FULL, mtr) > 0) {
03699
03700 first = flst_get_first(inode + FSEG_NOT_FULL, mtr);
03701
03702 } else if (flst_get_len(inode + FSEG_FREE, mtr) > 0) {
03703
03704 first = flst_get_first(inode + FSEG_FREE, mtr);
03705 }
03706
03707 if (first.page == FIL_NULL) {
03708
03709 return(NULL);
03710 }
03711 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
03712
03713 return(descr);
03714 }
03715
03716
03719 static
03720 ibool
03721 fseg_validate_low(
03722
03723 fseg_inode_t* inode,
03724 mtr_t* mtr2)
03725 {
03726 ulint space;
03727 ib_id_t seg_id;
03728 mtr_t mtr;
03729 xdes_t* descr;
03730 fil_addr_t node_addr;
03731 ulint n_used = 0;
03732 ulint n_used2 = 0;
03733
03734 ut_ad(mtr_memo_contains_page(mtr2, inode, MTR_MEMO_PAGE_X_FIX));
03735 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
03736
03737 space = page_get_space_id(page_align(inode));
03738
03739 seg_id = mach_read_from_8(inode + FSEG_ID);
03740 n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
03741 MLOG_4BYTES, mtr2);
03742 flst_validate(inode + FSEG_FREE, mtr2);
03743 flst_validate(inode + FSEG_NOT_FULL, mtr2);
03744 flst_validate(inode + FSEG_FULL, mtr2);
03745
03746
03747 node_addr = flst_get_first(inode + FSEG_FREE, mtr2);
03748
03749 while (!fil_addr_is_null(node_addr)) {
03750 ulint flags;
03751 ulint zip_size;
03752
03753 mtr_start(&mtr);
03754 mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
03755 zip_size = dict_table_flags_to_zip_size(flags);
03756
03757 descr = xdes_lst_get_descriptor(space, zip_size,
03758 node_addr, &mtr);
03759
03760 ut_a(xdes_get_n_used(descr, &mtr) == 0);
03761 ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
03762 ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
03763
03764 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
03765 mtr_commit(&mtr);
03766 }
03767
03768
03769
03770 node_addr = flst_get_first(inode + FSEG_NOT_FULL, mtr2);
03771
03772 while (!fil_addr_is_null(node_addr)) {
03773 ulint flags;
03774 ulint zip_size;
03775
03776 mtr_start(&mtr);
03777 mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
03778 zip_size = dict_table_flags_to_zip_size(flags);
03779
03780 descr = xdes_lst_get_descriptor(space, zip_size,
03781 node_addr, &mtr);
03782
03783 ut_a(xdes_get_n_used(descr, &mtr) > 0);
03784 ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
03785 ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
03786 ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
03787
03788 n_used2 += xdes_get_n_used(descr, &mtr);
03789
03790 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
03791 mtr_commit(&mtr);
03792 }
03793
03794
03795
03796 node_addr = flst_get_first(inode + FSEG_FULL, mtr2);
03797
03798 while (!fil_addr_is_null(node_addr)) {
03799 ulint flags;
03800 ulint zip_size;
03801
03802 mtr_start(&mtr);
03803 mtr_x_lock(fil_space_get_latch(space, &flags), &mtr);
03804 zip_size = dict_table_flags_to_zip_size(flags);
03805
03806 descr = xdes_lst_get_descriptor(space, zip_size,
03807 node_addr, &mtr);
03808
03809 ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
03810 ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
03811 ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
03812
03813 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
03814 mtr_commit(&mtr);
03815 }
03816
03817 ut_a(n_used == n_used2);
03818
03819 return(TRUE);
03820 }
03821
03822 #ifdef UNIV_DEBUG
03823
03826 UNIV_INTERN
03827 ibool
03828 fseg_validate(
03829
03830 fseg_header_t* header,
03831 mtr_t* mtr)
03832 {
03833 fseg_inode_t* inode;
03834 ibool ret;
03835 ulint space;
03836 ulint flags;
03837 ulint zip_size;
03838
03839 space = page_get_space_id(page_align(header));
03840
03841 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
03842 zip_size = dict_table_flags_to_zip_size(flags);
03843
03844 inode = fseg_inode_get(header, space, zip_size, mtr);
03845
03846 ret = fseg_validate_low(inode, mtr);
03847
03848 return(ret);
03849 }
03850 #endif
03851
03852
03854 static
03855 void
03856 fseg_print_low(
03857
03858 fseg_inode_t* inode,
03859 mtr_t* mtr)
03860 {
03861 ulint space;
03862 ulint n_used;
03863 ulint n_frag;
03864 ulint n_free;
03865 ulint n_not_full;
03866 ulint n_full;
03867 ulint reserved;
03868 ulint used;
03869 ulint page_no;
03870 ib_id_t seg_id;
03871
03872 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
03873 space = page_get_space_id(page_align(inode));
03874 page_no = page_get_page_no(page_align(inode));
03875
03876 reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
03877
03878 seg_id = mach_read_from_8(inode + FSEG_ID);
03879
03880 n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
03881 MLOG_4BYTES, mtr);
03882 n_frag = fseg_get_n_frag_pages(inode, mtr);
03883 n_free = flst_get_len(inode + FSEG_FREE, mtr);
03884 n_not_full = flst_get_len(inode + FSEG_NOT_FULL, mtr);
03885 n_full = flst_get_len(inode + FSEG_FULL, mtr);
03886
03887 fprintf(stderr,
03888 "SEGMENT id %llu space %lu; page %lu;"
03889 " res %lu used %lu; full ext %lu\n"
03890 "fragm pages %lu; free extents %lu;"
03891 " not full extents %lu: pages %lu\n",
03892 (ullint) seg_id,
03893 (ulong) space, (ulong) page_no,
03894 (ulong) reserved, (ulong) used, (ulong) n_full,
03895 (ulong) n_frag, (ulong) n_free, (ulong) n_not_full,
03896 (ulong) n_used);
03897 ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
03898 }
03899
03900 #ifdef UNIV_BTR_PRINT
03901
03903 UNIV_INTERN
03904 void
03905 fseg_print(
03906
03907 fseg_header_t* header,
03908 mtr_t* mtr)
03909 {
03910 fseg_inode_t* inode;
03911 ulint space;
03912 ulint flags;
03913 ulint zip_size;
03914
03915 space = page_get_space_id(page_align(header));
03916
03917 mtr_x_lock(fil_space_get_latch(space, &flags), mtr);
03918 zip_size = dict_table_flags_to_zip_size(flags);
03919
03920 inode = fseg_inode_get(header, space, zip_size, mtr);
03921
03922 fseg_print_low(inode, mtr);
03923 }
03924 #endif
03925
03926
03929 UNIV_INTERN
03930 ibool
03931 fsp_validate(
03932
03933 ulint space)
03934 {
03935 fsp_header_t* header;
03936 fseg_inode_t* seg_inode;
03937 page_t* seg_inode_page;
03938 rw_lock_t* latch;
03939 ulint size;
03940 ulint flags;
03941 ulint zip_size;
03942 ulint free_limit;
03943 ulint frag_n_used;
03944 mtr_t mtr;
03945 mtr_t mtr2;
03946 xdes_t* descr;
03947 fil_addr_t node_addr;
03948 fil_addr_t next_node_addr;
03949 ulint descr_count = 0;
03950 ulint n_used = 0;
03951 ulint n_used2 = 0;
03952 ulint n_full_frag_pages;
03953 ulint n;
03954 ulint seg_inode_len_free;
03955 ulint seg_inode_len_full;
03956
03957 latch = fil_space_get_latch(space, &flags);
03958 zip_size = dict_table_flags_to_zip_size(flags);
03959 ut_a(ut_is_2pow(zip_size));
03960 ut_a(zip_size <= UNIV_PAGE_SIZE);
03961 ut_a(!zip_size || zip_size >= PAGE_ZIP_MIN_SIZE);
03962
03963
03964
03965 mtr_start(&mtr2);
03966 mtr_x_lock(latch, &mtr2);
03967
03968 mtr_start(&mtr);
03969 mtr_x_lock(latch, &mtr);
03970
03971 header = fsp_get_space_header(space, zip_size, &mtr);
03972
03973 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
03974 free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT,
03975 MLOG_4BYTES, &mtr);
03976 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED,
03977 MLOG_4BYTES, &mtr);
03978
03979 n_full_frag_pages = FSP_EXTENT_SIZE
03980 * flst_get_len(header + FSP_FULL_FRAG, &mtr);
03981
03982 if (UNIV_UNLIKELY(free_limit > size)) {
03983
03984 ut_a(space != 0);
03985 ut_a(size < FSP_EXTENT_SIZE);
03986 }
03987
03988 flst_validate(header + FSP_FREE, &mtr);
03989 flst_validate(header + FSP_FREE_FRAG, &mtr);
03990 flst_validate(header + FSP_FULL_FRAG, &mtr);
03991
03992 mtr_commit(&mtr);
03993
03994
03995 mtr_start(&mtr);
03996 mtr_x_lock(latch, &mtr);
03997
03998 header = fsp_get_space_header(space, zip_size, &mtr);
03999 node_addr = flst_get_first(header + FSP_FREE, &mtr);
04000
04001 mtr_commit(&mtr);
04002
04003 while (!fil_addr_is_null(node_addr)) {
04004 mtr_start(&mtr);
04005 mtr_x_lock(latch, &mtr);
04006
04007 descr_count++;
04008 descr = xdes_lst_get_descriptor(space, zip_size,
04009 node_addr, &mtr);
04010
04011 ut_a(xdes_get_n_used(descr, &mtr) == 0);
04012 ut_a(xdes_get_state(descr, &mtr) == XDES_FREE);
04013
04014 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
04015 mtr_commit(&mtr);
04016 }
04017
04018
04019 mtr_start(&mtr);
04020 mtr_x_lock(latch, &mtr);
04021
04022 header = fsp_get_space_header(space, zip_size, &mtr);
04023 node_addr = flst_get_first(header + FSP_FREE_FRAG, &mtr);
04024
04025 mtr_commit(&mtr);
04026
04027 while (!fil_addr_is_null(node_addr)) {
04028 mtr_start(&mtr);
04029 mtr_x_lock(latch, &mtr);
04030
04031 descr_count++;
04032 descr = xdes_lst_get_descriptor(space, zip_size,
04033 node_addr, &mtr);
04034
04035 ut_a(xdes_get_n_used(descr, &mtr) > 0);
04036 ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
04037 ut_a(xdes_get_state(descr, &mtr) == XDES_FREE_FRAG);
04038
04039 n_used += xdes_get_n_used(descr, &mtr);
04040 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
04041
04042 mtr_commit(&mtr);
04043 }
04044
04045
04046 mtr_start(&mtr);
04047 mtr_x_lock(latch, &mtr);
04048
04049 header = fsp_get_space_header(space, zip_size, &mtr);
04050 node_addr = flst_get_first(header + FSP_FULL_FRAG, &mtr);
04051
04052 mtr_commit(&mtr);
04053
04054 while (!fil_addr_is_null(node_addr)) {
04055 mtr_start(&mtr);
04056 mtr_x_lock(latch, &mtr);
04057
04058 descr_count++;
04059 descr = xdes_lst_get_descriptor(space, zip_size,
04060 node_addr, &mtr);
04061
04062 ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
04063 ut_a(xdes_get_state(descr, &mtr) == XDES_FULL_FRAG);
04064
04065 node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
04066 mtr_commit(&mtr);
04067 }
04068
04069
04070 mtr_start(&mtr);
04071 mtr_x_lock(latch, &mtr);
04072
04073 header = fsp_get_space_header(space, zip_size, &mtr);
04074
04075 node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr);
04076
04077 seg_inode_len_full = flst_get_len(header + FSP_SEG_INODES_FULL, &mtr);
04078
04079 mtr_commit(&mtr);
04080
04081 while (!fil_addr_is_null(node_addr)) {
04082
04083 n = 0;
04084 do {
04085 mtr_start(&mtr);
04086 mtr_x_lock(latch, &mtr);
04087
04088 seg_inode_page = fut_get_ptr(
04089 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04090 - FSEG_INODE_PAGE_NODE;
04091
04092 seg_inode = fsp_seg_inode_page_get_nth_inode(
04093 seg_inode_page, n, zip_size, &mtr);
04094 ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
04095 fseg_validate_low(seg_inode, &mtr);
04096
04097 descr_count += flst_get_len(seg_inode + FSEG_FREE,
04098 &mtr);
04099 descr_count += flst_get_len(seg_inode + FSEG_FULL,
04100 &mtr);
04101 descr_count += flst_get_len(seg_inode + FSEG_NOT_FULL,
04102 &mtr);
04103
04104 n_used2 += fseg_get_n_frag_pages(seg_inode, &mtr);
04105
04106 next_node_addr = flst_get_next_addr(
04107 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04108 mtr_commit(&mtr);
04109 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04110
04111 node_addr = next_node_addr;
04112 }
04113
04114 mtr_start(&mtr);
04115 mtr_x_lock(latch, &mtr);
04116
04117 header = fsp_get_space_header(space, zip_size, &mtr);
04118
04119 node_addr = flst_get_first(header + FSP_SEG_INODES_FREE, &mtr);
04120
04121 seg_inode_len_free = flst_get_len(header + FSP_SEG_INODES_FREE, &mtr);
04122
04123 mtr_commit(&mtr);
04124
04125 while (!fil_addr_is_null(node_addr)) {
04126
04127 n = 0;
04128
04129 do {
04130 mtr_start(&mtr);
04131 mtr_x_lock(latch, &mtr);
04132
04133 seg_inode_page = fut_get_ptr(
04134 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04135 - FSEG_INODE_PAGE_NODE;
04136
04137 seg_inode = fsp_seg_inode_page_get_nth_inode(
04138 seg_inode_page, n, zip_size, &mtr);
04139 if (mach_read_from_8(seg_inode + FSEG_ID)) {
04140 fseg_validate_low(seg_inode, &mtr);
04141
04142 descr_count += flst_get_len(
04143 seg_inode + FSEG_FREE, &mtr);
04144 descr_count += flst_get_len(
04145 seg_inode + FSEG_FULL, &mtr);
04146 descr_count += flst_get_len(
04147 seg_inode + FSEG_NOT_FULL, &mtr);
04148 n_used2 += fseg_get_n_frag_pages(
04149 seg_inode, &mtr);
04150 }
04151
04152 next_node_addr = flst_get_next_addr(
04153 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04154 mtr_commit(&mtr);
04155 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04156
04157 node_addr = next_node_addr;
04158 }
04159
04160 ut_a(descr_count * FSP_EXTENT_SIZE == free_limit);
04161 if (!zip_size) {
04162 ut_a(n_used + n_full_frag_pages
04163 == n_used2 + 2 * ((free_limit + (UNIV_PAGE_SIZE - 1))
04164 / UNIV_PAGE_SIZE)
04165 + seg_inode_len_full + seg_inode_len_free);
04166 } else {
04167 ut_a(n_used + n_full_frag_pages
04168 == n_used2 + 2 * ((free_limit + (zip_size - 1))
04169 / zip_size)
04170 + seg_inode_len_full + seg_inode_len_free);
04171 }
04172 ut_a(frag_n_used == n_used);
04173
04174 mtr_commit(&mtr2);
04175
04176 return(TRUE);
04177 }
04178
04179
04181 UNIV_INTERN
04182 void
04183 fsp_print(
04184
04185 ulint space)
04186 {
04187 fsp_header_t* header;
04188 fseg_inode_t* seg_inode;
04189 page_t* seg_inode_page;
04190 rw_lock_t* latch;
04191 ulint flags;
04192 ulint zip_size;
04193 ulint size;
04194 ulint free_limit;
04195 ulint frag_n_used;
04196 fil_addr_t node_addr;
04197 fil_addr_t next_node_addr;
04198 ulint n_free;
04199 ulint n_free_frag;
04200 ulint n_full_frag;
04201 ib_id_t seg_id;
04202 ulint n;
04203 ulint n_segs = 0;
04204 mtr_t mtr;
04205 mtr_t mtr2;
04206
04207 latch = fil_space_get_latch(space, &flags);
04208 zip_size = dict_table_flags_to_zip_size(flags);
04209
04210
04211
04212
04213 mtr_start(&mtr2);
04214
04215 mtr_x_lock(latch, &mtr2);
04216
04217 mtr_start(&mtr);
04218
04219 mtr_x_lock(latch, &mtr);
04220
04221 header = fsp_get_space_header(space, zip_size, &mtr);
04222
04223 size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
04224
04225 free_limit = mtr_read_ulint(header + FSP_FREE_LIMIT, MLOG_4BYTES,
04226 &mtr);
04227 frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
04228 &mtr);
04229 n_free = flst_get_len(header + FSP_FREE, &mtr);
04230 n_free_frag = flst_get_len(header + FSP_FREE_FRAG, &mtr);
04231 n_full_frag = flst_get_len(header + FSP_FULL_FRAG, &mtr);
04232
04233 seg_id = mach_read_from_8(header + FSP_SEG_ID);
04234
04235 fprintf(stderr,
04236 "FILE SPACE INFO: id %lu\n"
04237 "size %lu, free limit %lu, free extents %lu\n"
04238 "not full frag extents %lu: used pages %lu,"
04239 " full frag extents %lu\n"
04240 "first seg id not used %llu\n",
04241 (ulong) space,
04242 (ulong) size, (ulong) free_limit, (ulong) n_free,
04243 (ulong) n_free_frag, (ulong) frag_n_used, (ulong) n_full_frag,
04244 (ullint) seg_id);
04245
04246 mtr_commit(&mtr);
04247
04248
04249
04250 mtr_start(&mtr);
04251 mtr_x_lock(latch, &mtr);
04252
04253 header = fsp_get_space_header(space, zip_size, &mtr);
04254
04255 node_addr = flst_get_first(header + FSP_SEG_INODES_FULL, &mtr);
04256
04257 mtr_commit(&mtr);
04258
04259 while (!fil_addr_is_null(node_addr)) {
04260
04261 n = 0;
04262
04263 do {
04264
04265 mtr_start(&mtr);
04266 mtr_x_lock(latch, &mtr);
04267
04268 seg_inode_page = fut_get_ptr(
04269 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04270 - FSEG_INODE_PAGE_NODE;
04271
04272 seg_inode = fsp_seg_inode_page_get_nth_inode(
04273 seg_inode_page, n, zip_size, &mtr);
04274 ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
04275 fseg_print_low(seg_inode, &mtr);
04276
04277 n_segs++;
04278
04279 next_node_addr = flst_get_next_addr(
04280 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04281 mtr_commit(&mtr);
04282 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04283
04284 node_addr = next_node_addr;
04285 }
04286
04287 mtr_start(&mtr);
04288 mtr_x_lock(latch, &mtr);
04289
04290 header = fsp_get_space_header(space, zip_size, &mtr);
04291
04292 node_addr = flst_get_first(header + FSP_SEG_INODES_FREE, &mtr);
04293
04294 mtr_commit(&mtr);
04295
04296 while (!fil_addr_is_null(node_addr)) {
04297
04298 n = 0;
04299
04300 do {
04301
04302 mtr_start(&mtr);
04303 mtr_x_lock(latch, &mtr);
04304
04305 seg_inode_page = fut_get_ptr(
04306 space, zip_size, node_addr, RW_X_LATCH, &mtr)
04307 - FSEG_INODE_PAGE_NODE;
04308
04309 seg_inode = fsp_seg_inode_page_get_nth_inode(
04310 seg_inode_page, n, zip_size, &mtr);
04311 if (mach_read_from_8(seg_inode + FSEG_ID)) {
04312
04313 fseg_print_low(seg_inode, &mtr);
04314 n_segs++;
04315 }
04316
04317 next_node_addr = flst_get_next_addr(
04318 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
04319 mtr_commit(&mtr);
04320 } while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
04321
04322 node_addr = next_node_addr;
04323 }
04324
04325 mtr_commit(&mtr2);
04326
04327 fprintf(stderr, "NUMBER of file segments: %lu\n", (ulong) n_segs);
04328 }
04329 #endif