1
1
/*****************************************************************************
3
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
128
128
#define FSEG_ARR_OFFSET (FSEG_PAGE_DATA + FLST_NODE_SIZE)
129
129
/*-------------------------------------*/
130
#define FSEG_ID 0 /* 8 bytes of segment id: if this is 0,
131
it means that the header is unused */
130
#define FSEG_ID 0 /* 8 bytes of segment id: if this is
131
ut_dulint_zero, it means that the
132
133
#define FSEG_NOT_FULL_N_USED 8
133
134
/* number of used segment pages in
134
135
the FSEG_NOT_FULL list */
388
const xdes_t* descr, /*!< in: descriptor */
389
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
390
ulint offset, /*!< in: page offset within extent:
391
0 ... FSP_EXTENT_SIZE - 1 */
392
mtr_t* mtr) /*!< in: mtr */
389
xdes_t* descr, /*!< in: descriptor */
390
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
391
ulint offset, /*!< in: page offset within extent:
392
0 ... FSP_EXTENT_SIZE - 1 */
393
mtr_t* mtr) /*!< in: mtr */
395
396
ulint byte_index;
553
const xdes_t* descr, /*!< in: descriptor */
554
mtr_t* mtr) /*!< in: mtr */
554
xdes_t* descr, /*!< in: descriptor */
555
mtr_t* mtr) /*!< in: mtr */
556
557
if (0 == xdes_get_n_used(descr, mtr)) {
571
const xdes_t* descr, /*!< in: descriptor */
572
mtr_t* mtr) /*!< in: mtr */
572
xdes_t* descr, /*!< in: descriptor */
573
mtr_t* mtr) /*!< in: mtr */
574
575
if (FSP_EXTENT_SIZE == xdes_get_n_used(descr, mtr)) {
588
xdes_t* descr, /*!< in/out: descriptor */
589
xdes_t* descr, /*!< in: descriptor */
589
590
ulint state, /*!< in: state to set */
590
591
mtr_t* mtr) /*!< in: mtr handle */
705
706
xdes_get_descriptor_with_space_hdr(
706
707
/*===============================*/
707
fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
708
fsp_header_t* sp_header,/*!< in: space header, x-latched */
708
709
ulint space, /*!< in: space id */
709
710
ulint offset, /*!< in: page offset;
710
711
if equal to the free limit,
871
memset(page, 0, UNIV_PAGE_SIZE);
872
#ifdef UNIV_BASIC_LOG_DEBUG
873
memset(page, 0xff, UNIV_PAGE_SIZE);
872
875
mach_write_to_4(page + FIL_PAGE_OFFSET, buf_block_get_page_no(block));
876
memset(page + FIL_PAGE_LSN, 0, 8);
873
877
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
874
878
buf_block_get_space(block));
879
memset(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, 0, 8);
877
882
#ifndef UNIV_HOTBACKUP
899
904
fsp_parse_init_file_page(
900
905
/*=====================*/
901
906
byte* ptr, /*!< in: buffer */
902
byte* /*end_ptr __attribute__((unused))*/, /*!< in: buffer end */
907
byte* end_ptr __attribute__((unused)), /*!< in: buffer end */
903
908
buf_block_t* block) /*!< in: block or NULL */
905
910
ut_ad(ptr && end_ptr);
998
1003
flst_init(header + FSP_SEG_INODES_FULL, mtr);
999
1004
flst_init(header + FSP_SEG_INODES_FREE, mtr);
1001
mlog_write_ull(header + FSP_SEG_ID, 1, mtr);
1006
mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
1002
1007
if (space == 0) {
1003
1008
fsp_fill_free_list(FALSE, space, header, mtr);
1004
1009
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
1005
0, 0, DICT_IBUF_ID_MIN + space,
1010
0, 0, ut_dulint_add(DICT_IBUF_ID_MIN, space),
1006
1011
dict_ind_redundant, mtr);
1008
1013
fsp_fill_free_list(TRUE, space, header, mtr);
1337
1342
descriptor page and ibuf bitmap page;
1338
1343
then we do not allocate more extents */
1339
1344
ulint space, /*!< in: space */
1340
fsp_header_t* header, /*!< in/out: space header */
1345
fsp_header_t* header, /*!< in: space header */
1341
1346
mtr_t* mtr) /*!< in: mtr */
1810
1815
/*=============================*/
1811
1816
page_t* page, /*!< in: segment inode page */
1812
1817
ulint i, /*!< in: inode index on page */
1813
ulint /*zip_size __attribute__((unused))*/,
1818
ulint zip_size __attribute__((unused)),
1814
1819
/*!< in: compressed page size, or 0 */
1815
mtr_t* /*mtr __attribute__((unused))*/)
1820
mtr_t* mtr __attribute__((unused)))
1816
1821
/*!< in: mini-transaction handle */
1818
1823
ut_ad(i < FSP_SEG_INODES_PER_PAGE(zip_size));
1930
1935
inode = fsp_seg_inode_page_get_nth_inode(page, i,
1931
1936
zip_size, mtr);
1933
mlog_write_ull(inode + FSEG_ID, 0, mtr);
1938
mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
1936
1941
flst_add_last(space_header + FSP_SEG_INODES_FREE,
2035
2040
page + FSEG_INODE_PAGE_NODE, mtr);
2038
mlog_write_ull(inode + FSEG_ID, 0, mtr);
2043
mlog_write_dulint(inode + FSEG_ID, ut_dulint_zero, mtr);
2039
2044
mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
2041
2046
if (ULINT_UNDEFINED
2111
2117
/*======================*/
2112
2118
fseg_inode_t* inode, /*!< in: segment inode */
2113
2119
ulint n, /*!< in: slot index */
2114
mtr_t* /*mtr __attribute__((unused))*/) /*!< in: mtr handle */
2120
mtr_t* mtr __attribute__((unused))) /*!< in: mtr handle */
2116
2122
ut_ad(inode && mtr);
2117
2123
ut_ad(n < FSEG_FRAG_ARR_N_SLOTS);
2301
2307
/* Read the next segment id from space header and increment the
2302
2308
value in space header */
2304
seg_id = mach_read_from_8(space_header + FSP_SEG_ID);
2306
mlog_write_ull(space_header + FSP_SEG_ID, seg_id + 1, mtr);
2308
mlog_write_ull(inode + FSEG_ID, seg_id, mtr);
2310
seg_id = mtr_read_dulint(space_header + FSP_SEG_ID, mtr);
2312
mlog_write_dulint(space_header + FSP_SEG_ID, ut_dulint_add(seg_id, 1),
2315
mlog_write_dulint(inode + FSEG_ID, seg_id, mtr);
2309
2316
mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr);
2311
2318
flst_init(inode + FSEG_FREE, mtr);
2495
2502
xdes_set_state(descr, XDES_FSEG, mtr);
2497
seg_id = mach_read_from_8(inode + FSEG_ID);
2504
seg_id = mtr_read_dulint(inode + FSEG_ID, mtr);
2498
2505
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N)
2499
2506
== FSEG_MAGIC_N_VALUE);
2500
mlog_write_ull(descr + XDES_ID, seg_id, mtr);
2507
mlog_write_dulint(descr + XDES_ID, seg_id, mtr);
2502
2509
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
2503
2510
hint += FSP_EXTENT_SIZE;
2545
seg_id = mach_read_from_8(inode + FSEG_ID);
2552
seg_id = mtr_read_dulint(inode + FSEG_ID, mtr);
2547
2554
xdes_set_state(descr, XDES_FSEG, mtr);
2548
mlog_write_ull(descr + XDES_ID, seg_id, mtr);
2555
mlog_write_dulint(descr + XDES_ID, seg_id, mtr);
2549
2556
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
2551
2558
/* Try to fill the segment free list */
2596
2603
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
2597
2604
== FSEG_MAGIC_N_VALUE);
2598
2605
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
2599
seg_id = mach_read_from_8(seg_inode + FSEG_ID);
2606
seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr);
2608
ut_ad(!ut_dulint_is_zero(seg_id));
2603
2610
reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
2616
2623
/* In the big if-else below we look for ret_page and ret_descr */
2617
2624
/*-------------------------------------------------------------*/
2618
2625
if ((xdes_get_state(descr, mtr) == XDES_FSEG)
2619
&& mach_read_from_8(descr + XDES_ID) == seg_id
2626
&& (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
2620
2628
&& (xdes_get_bit(descr, XDES_FREE_BIT,
2621
2629
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
2638
2646
ut_a(ret_descr == descr);
2640
2648
xdes_set_state(ret_descr, XDES_FSEG, mtr);
2641
mlog_write_ull(ret_descr + XDES_ID, seg_id, mtr);
2649
mlog_write_dulint(ret_descr + XDES_ID, seg_id, mtr);
2642
2650
flst_add_last(seg_inode + FSEG_FREE,
2643
2651
ret_descr + XDES_FLST_NODE, mtr);
2668
2676
/*-----------------------------------------------------------*/
2669
2677
} else if ((xdes_get_state(descr, mtr) == XDES_FSEG)
2670
&& mach_read_from_8(descr + XDES_ID) == seg_id
2678
&& (0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID,
2671
2680
&& (!xdes_is_full(descr, mtr))) {
2673
2682
/* 4. We can take the page from the same extent as the
2771
2780
can be obtained immediately with buf_page_get without need
2772
2781
for a disk read */
2773
2782
buf_block_t* block;
2774
ulint page_zip_size = dict_table_flags_to_zip_size(
2783
ulint zip_size = dict_table_flags_to_zip_size(
2775
2784
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
2777
block = buf_page_create(space, ret_page, page_zip_size, mtr);
2786
block = buf_page_create(space, ret_page, zip_size, mtr);
2778
2787
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
2780
if (UNIV_UNLIKELY(block != buf_page_get(space, page_zip_size,
2789
if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
2781
2790
ret_page, RW_X_LATCH,
2790
2799
The extent is still in the appropriate list (FSEG_NOT_FULL
2791
2800
or FSEG_FREE), and the page is not yet marked as used. */
2793
ut_ad(xdes_get_descriptor(space, page_zip_size, ret_page, mtr)
2802
ut_ad(xdes_get_descriptor(space, zip_size, ret_page, mtr)
2795
2804
ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT,
2796
2805
ret_page % FSP_EXTENT_SIZE, mtr) == TRUE);
2798
fseg_mark_page_used(seg_inode, space, page_zip_size, ret_page, mtr);
2807
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
2801
2810
buf_reset_check_index_page_at_flush(space, ret_page);
3098
3107
ut_ad(!mutex_own(&kernel_mutex));
3100
/* The convoluted mutex acquire is to overcome latching order
3101
issues: The problem is that the fil_mutex is at a lower level
3102
than the tablespace latch and the buffer pool mutex. We have to
3103
first prevent any operations on the file system by acquiring the
3104
dictionary mutex. Then acquire the tablespace latch to obey the
3105
latching order and then release the dictionary mutex. That way we
3106
ensure that the tablespace instance can't be freed while we are
3107
examining its contents (see fil_space_free()).
3109
However, there is one further complication, we release the fil_mutex
3110
when we need to invalidate the the pages in the buffer pool and we
3111
reacquire the fil_mutex when deleting and freeing the tablespace
3112
instance in fil0fil.c. Here we need to account for that situation
3115
mutex_enter(&dict_sys->mutex);
3117
/* At this stage there is no guarantee that the tablespace even
3118
exists in the cache. */
3120
if (fil_tablespace_deleted_or_being_deleted_in_mem(space, -1)) {
3122
mutex_exit(&dict_sys->mutex);
3124
return(ULLINT_UNDEFINED);
3127
3109
mtr_start(&mtr);
3129
3111
latch = fil_space_get_latch(space, &flags);
3131
/* This should ensure that the tablespace instance can't be freed
3132
by another thread. However, the tablespace pages can still be freed
3133
from the buffer pool. We need to check for that again. */
3135
3112
zip_size = dict_table_flags_to_zip_size(flags);
3137
3114
mtr_x_lock(latch, &mtr);
3139
mutex_exit(&dict_sys->mutex);
3141
/* At this point it is possible for the tablespace to be deleted and
3142
its pages removed from the buffer pool. We need to check for that
3143
situation. However, the tablespace instance can't be deleted because
3144
our latching above should ensure that. */
3146
if (fil_tablespace_is_being_deleted(space)) {
3150
return(ULLINT_UNDEFINED);
3153
/* From here on even if the user has dropped the tablespace, the
3154
pages _must_ still exist in the buffer pool and the tablespace
3155
instance _must_ be in the file system hash table. */
3157
3116
space_header = fsp_get_space_header(space, zip_size, &mtr);
3159
3118
size = mtr_read_ulint(space_header + FSP_SIZE, MLOG_4BYTES, &mtr);
3349
3308
/* If we get here, the page is in some extent of the segment */
3351
descr_id = mach_read_from_8(descr + XDES_ID);
3352
seg_id = mach_read_from_8(seg_inode + FSEG_ID);
3310
descr_id = mtr_read_dulint(descr + XDES_ID, mtr);
3311
seg_id = mtr_read_dulint(seg_inode + FSEG_ID, mtr);
3354
3313
fprintf(stderr,
3355
3314
"InnoDB: InnoDB is freeing space %lu page %lu,\n"
3356
"InnoDB: which belongs to descr seg %llu\n"
3357
"InnoDB: segment %llu.\n",
3315
"InnoDB: which belongs to descr seg %lu %lu\n"
3316
"InnoDB: segment %lu %lu.\n",
3358
3317
(ulong) space, (ulong) page,
3318
(ulong) ut_dulint_get_high(descr_id),
3319
(ulong) ut_dulint_get_low(descr_id),
3320
(ulong) ut_dulint_get_high(seg_id),
3321
(ulong) ut_dulint_get_low(seg_id));
3362
if (UNIV_UNLIKELY(descr_id != seg_id)) {
3323
if (0 != ut_dulint_cmp(descr_id, seg_id)) {
3363
3324
fputs("InnoDB: Dump of the tablespace extent descriptor: ",
3365
3326
ut_print_buf(stderr, descr, 40);
3371
3332
"InnoDB: Serious error: InnoDB is trying to"
3372
3333
" free space %lu page %lu,\n"
3373
3334
"InnoDB: which does not belong to"
3374
" segment %llu but belongs\n"
3375
"InnoDB: to segment %llu.\n",
3335
" segment %lu %lu but belongs\n"
3336
"InnoDB: to segment %lu %lu.\n",
3376
3337
(ulong) space, (ulong) page,
3338
(ulong) ut_dulint_get_high(descr_id),
3339
(ulong) ut_dulint_get_low(descr_id),
3340
(ulong) ut_dulint_get_high(seg_id),
3341
(ulong) ut_dulint_get_low(seg_id));
3464
3427
descr = xdes_get_descriptor(space, zip_size, page, mtr);
3466
3429
ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
3467
ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
3430
ut_a(0 == ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, mtr),
3431
mtr_read_dulint(seg_inode + FSEG_ID, mtr)));
3468
3432
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
3469
3433
== FSEG_MAGIC_N_VALUE);
3737
3701
space = page_get_space_id(page_align(inode));
3739
seg_id = mach_read_from_8(inode + FSEG_ID);
3703
seg_id = mtr_read_dulint(inode + FSEG_ID, mtr2);
3740
3704
n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
3741
3705
MLOG_4BYTES, mtr2);
3742
3706
flst_validate(inode + FSEG_FREE, mtr2);
3760
3724
ut_a(xdes_get_n_used(descr, &mtr) == 0);
3761
3725
ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
3762
ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
3726
ut_a(!ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, &mtr),
3764
3729
node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
3765
3730
mtr_commit(&mtr);
3783
3748
ut_a(xdes_get_n_used(descr, &mtr) > 0);
3784
3749
ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE);
3785
3750
ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
3786
ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
3751
ut_a(!ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, &mtr),
3788
3754
n_used2 += xdes_get_n_used(descr, &mtr);
3809
3775
ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE);
3810
3776
ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG);
3811
ut_a(mach_read_from_8(descr + XDES_ID) == seg_id);
3777
ut_a(!ut_dulint_cmp(mtr_read_dulint(descr + XDES_ID, &mtr),
3813
3780
node_addr = flst_get_next_addr(descr + XDES_FLST_NODE, &mtr);
3814
3781
mtr_commit(&mtr);
3876
3845
reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
3878
seg_id = mach_read_from_8(inode + FSEG_ID);
3847
d_var = mtr_read_dulint(inode + FSEG_ID, mtr);
3849
seg_id_low = ut_dulint_get_low(d_var);
3850
seg_id_high = ut_dulint_get_high(d_var);
3880
3852
n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
3881
3853
MLOG_4BYTES, mtr);
3885
3857
n_full = flst_get_len(inode + FSEG_FULL, mtr);
3887
3859
fprintf(stderr,
3888
"SEGMENT id %llu space %lu; page %lu;"
3860
"SEGMENT id %lu %lu space %lu; page %lu;"
3889
3861
" res %lu used %lu; full ext %lu\n"
3890
3862
"fragm pages %lu; free extents %lu;"
3891
3863
" not full extents %lu: pages %lu\n",
3864
(ulong) seg_id_high, (ulong) seg_id_low,
3893
3865
(ulong) space, (ulong) page_no,
3894
3866
(ulong) reserved, (ulong) used, (ulong) n_full,
3895
3867
(ulong) n_frag, (ulong) n_free, (ulong) n_not_full,
4092
4064
seg_inode = fsp_seg_inode_page_get_nth_inode(
4093
4065
seg_inode_page, n, zip_size, &mtr);
4094
ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
4066
ut_a(!ut_dulint_is_zero(
4067
mach_read_from_8(seg_inode + FSEG_ID)));
4095
4068
fseg_validate_low(seg_inode, &mtr);
4097
4070
descr_count += flst_get_len(seg_inode + FSEG_FREE,
4137
4110
seg_inode = fsp_seg_inode_page_get_nth_inode(
4138
4111
seg_inode_page, n, zip_size, &mtr);
4139
if (mach_read_from_8(seg_inode + FSEG_ID)) {
4112
if (!ut_dulint_is_zero(
4113
mach_read_from_8(seg_inode + FSEG_ID))) {
4140
4114
fseg_validate_low(seg_inode, &mtr);
4142
4116
descr_count += flst_get_len(
4230
4206
n_free_frag = flst_get_len(header + FSP_FREE_FRAG, &mtr);
4231
4207
n_full_frag = flst_get_len(header + FSP_FULL_FRAG, &mtr);
4233
seg_id = mach_read_from_8(header + FSP_SEG_ID);
4209
d_var = mtr_read_dulint(header + FSP_SEG_ID, &mtr);
4211
seg_id_low = ut_dulint_get_low(d_var);
4212
seg_id_high = ut_dulint_get_high(d_var);
4235
4214
fprintf(stderr,
4236
4215
"FILE SPACE INFO: id %lu\n"
4237
4216
"size %lu, free limit %lu, free extents %lu\n"
4238
4217
"not full frag extents %lu: used pages %lu,"
4239
4218
" full frag extents %lu\n"
4240
"first seg id not used %llu\n",
4219
"first seg id not used %lu %lu\n",
4242
4221
(ulong) size, (ulong) free_limit, (ulong) n_free,
4243
4222
(ulong) n_free_frag, (ulong) frag_n_used, (ulong) n_full_frag,
4223
(ulong) seg_id_high, (ulong) seg_id_low);
4246
4225
mtr_commit(&mtr);
4272
4251
seg_inode = fsp_seg_inode_page_get_nth_inode(
4273
4252
seg_inode_page, n, zip_size, &mtr);
4274
ut_a(mach_read_from_8(seg_inode + FSEG_ID) != 0);
4253
ut_a(!ut_dulint_is_zero(
4254
mach_read_from_8(seg_inode + FSEG_ID)));
4275
4255
fseg_print_low(seg_inode, &mtr);
4309
4289
seg_inode = fsp_seg_inode_page_get_nth_inode(
4310
4290
seg_inode_page, n, zip_size, &mtr);
4311
if (mach_read_from_8(seg_inode + FSEG_ID)) {
4291
if (!ut_dulint_is_zero(
4292
mach_read_from_8(seg_inode + FSEG_ID))) {
4313
4294
fseg_print_low(seg_inode, &mtr);