54 #ifndef UNIV_HOTBACKUP
56 static ibool fsp_tbs_full_error_printed = FALSE;
75 fseg_inode_t* seg_inode,
87 fseg_n_reserved_pages_low(
96 static __attribute__((nonnull))
100 fseg_inode_t* seg_inode,
111 fseg_get_first_extent(
133 fsp_header_t* header,
135 UNIV_COLD __attribute__((nonnull));
146 fseg_alloc_free_page_low(
151 fseg_inode_t* seg_inode,
164 __attribute__((warn_unused_result, nonnull));
179 #ifndef UNIV_HOTBACKUP
193 fsp_header_t* header;
196 ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
197 ut_ad(!zip_size || zip_size >= UNIV_ZIP_SIZE_MIN);
198 ut_ad(
id || !zip_size);
202 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
223 ut_ad(mtr->state == MTR_ACTIVE);
224 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
247 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
248 ut_ad((bit == XDES_FREE_BIT) || (bit == XDES_CLEAN_BIT));
249 ut_ad(offset < FSP_EXTENT_SIZE);
251 index = bit + XDES_BITS_PER_PAGE *
offset;
253 byte_index = index / 8;
254 bit_index = index % 8;
284 ut_ad(hint < FSP_EXTENT_SIZE);
285 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
286 for (i = hint; i < FSP_EXTENT_SIZE; i++) {
293 for (i = 0; i < hint; i++) {
300 return(ULINT_UNDEFINED);
322 ut_ad(hint < FSP_EXTENT_SIZE);
323 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
324 for (i = hint + 1; i > 0; i--) {
331 for (i = FSP_EXTENT_SIZE - 1; i > hint; i--) {
338 return(ULINT_UNDEFINED);
354 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
355 for (ulint
i = 0;
i < FSP_EXTENT_SIZE; ++
i) {
411 ut_ad(state >= XDES_FREE);
412 ut_ad(state <= XDES_FSEG);
413 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
431 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
434 ut_ad(state - 1 < XDES_FSEG);
450 ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
453 for (i = XDES_BITMAP; i <
XDES_SIZE; i += 4) {
466 UNIV_INLINE __attribute__((nonnull, warn_unused_result))
468 xdes_get_descriptor_with_space_hdr(
470 fsp_header_t* sp_header,
487 ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
495 if ((offset >= size) || (offset >= limit)) {
501 if (descr_page_no == 0) {
510 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
512 descr_page = buf_block_get_frame(block);
528 static __attribute__((nonnull, warn_unused_result))
540 fsp_header_t* sp_header;
542 block =
buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
543 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
546 return(xdes_get_descriptor_with_space_hdr(sp_header, space, offset,
557 xdes_lst_get_descriptor(
571 descr =
fut_get_ptr(space, zip_size, lst_node, RW_X_LATCH, mtr)
598 fsp_init_file_page_low(
602 page_t* page = buf_block_get_frame(block);
605 #ifndef UNIV_HOTBACKUP
610 memset(page, 0, UNIV_PAGE_SIZE);
624 memset(page, 0, UNIV_PAGE_SIZE);
630 #ifndef UNIV_HOTBACKUP
640 fsp_init_file_page_low(block);
655 byte* end_ptr __attribute__((unused)),
658 ut_ad(ptr && end_ptr);
661 fsp_init_file_page_low(block);
675 ut_a(0 == (UNIV_PAGE_SIZE % FSP_EXTENT_SIZE));
676 ut_a(UNIV_PAGE_SIZE);
678 #if UNIV_PAGE_SIZE_MAX % FSP_EXTENT_SIZE_MAX
679 # error "UNIV_PAGE_SIZE_MAX % FSP_EXTENT_SIZE_MAX != 0"
681 #if UNIV_ZIP_SIZE_MIN % FSP_EXTENT_SIZE_MIN
682 # error "UNIV_ZIP_SIZE_MIN % FSP_EXTENT_SIZE_MIN != 0"
708 #ifndef UNIV_HOTBACKUP
720 fsp_header_t* header;
733 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
737 fsp_init_file_page(block, mtr);
738 page = buf_block_get_frame(block);
757 flst_init(header + FSP_SEG_INODES_FULL, mtr);
758 flst_init(header + FSP_SEG_INODES_FREE, mtr);
762 fsp_fill_free_list(FALSE, space, header, mtr);
764 0, 0, DICT_IBUF_ID_MIN + space,
767 fsp_fill_free_list(TRUE, space, header, mtr);
788 DBUG_EXECUTE_IF(
"fsp_header_get_space_id_failure",
789 id = ULINT_UNDEFINED;);
793 "Space id in fsp header %lu,but in the page header "
796 return(ULINT_UNDEFINED);
830 #ifndef UNIV_HOTBACKUP
841 fsp_header_t* header;
870 fsp_header_t* header;
891 static UNIV_COLD __attribute__((nonnull, warn_unused_result))
893 fsp_try_extend_data_file_with_pages(
897 fsp_header_t* header,
908 ut_a(page_no >= size);
923 static UNIV_COLD __attribute__((nonnull))
925 fsp_try_extend_data_file(
927 ulint* actual_increase,
933 fsp_header_t* header,
944 *actual_increase = 0;
946 if (space == 0 && !srv_auto_extend_last_data_file) {
952 if (fsp_tbs_full_error_printed == FALSE) {
954 "InnoDB: Error: Data file(s) ran"
956 "Please add another data file or"
957 " use \'autoextend\' for the last"
959 fsp_tbs_full_error_printed = TRUE;
971 if (!srv_last_file_size_max) {
972 size_increase = SRV_AUTO_EXTEND_INCREMENT;
974 if (srv_last_file_size_max
975 < srv_data_file_sizes[srv_n_data_files - 1]) {
978 "InnoDB: Error: Last data file size"
979 " is %lu, max size allowed %lu\n",
980 (ulong) srv_data_file_sizes[
981 srv_n_data_files - 1],
982 (ulong) srv_last_file_size_max);
985 size_increase = srv_last_file_size_max
986 - srv_data_file_sizes[srv_n_data_files - 1];
987 if (size_increase > SRV_AUTO_EXTEND_INCREMENT) {
988 size_increase = SRV_AUTO_EXTEND_INCREMENT;
999 extent_size = FSP_EXTENT_SIZE;
1001 extent_size = FSP_EXTENT_SIZE
1005 if (size < extent_size) {
1007 success = fsp_try_extend_data_file_with_pages(
1008 space, extent_size - 1, header, mtr);
1013 *actual_increase = new_size - old_size;
1021 if (size < 32 * extent_size) {
1022 size_increase = extent_size;
1027 size_increase = FSP_FREE_ADD * extent_size;
1031 if (size_increase == 0) {
1037 size + size_increase);
1048 (1024 * 1024) / UNIV_PAGE_SIZE);
1051 (1024 * 1024) / zip_size);
1055 *actual_increase = new_size - old_size;
1074 fsp_header_t* header,
1083 ulint actual_increase;
1087 ut_ad(header && mtr);
1097 ut_a(zip_size <= UNIV_ZIP_SIZE_MAX);
1098 ut_a(!zip_size || zip_size >= UNIV_ZIP_SIZE_MIN);
1100 if (space == 0 && srv_auto_extend_last_data_file
1101 && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
1104 fsp_try_extend_data_file(&actual_increase, space, header, mtr);
1108 if (space != 0 && !init_space
1109 && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
1112 fsp_try_extend_data_file(&actual_increase, space, header, mtr);
1118 while ((init_space && i < 1)
1119 || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
1131 if (UNIV_UNLIKELY(init_xdes)) {
1141 space, i, zip_size, mtr);
1144 buf_block_dbg_add_level(block,
1147 fsp_init_file_page(block, mtr);
1162 i + FSP_IBUF_BITMAP_OFFSET,
1163 zip_size, &ibuf_mtr);
1165 i + FSP_IBUF_BITMAP_OFFSET,
1166 RW_X_LATCH, &ibuf_mtr);
1167 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
1169 fsp_init_file_page(block, &ibuf_mtr);
1176 descr = xdes_get_descriptor_with_space_hdr(header, space, i,
1180 if (UNIV_UNLIKELY(init_xdes)) {
1188 FSP_IBUF_BITMAP_OFFSET, FALSE, mtr);
1192 descr + XDES_FLST_NODE, mtr);
1199 descr + XDES_FLST_NODE, mtr);
1203 i += FSP_EXTENT_SIZE;
1212 fsp_alloc_free_extent(
1222 fsp_header_t* header;
1230 descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
1239 fsp_fill_free_list(FALSE, space, header, mtr);
1249 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
1252 flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
1259 static __attribute__((nonnull))
1261 fsp_alloc_from_free_frag(
1263 fsp_header_t* header,
1282 flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
1286 flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
1317 #ifdef UNIV_SYNC_DEBUG
1318 ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)
1319 == rw_lock_own(&block->
lock, RW_LOCK_EX));
1323 rw_lock_x_lock(&block->
lock);
1324 mutex_enter(&block->
mutex);
1326 mutex_exit(&block->
mutex);
1335 ut_ad(init_mtr == mtr
1336 || !mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
1338 fsp_init_file_page(block, init_mtr);
1350 static __attribute__((nonnull, warn_unused_result))
1352 fsp_alloc_free_page(
1363 fsp_header_t* header;
1376 descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
1392 descr = fsp_alloc_free_extent(space, zip_size,
1395 if (descr == NULL) {
1403 descr + XDES_FLST_NODE, mtr);
1405 descr = xdes_lst_get_descriptor(space, zip_size,
1417 hint % FSP_EXTENT_SIZE, mtr);
1418 if (free == ULINT_UNDEFINED) {
1426 page_no = xdes_get_offset(descr) + free;
1430 if (space_size <= page_no) {
1435 if (page_no >= FSP_EXTENT_SIZE) {
1437 "InnoDB: Error: trying to extend a"
1438 " single-table tablespace %lu\n"
1439 "InnoDB: by single page(s) though the"
1440 " space size %lu. Page no %lu.\n",
1441 (ulong) space, (ulong) space_size,
1445 if (!fsp_try_extend_data_file_with_pages(space, page_no,
1452 fsp_alloc_from_free_frag(header, descr, free, mtr);
1453 return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr));
1468 fsp_header_t* header;
1479 descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
1483 if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) {
1485 "InnoDB: Error: File space extent descriptor"
1486 " of page %lu has state %lu\n",
1489 fputs(
"InnoDB: Dump of descriptor: ", stderr);
1496 if (state == XDES_FREE) {
1507 page % FSP_EXTENT_SIZE, mtr)) {
1510 "InnoDB: Error: File space extent descriptor"
1511 " of page %lu says it is free\n"
1512 "InnoDB: Dump of descriptor: ", (ulong) page);
1525 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
1526 xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
1530 if (state == XDES_FULL_FRAG) {
1532 flst_remove(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
1535 flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
1538 frag_n_used + FSP_EXTENT_SIZE - 1,
1541 ut_a(frag_n_used > 0);
1548 flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
1550 fsp_free_extent(space, zip_size, page, mtr);
1553 mtr->n_freed_pages++;
1568 fsp_header_t* header;
1575 descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
1587 flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
1595 fsp_seg_inode_page_get_nth_inode(
1599 ulint zip_size __attribute__((unused)),
1601 mtr_t* mtr __attribute__((unused)))
1604 ut_ad(i < FSP_SEG_INODES_PER_PAGE(zip_size));
1605 ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
1607 return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);
1615 fsp_seg_inode_page_find_used(
1622 fseg_inode_t* inode;
1624 for (i = 0; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
1626 inode = fsp_seg_inode_page_get_nth_inode(
1627 page, i, zip_size, mtr);
1633 == FSEG_MAGIC_N_VALUE);
1638 return(ULINT_UNDEFINED);
1646 fsp_seg_inode_page_find_free(
1653 for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
1655 fseg_inode_t* inode;
1657 inode = fsp_seg_inode_page_get_nth_inode(
1658 page, i, zip_size, mtr);
1666 == FSEG_MAGIC_N_VALUE);
1669 return(ULINT_UNDEFINED);
1677 fsp_alloc_seg_inode_page(
1679 fsp_header_t* space_header,
1682 fseg_inode_t* inode;
1695 block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
1697 if (block == NULL) {
1702 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
1707 page = buf_block_get_frame(block);
1712 for (ulint i = 0; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
1714 inode = fsp_seg_inode_page_get_nth_inode(
1715 page, i, zip_size, mtr);
1721 space_header + FSP_SEG_INODES_FREE,
1722 page + FSEG_INODE_PAGE_NODE, mtr);
1732 fsp_alloc_seg_inode(
1734 fsp_header_t* space_header,
1740 fseg_inode_t* inode;
1747 if (
flst_get_len(space_header + FSP_SEG_INODES_FREE, mtr) == 0) {
1750 success = fsp_alloc_seg_inode_page(space_header, mtr);
1763 zip_size, page_no, RW_X_LATCH, mtr);
1764 buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
1766 page = buf_block_get_frame(block);
1768 n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr);
1770 ut_a(n != ULINT_UNDEFINED);
1772 inode = fsp_seg_inode_page_get_nth_inode(page, n, zip_size, mtr);
1774 if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
1780 page + FSEG_INODE_PAGE_NODE, mtr);
1783 page + FSEG_INODE_PAGE_NODE, mtr);
1800 fseg_inode_t* inode,
1804 fsp_header_t* space_header;
1813 == fsp_seg_inode_page_find_free(page, 0, zip_size, mtr)) {
1818 page + FSEG_INODE_PAGE_NODE, mtr);
1821 page + FSEG_INODE_PAGE_NODE, mtr);
1828 == fsp_seg_inode_page_find_used(page, zip_size, mtr)) {
1833 page + FSEG_INODE_PAGE_NODE, mtr);
1846 fseg_header_t* header,
1853 fseg_inode_t* inode;
1859 inode =
fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
1866 == FSEG_MAGIC_N_VALUE);
1879 fseg_header_t* header,
1886 = fseg_inode_try_get(header, space, zip_size, mtr);
1896 fseg_get_nth_frag_page_no(
1898 fseg_inode_t* inode,
1900 mtr_t* mtr __attribute__((unused)))
1903 ut_ad(inode && mtr);
1904 ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
1905 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
1908 + n * FSEG_FRAG_SLOT_SIZE));
1915 fseg_set_nth_frag_page_no(
1917 fseg_inode_t* inode,
1922 ut_ad(inode && mtr);
1923 ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
1924 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
1936 fseg_find_free_frag_page_slot(
1938 fseg_inode_t* inode,
1944 ut_ad(inode && mtr);
1946 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
1947 page_no = fseg_get_nth_frag_page_no(inode, i, mtr);
1955 return(ULINT_UNDEFINED);
1963 fseg_find_last_used_frag_page_slot(
1965 fseg_inode_t* inode,
1971 ut_ad(inode && mtr);
1973 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
1974 page_no = fseg_get_nth_frag_page_no(
1975 inode, FSEG_FRAG_ARR_N_SLOTS - i - 1, mtr);
1979 return(FSEG_FRAG_ARR_N_SLOTS - i - 1);
1983 return(ULINT_UNDEFINED);
1991 fseg_get_n_frag_pages(
1993 fseg_inode_t* inode,
1999 ut_ad(inode && mtr);
2001 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
2002 if (
FIL_NULL != fseg_get_nth_frag_page_no(inode, i, mtr)) {
2025 ibool has_done_reservation,
2035 fsp_header_t* space_header;
2036 fseg_inode_t* inode;
2039 fseg_header_t* header = 0;
2046 ut_ad(byte_offset + FSEG_HEADER_SIZE
2053 block =
buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
2054 header = byte_offset + buf_block_get_frame(block);
2063 if (space == IBUF_SPACE_ID) {
2068 if (!has_done_reservation) {
2078 inode = fsp_alloc_seg_inode(space_header, mtr);
2080 if (inode == NULL) {
2101 for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
2102 fseg_set_nth_frag_page_no(inode, i,
FIL_NULL, mtr);
2106 block = fseg_alloc_free_page_low(space, zip_size,
2107 inode, 0, FSP_UP, mtr, mtr);
2109 if (block == NULL) {
2111 fsp_free_seg_inode(space, zip_size, inode, mtr);
2118 header = byte_offset + buf_block_get_frame(block);
2133 if (!has_done_reservation) {
2167 fseg_n_reserved_pages_low(
2169 fseg_inode_t* inode,
2176 ut_ad(inode && used && mtr);
2177 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
2180 + FSP_EXTENT_SIZE *
flst_get_len(inode + FSEG_FULL, mtr)
2181 + fseg_get_n_frag_pages(inode, mtr);
2183 ret = fseg_get_n_frag_pages(inode, mtr)
2184 + FSP_EXTENT_SIZE *
flst_get_len(inode + FSEG_FREE, mtr)
2185 + FSP_EXTENT_SIZE *
flst_get_len(inode + FSEG_NOT_FULL, mtr)
2186 + FSP_EXTENT_SIZE *
flst_get_len(inode + FSEG_FULL, mtr);
2199 fseg_header_t* header,
2204 fseg_inode_t* inode;
2216 inode = fseg_inode_get(header, space, zip_size, mtr);
2218 ret = fseg_n_reserved_pages_low(inode, used, mtr);
2230 fseg_fill_free_list(
2232 fseg_inode_t* inode,
2246 ut_ad(inode && mtr);
2249 reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
2251 if (reserved < FSEG_FREE_LIST_LIMIT * FSP_EXTENT_SIZE) {
2264 for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) {
2265 descr = xdes_get_descriptor(space, zip_size, hint, mtr);
2275 descr = fsp_alloc_free_extent(space, zip_size, hint, mtr);
2281 == FSEG_MAGIC_N_VALUE);
2284 flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
2285 hint += FSP_EXTENT_SIZE;
2299 fseg_alloc_free_extent(
2301 fseg_inode_t* inode,
2319 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
2322 descr = fsp_alloc_free_extent(space, zip_size, 0, mtr);
2324 if (descr == NULL) {
2333 flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
2336 fseg_fill_free_list(inode, space, zip_size,
2337 xdes_get_offset(descr) + FSP_EXTENT_SIZE,
2354 fseg_alloc_free_page_low(
2359 fseg_inode_t* seg_inode,
2373 fsp_header_t* space_header;
2386 ut_ad((direction >= FSP_UP) && (direction <= FSP_NO_DIR));
2388 == FSEG_MAGIC_N_VALUE);
2394 reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
2398 descr = xdes_get_descriptor_with_space_hdr(space_header, space,
2400 if (descr == NULL) {
2405 descr = xdes_get_descriptor(space, zip_size, hint, mtr);
2413 hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
2422 goto got_hinted_page;
2425 && reserved - used < reserved / FSEG_FILLFACTOR
2426 && used >= FSEG_FRAG_LIMIT) {
2432 ret_descr = fsp_alloc_free_extent(space, zip_size, hint, mtr);
2434 ut_a(ret_descr == descr);
2439 ret_descr + XDES_FLST_NODE, mtr);
2442 fseg_fill_free_list(seg_inode, space, zip_size,
2443 hint + FSP_EXTENT_SIZE, mtr);
2444 goto take_hinted_page;
2446 }
else if ((direction != FSP_NO_DIR)
2447 && ((reserved - used) < reserved / FSEG_FILLFACTOR)
2448 && (used >= FSEG_FRAG_LIMIT)
2450 = fseg_alloc_free_extent(seg_inode,
2451 space, zip_size, mtr)))) {
2459 ret_page = xdes_get_offset(ret_descr);
2461 if (direction == FSP_DOWN) {
2462 ret_page += FSP_EXTENT_SIZE - 1;
2476 ret_page = xdes_get_offset(ret_descr)
2478 hint % FSP_EXTENT_SIZE, mtr);
2480 }
else if (reserved - used > 0) {
2485 if (
flst_get_len(seg_inode + FSEG_NOT_FULL, mtr) > 0) {
2488 }
else if (
flst_get_len(seg_inode + FSEG_FREE, mtr) > 0) {
2495 ret_descr = xdes_lst_get_descriptor(space, zip_size,
2497 ret_page = xdes_get_offset(ret_descr)
2501 }
else if (used < FSEG_FRAG_LIMIT) {
2505 space, zip_size, hint, mtr, init_mtr);
2507 if (block != NULL) {
2510 n = fseg_find_free_frag_page_slot(seg_inode, mtr);
2511 ut_a(n != ULINT_UNDEFINED);
2513 fseg_set_nth_frag_page_no(
2525 ret_descr = fseg_alloc_free_extent(seg_inode,
2526 space, zip_size, mtr);
2528 if (ret_descr == NULL) {
2531 ret_page = xdes_get_offset(ret_descr);
2544 if (space_size <= ret_page) {
2548 if (ret_page >= FSP_EXTENT_SIZE) {
2550 "InnoDB: Error (2): trying to extend"
2551 " a single-table tablespace %lu\n"
2552 "InnoDB: by single page(s) though"
2553 " the space size %lu. Page no %lu.\n",
2554 (ulong) space, (ulong) space_size,
2559 success = fsp_try_extend_data_file_with_pages(
2560 space, ret_page, space_header, mtr);
2571 if (ret_descr != NULL) {
2576 ut_ad(xdes_get_descriptor(space, zip_size, ret_page, mtr)
2580 ret_descr, XDES_FREE_BIT,
2581 ret_page % FSP_EXTENT_SIZE, mtr));
2583 fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
2586 return(fsp_page_create(
2590 ret_page, mtr, init_mtr));
2613 ibool has_done_reservation,
2624 fseg_inode_t* inode;
2644 if (space == IBUF_SPACE_ID) {
2649 inode = fseg_inode_get(seg_header, space, zip_size, mtr);
2651 if (!has_done_reservation
2657 block = fseg_alloc_free_page_low(space, zip_size,
2658 inode, hint, direction,
2660 if (!has_done_reservation) {
2676 fsp_reserve_free_pages(
2679 fsp_header_t* space_header,
2689 ut_a(size < FSP_EXTENT_SIZE / 2);
2691 descr = xdes_get_descriptor_with_space_hdr(space_header, space, 0,
2695 ut_a(n_used <= size);
2697 if (size >= n_used + 2) {
2702 return(fsp_try_extend_data_file_with_pages(space, n_used + 1,
2703 space_header, mtr));
2744 fsp_header_t* space_header;
2746 ulint n_free_list_ext;
2755 ulint n_pages_added;
2758 *n_reserved =
n_ext;
2769 if (size < FSP_EXTENT_SIZE / 2) {
2772 return(fsp_reserve_free_pages(space, space_header, size, mtr));
2775 n_free_list_ext =
flst_get_len(space_header + FSP_FREE, mtr);
2784 n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
2786 if (n_free_up > 0) {
2789 n_free_up -= n_free_up
2790 / (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE);
2792 n_free_up -= n_free_up
2793 / (zip_size / FSP_EXTENT_SIZE);
2797 n_free = n_free_list_ext + n_free_up;
2799 if (alloc_type == FSP_NORMAL) {
2804 reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
2806 if (n_free <= reserve + n_ext) {
2810 }
else if (alloc_type == FSP_UNDO) {
2813 reserve = 1 + ((size / FSP_EXTENT_SIZE) * 1) / 200;
2815 if (n_free <= reserve + n_ext) {
2820 ut_a(alloc_type == FSP_CLEANING);
2829 success = fsp_try_extend_data_file(&n_pages_added, space,
2831 if (success && n_pages_added > 0) {
2851 fsp_header_t* space_header;
2852 ulint n_free_list_ext;
2887 return(ULLINT_UNDEFINED);
2913 return(ULLINT_UNDEFINED);
2924 n_free_list_ext =
flst_get_len(space_header + FSP_FREE, &mtr);
2930 if (size < FSP_EXTENT_SIZE) {
2942 n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
2944 if (n_free_up > 0) {
2947 n_free_up -= n_free_up
2948 / (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE);
2950 n_free_up -= n_free_up
2951 / (zip_size / FSP_EXTENT_SIZE);
2955 n_free = n_free_list_ext + n_free_up;
2961 reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
2963 if (reserve > n_free) {
2968 return((ullint) (n_free - reserve)
2970 * (UNIV_PAGE_SIZE / 1024));
2972 return((ullint) (n_free - reserve)
2974 * (zip_size / 1024));
2981 static __attribute__((nonnull))
2983 fseg_mark_page_used(
2985 fseg_inode_t* seg_inode,
2990 ulint not_full_n_used;
2994 == FSEG_MAGIC_N_VALUE);
3002 flst_remove(seg_inode + FSEG_FREE, descr + XDES_FLST_NODE,
3005 descr + XDES_FLST_NODE, mtr);
3009 descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr));
3012 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, FALSE, mtr);
3014 not_full_n_used =
mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
3023 descr + XDES_FLST_NODE, mtr);
3025 descr + XDES_FLST_NODE, mtr);
3028 not_full_n_used - FSP_EXTENT_SIZE,
3039 fseg_inode_t* seg_inode,
3047 ulint not_full_n_used;
3053 ut_ad(seg_inode && mtr);
3055 == FSEG_MAGIC_N_VALUE);
3063 descr = xdes_get_descriptor(space, zip_size, page, mtr);
3066 page % FSP_EXTENT_SIZE, mtr)) {
3067 fputs(
"InnoDB: Dump of the tablespace extent descriptor: ",
3071 fprintf(stderr,
"\n"
3072 "InnoDB: Serious error! InnoDB is trying to"
3074 "InnoDB: though it is already marked as free"
3075 " in the tablespace!\n"
3076 "InnoDB: The tablespace free space info is corrupt.\n"
3077 "InnoDB: You may need to dump your"
3078 " InnoDB tables and recreate the whole\n"
3079 "InnoDB: database!\n", (ulong) page);
3081 fputs(
"InnoDB: Please refer to\n"
3082 "InnoDB: " REFMAN
"forcing-innodb-recovery.html\n"
3083 "InnoDB: about forcing recovery.\n", stderr);
3089 if (state != XDES_FSEG) {
3093 if (fseg_get_nth_frag_page_no(seg_inode, i, mtr)
3096 fseg_set_nth_frag_page_no(seg_inode, i,
3102 fsp_free_page(space, zip_size, page, mtr);
3113 "InnoDB: InnoDB is freeing space %lu page %lu,\n"
3114 "InnoDB: which belongs to descr seg %llu\n"
3115 "InnoDB: segment %llu.\n",
3116 (ulong) space, (ulong) page,
3120 if (UNIV_UNLIKELY(descr_id != seg_id)) {
3121 fputs(
"InnoDB: Dump of the tablespace extent descriptor: ",
3124 fputs(
"\nInnoDB: Dump of the segment inode: ", stderr);
3129 "InnoDB: Serious error: InnoDB is trying to"
3130 " free space %lu page %lu,\n"
3131 "InnoDB: which does not belong to"
3132 " segment %llu but belongs\n"
3133 "InnoDB: to segment %llu.\n",
3134 (ulong) space, (ulong) page,
3140 not_full_n_used =
mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
3145 descr + XDES_FLST_NODE, mtr);
3147 descr + XDES_FLST_NODE, mtr);
3149 not_full_n_used + FSP_EXTENT_SIZE - 1,
3152 ut_a(not_full_n_used > 0);
3157 xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
3158 xdes_set_bit(descr, XDES_CLEAN_BIT, page % FSP_EXTENT_SIZE, TRUE, mtr);
3163 descr + XDES_FLST_NODE, mtr);
3164 fsp_free_extent(space, zip_size, page, mtr);
3167 mtr->n_freed_pages++;
3176 fseg_header_t* seg_header,
3183 fseg_inode_t* seg_inode;
3191 seg_inode = fseg_inode_get(seg_header, space, zip_size, mtr);
3193 fseg_free_page_low(seg_inode, space, zip_size, page, mtr);
3195 #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
3196 buf_page_set_file_page_was_freed(space, page);
3207 fseg_header_t* seg_header,
3217 fseg_inode_t* seg_inode;
3225 seg_inode = fseg_inode_get(seg_header, space, zip_size, &mtr);
3229 == FSEG_MAGIC_N_VALUE);
3232 descr = xdes_get_descriptor(space, zip_size, page, &mtr);
3236 descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, &mtr);
3249 fseg_inode_t* seg_inode,
3256 ulint first_page_in_extent;
3258 ulint not_full_n_used;
3262 ut_ad(seg_inode && mtr);
3264 descr = xdes_get_descriptor(space, zip_size, page, mtr);
3267 ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
3269 == FSEG_MAGIC_N_VALUE);
3271 first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
3273 for (i = 0; i < FSP_EXTENT_SIZE; i++) {
3280 space, zip_size, first_page_in_extent + i);
3286 descr + XDES_FLST_NODE, mtr);
3289 descr + XDES_FLST_NODE, mtr);
3292 descr + XDES_FLST_NODE, mtr);
3295 seg_inode + FSEG_NOT_FULL_N_USED,
MLOG_4BYTES, mtr);
3298 ut_a(not_full_n_used >= descr_n_used);
3300 not_full_n_used - descr_n_used,
3304 fsp_free_extent(space, zip_size, page, mtr);
3306 #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
3307 for (i = 0; i < FSP_EXTENT_SIZE; i++) {
3309 buf_page_set_file_page_was_freed(space,
3310 first_page_in_extent + i);
3325 fseg_header_t* header,
3334 fseg_inode_t* inode;
3349 descr = xdes_get_descriptor(space, zip_size, header_page, mtr);
3355 header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
3357 inode = fseg_inode_try_get(header, space, zip_size, mtr);
3359 if (UNIV_UNLIKELY(inode == NULL)) {
3360 fprintf(stderr,
"double free of inode from %u:%u\n",
3361 (
unsigned) space, (
unsigned) header_page);
3365 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
3367 if (descr != NULL) {
3369 page = xdes_get_offset(descr);
3371 fseg_free_extent(inode, space, zip_size, page, mtr);
3377 n = fseg_find_last_used_frag_page_slot(inode, mtr);
3379 if (n == ULINT_UNDEFINED) {
3381 fsp_free_seg_inode(space, zip_size, inode, mtr);
3386 fseg_free_page_low(inode, space, zip_size,
3387 fseg_get_nth_frag_page_no(inode, n, mtr), mtr);
3389 n = fseg_find_last_used_frag_page_slot(inode, mtr);
3391 if (n == ULINT_UNDEFINED) {
3393 fsp_free_seg_inode(space, zip_size, inode, mtr);
3409 fseg_header_t* header,
3416 fseg_inode_t* inode;
3430 inode = fseg_inode_get(header, space, zip_size, mtr);
3432 descr = fseg_get_first_extent(inode, space, zip_size, mtr);
3434 if (descr != NULL) {
3436 page = xdes_get_offset(descr);
3438 fseg_free_extent(inode, space, zip_size, page, mtr);
3445 n = fseg_find_last_used_frag_page_slot(inode, mtr);
3447 if (n == ULINT_UNDEFINED) {
3451 page_no = fseg_get_nth_frag_page_no(inode, n, mtr);
3458 fseg_free_page_low(inode, space, zip_size, page_no, mtr);
3470 fseg_get_first_extent(
3472 fseg_inode_t* inode,
3481 ut_ad(inode && mtr);
3492 }
else if (
flst_get_len(inode + FSEG_NOT_FULL, mtr) > 0) {
3505 descr = xdes_lst_get_descriptor(space, zip_size, first, mtr);
3517 fseg_inode_t* inode,
3528 ut_ad(mtr_memo_contains_page(mtr2, inode, MTR_MEMO_PAGE_X_FIX));
3551 descr = xdes_lst_get_descriptor(space, zip_size,
3574 descr = xdes_lst_get_descriptor(space, zip_size,
3600 descr = xdes_lst_get_descriptor(space, zip_size,
3611 ut_a(n_used == n_used2);
3624 fseg_header_t* header,
3627 fseg_inode_t* inode;
3638 inode = fseg_inode_get(header, space, zip_size, mtr);
3640 ret = fseg_validate_low(inode, mtr);
3652 fseg_inode_t* inode,
3666 ut_ad(mtr_memo_contains_page(mtr, inode, MTR_MEMO_PAGE_X_FIX));
3670 reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
3676 n_frag = fseg_get_n_frag_pages(inode, mtr);
3682 "SEGMENT id %llu space %lu; page %lu;"
3683 " res %lu used %lu; full ext %lu\n"
3684 "fragm pages %lu; free extents %lu;"
3685 " not full extents %lu: pages %lu\n",
3687 (ulong) space, (ulong) page_no,
3688 (ulong) reserved, (ulong) used, (ulong) n_full,
3689 (ulong) n_frag, (ulong) n_free, (ulong) n_not_full,
3694 #ifdef UNIV_BTR_PRINT
3701 fseg_header_t* header,
3704 fseg_inode_t* inode;
3714 inode = fseg_inode_get(header, space, zip_size, mtr);
3716 fseg_print_low(inode, mtr);
3729 fsp_header_t* header;
3730 fseg_inode_t* seg_inode;
3743 ulint descr_count = 0;
3746 ulint n_full_frag_pages;
3748 ulint seg_inode_len_free;
3749 ulint seg_inode_len_full;
3754 ut_a(zip_size <= UNIV_ZIP_SIZE_MAX);
3755 ut_a(!zip_size || zip_size >= UNIV_ZIP_SIZE_MIN);
3773 n_full_frag_pages = FSP_EXTENT_SIZE
3776 if (UNIV_UNLIKELY(free_limit > size)) {
3779 ut_a(size < FSP_EXTENT_SIZE);
3802 descr = xdes_lst_get_descriptor(space, zip_size,
3826 descr = xdes_lst_get_descriptor(space, zip_size,
3853 descr = xdes_lst_get_descriptor(space, zip_size,
3871 seg_inode_len_full =
flst_get_len(header + FSP_SEG_INODES_FULL, &mtr);
3883 space, zip_size, node_addr, RW_X_LATCH, &mtr)
3884 - FSEG_INODE_PAGE_NODE;
3886 seg_inode = fsp_seg_inode_page_get_nth_inode(
3887 seg_inode_page, n, zip_size, &mtr);
3889 fseg_validate_low(seg_inode, &mtr);
3898 n_used2 += fseg_get_n_frag_pages(seg_inode, &mtr);
3901 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
3903 }
while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
3905 node_addr = next_node_addr;
3915 seg_inode_len_free =
flst_get_len(header + FSP_SEG_INODES_FREE, &mtr);
3928 space, zip_size, node_addr, RW_X_LATCH, &mtr)
3929 - FSEG_INODE_PAGE_NODE;
3931 seg_inode = fsp_seg_inode_page_get_nth_inode(
3932 seg_inode_page, n, zip_size, &mtr);
3934 fseg_validate_low(seg_inode, &mtr);
3937 seg_inode + FSEG_FREE, &mtr);
3939 seg_inode + FSEG_FULL, &mtr);
3941 seg_inode + FSEG_NOT_FULL, &mtr);
3942 n_used2 += fseg_get_n_frag_pages(
3947 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
3949 }
while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
3951 node_addr = next_node_addr;
3954 ut_a(descr_count * FSP_EXTENT_SIZE == free_limit);
3956 ut_a(n_used + n_full_frag_pages
3957 == n_used2 + 2 * ((free_limit + (UNIV_PAGE_SIZE - 1))
3959 + seg_inode_len_full + seg_inode_len_free);
3961 ut_a(n_used + n_full_frag_pages
3962 == n_used2 + 2 * ((free_limit + (zip_size - 1))
3964 + seg_inode_len_full + seg_inode_len_free);
3966 ut_a(frag_n_used == n_used);
3981 fsp_header_t* header;
3982 fseg_inode_t* seg_inode;
4024 n_free_frag =
flst_get_len(header + FSP_FREE_FRAG, &mtr);
4025 n_full_frag =
flst_get_len(header + FSP_FULL_FRAG, &mtr);
4030 "FILE SPACE INFO: id %lu\n"
4031 "size %lu, free limit %lu, free extents %lu\n"
4032 "not full frag extents %lu: used pages %lu,"
4033 " full frag extents %lu\n"
4034 "first seg id not used %llu\n",
4036 (ulong) size, (ulong) free_limit, (ulong) n_free,
4037 (ulong) n_free_frag, (ulong) frag_n_used, (ulong) n_full_frag,
4063 space, zip_size, node_addr, RW_X_LATCH, &mtr)
4064 - FSEG_INODE_PAGE_NODE;
4066 seg_inode = fsp_seg_inode_page_get_nth_inode(
4067 seg_inode_page, n, zip_size, &mtr);
4069 fseg_print_low(seg_inode, &mtr);
4074 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
4076 }
while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
4078 node_addr = next_node_addr;
4100 space, zip_size, node_addr, RW_X_LATCH, &mtr)
4101 - FSEG_INODE_PAGE_NODE;
4103 seg_inode = fsp_seg_inode_page_get_nth_inode(
4104 seg_inode_page, n, zip_size, &mtr);
4107 fseg_print_low(seg_inode, &mtr);
4112 seg_inode_page + FSEG_INODE_PAGE_NODE, &mtr);
4114 }
while (++n < FSP_SEG_INODES_PER_PAGE(zip_size));
4116 node_addr = next_node_addr;
4121 fprintf(stderr,
"NUMBER of file segments: %lu\n", (ulong) n_segs);