summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin/fsp/fsp0fsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innodb_plugin/fsp/fsp0fsp.c')
-rw-r--r--storage/innodb_plugin/fsp/fsp0fsp.c399
1 files changed, 233 insertions, 166 deletions
diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
index fee7fde2e5c..c84cae302a6 100644
--- a/storage/innodb_plugin/fsp/fsp0fsp.c
+++ b/storage/innodb_plugin/fsp/fsp0fsp.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -312,28 +312,38 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page;
then we do not allocate more extents */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr); /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+ __attribute__((nonnull));
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return the allocated page number, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
-ulint
+buf_block_t*
fseg_alloc_free_page_low(
/*=====================*/
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
- ulint hint, /*!< in: hint of which page would be desirable */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr); /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
+ __attribute__((warn_unused_result, nonnull));
#endif /* !UNIV_HOTBACKUP */
/**********************************************************************//**
@@ -701,17 +711,18 @@ list, if not free limit == space size. This adding is necessary to make the
descriptor defined, as they are uninitialized above the free limit.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
-UNIV_INLINE
+UNIV_INLINE __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor_with_space_hdr(
/*===============================*/
- fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
- ulint space, /*!< in: space id */
- ulint offset, /*!< in: page offset;
- if equal to the free limit,
- we try to add new extents to
- the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ fsp_header_t* sp_header, /*!< in/out: space header, x-latched
+ in mtr */
+ ulint space, /*!< in: space id */
+ ulint offset, /*!< in: page offset; if equal
+ to the free limit, we try to
+ add new extents to the space
+ free list */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -719,11 +730,9 @@ xdes_get_descriptor_with_space_hdr(
ulint descr_page_no;
page_t* descr_page;
- ut_ad(mtr);
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
MTR_MEMO_X_LOCK));
- ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
- || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
+ ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
/* Read free limit and space size */
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
@@ -773,7 +782,7 @@ is necessary to make the descriptor defined, as they are uninitialized
above the free limit.
@return pointer to the extent descriptor, NULL if the page does not
exist in the space or if the offset exceeds the free limit */
-static
+static __attribute__((nonnull, warn_unused_result))
xdes_t*
xdes_get_descriptor(
/*================*/
@@ -782,7 +791,7 @@ xdes_get_descriptor(
or 0 for uncompressed pages */
ulint offset, /*!< in: page offset; if equal to the free limit,
we try to add new extents to the space free list */
- mtr_t* mtr) /*!< in: mtr handle */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fsp_header_t* sp_header;
@@ -1160,14 +1169,14 @@ fsp_header_get_tablespace_size(void)
Tries to extend a single-table tablespace so that a page would fit in the
data file.
@return TRUE if success */
-static
+static __attribute__((nonnull, warn_unused_result))
ibool
fsp_try_extend_data_file_with_pages(
/*================================*/
ulint space, /*!< in: space */
ulint page_no, /*!< in: page number */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ibool success;
ulint actual_size;
@@ -1192,7 +1201,7 @@ fsp_try_extend_data_file_with_pages(
/***********************************************************************//**
Tries to extend the last data file of a tablespace if it is auto-extending.
@return FALSE if not auto-extending */
-static
+static __attribute__((nonnull))
ibool
fsp_try_extend_data_file(
/*=====================*/
@@ -1202,8 +1211,8 @@ fsp_try_extend_data_file(
the actual file size rounded down to
megabyte */
ulint space, /*!< in: space */
- fsp_header_t* header, /*!< in: space header */
- mtr_t* mtr) /*!< in: mtr */
+ fsp_header_t* header, /*!< in/out: space header */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint size;
ulint zip_size;
@@ -1339,7 +1348,7 @@ fsp_fill_free_list(
then we do not allocate more extents */
ulint space, /*!< in: space */
fsp_header_t* header, /*!< in/out: space header */
- mtr_t* mtr) /*!< in: mtr */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint limit;
ulint size;
@@ -1538,29 +1547,120 @@ fsp_alloc_free_extent(
}
/**********************************************************************//**
-Allocates a single free page from a space. The page is marked as used.
-@return the page offset, FIL_NULL if no page could be allocated */
+Allocates a single free page from a space. */
+static __attribute__((nonnull))
+void
+fsp_alloc_from_free_frag(
+/*=====================*/
+ fsp_header_t* header, /*!< in/out: tablespace header */
+ xdes_t* descr, /*!< in/out: extent descriptor */
+ ulint bit, /*!< in: slot to allocate in the extent */
+ mtr_t* mtr) /*!< in/out: mini-transaction */
+{
+ ulint frag_n_used;
+
+ ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
+ ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr));
+ xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr);
+
+ /* Update the FRAG_N_USED field */
+ frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
+ mtr);
+ frag_n_used++;
+ mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
+ mtr);
+ if (xdes_is_full(descr, mtr)) {
+ /* The fragment is full: move it to another list */
+ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ xdes_set_state(descr, XDES_FULL_FRAG, mtr);
+
+ flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
+ mtr);
+ mlog_write_ulint(header + FSP_FRAG_N_USED,
+ frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
+ mtr);
+ }
+}
+
+/**********************************************************************//**
+Gets a buffer block for an allocated page.
+
+NOTE: If init_mtr != mtr, the block will only be initialized if it was
+not previously x-latched. It is assumed that the block has been
+x-latched only by mtr, and freed in mtr in that case.
+
+@return block, initialized if init_mtr==mtr
+or rw_lock_x_lock_count(&block->lock) == 1 */
static
-ulint
+buf_block_t*
+fsp_page_create(
+/*============*/
+ ulint space, /*!< in: space id of the allocated page */
+ ulint zip_size, /*!< in: compressed page size in bytes
+ or 0 for uncompressed pages */
+ ulint page_no, /*!< in: page number of the allocated page */
+ mtr_t* mtr, /*!< in: mini-transaction of the allocation */
+ mtr_t* init_mtr) /*!< in: mini-transaction for initializing
+ the page */
+{
+ buf_block_t* block
+ = buf_page_create(space, page_no, zip_size, init_mtr);
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)
+ == rw_lock_own(&block->lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+ /* Mimic buf_page_get(), but avoid the buf_pool->page_hash lookup. */
+ rw_lock_x_lock(&block->lock);
+ mutex_enter(&block->mutex);
+ buf_block_buf_fix_inc(block, __FILE__, __LINE__);
+ mutex_exit(&block->mutex);
+ mtr_memo_push(init_mtr, block, MTR_MEMO_PAGE_X_FIX);
+
+ if (init_mtr == mtr
+ || rw_lock_get_x_lock_count(&block->lock) == 1) {
+
+ /* Initialize the page, unless it was already
+ X-latched in mtr. (In this case, we would want to
+ allocate another page that has not been freed in mtr.) */
+ ut_ad(init_mtr == mtr
+ || !mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+
+ fsp_init_file_page(block, init_mtr);
+ }
+
+ return(block);
+}
+
+/**********************************************************************//**
+Allocates a single free page from a space. The page is marked as used.
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
+static __attribute__((nonnull, warn_unused_result))
+buf_block_t*
fsp_alloc_free_page(
/*================*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint hint, /*!< in: hint of which page would be desirable */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
+ page should be initialized
+ (may be the same as mtr) */
{
fsp_header_t* header;
fil_addr_t first;
xdes_t* descr;
- buf_block_t* block;
ulint free;
- ulint frag_n_used;
ulint page_no;
ulint space_size;
- ibool success;
ut_ad(mtr);
+ ut_ad(init_mtr);
header = fsp_get_space_header(space, zip_size, mtr);
@@ -1587,7 +1687,7 @@ fsp_alloc_free_page(
if (descr == NULL) {
/* No free space left */
- return(FIL_NULL);
+ return(NULL);
}
xdes_set_state(descr, XDES_FREE_FRAG, mtr);
@@ -1632,50 +1732,18 @@ fsp_alloc_free_page(
" space size %lu. Page no %lu.\n",
(ulong) space, (ulong) space_size,
(ulong) page_no);
- return(FIL_NULL);
+ return(NULL);
}
- success = fsp_try_extend_data_file_with_pages(space, page_no,
- header, mtr);
- if (!success) {
+ if (!fsp_try_extend_data_file_with_pages(space, page_no,
+ header, mtr)) {
/* No disk space left */
- return(FIL_NULL);
+ return(NULL);
}
}
- xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
+ fsp_alloc_from_free_frag(header, descr, free, mtr);
- /* Update the FRAG_N_USED field */
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
- mtr);
- frag_n_used++;
- mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
- mtr);
- if (xdes_is_full(descr, mtr)) {
- /* The fragment is full: move it to another list */
- flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
- mtr);
- xdes_set_state(descr, XDES_FULL_FRAG, mtr);
-
- flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
- mtr);
- mlog_write_ulint(header + FSP_FRAG_N_USED,
- frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
- mtr);
- }
-
- /* Initialize the allocated page to the buffer pool, so that it can
- be obtained immediately with buf_page_get without need for a disk
- read. */
-
- buf_page_create(space, page_no, zip_size, mtr);
-
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- /* Prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
-
- return(page_no);
+ return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr));
}
/**********************************************************************//**
@@ -1714,6 +1782,9 @@ fsp_free_page(
fputs("InnoDB: Dump of descriptor: ", stderr);
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
putc('\n', stderr);
+ /* Crash in debug version, so that we get a core dump
+ of this corruption. */
+ ut_ad(0);
if (state == XDES_FREE) {
/* We put here some fault tolerance: if the page
@@ -1732,6 +1803,9 @@ fsp_free_page(
"InnoDB: Dump of descriptor: ", (ulong) page);
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
putc('\n', stderr);
+ /* Crash in debug version, so that we get a core dump
+ of this corruption. */
+ ut_ad(0);
/* We put here some fault tolerance: if the page
is already free, return without doing anything! */
@@ -1766,6 +1840,8 @@ fsp_free_page(
mtr);
fsp_free_extent(space, zip_size, page, mtr);
}
+
+ mtr->n_freed_pages++;
}
/**********************************************************************//**
@@ -1898,7 +1974,6 @@ fsp_alloc_seg_inode_page(
fseg_inode_t* inode;
buf_block_t* block;
page_t* page;
- ulint page_no;
ulint space;
ulint zip_size;
ulint i;
@@ -1909,15 +1984,15 @@ fsp_alloc_seg_inode_page(
zip_size = dict_table_flags_to_zip_size(
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
- page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
+ block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
- if (page_no == FIL_NULL) {
+ if (block == NULL) {
return(FALSE);
}
- block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
block->check_index_page_at_flush = FALSE;
@@ -2322,19 +2397,20 @@ fseg_create_general(
}
if (page == 0) {
- page = fseg_alloc_free_page_low(space, zip_size,
- inode, 0, FSP_UP, mtr);
+ block = fseg_alloc_free_page_low(space, zip_size,
+ inode, 0, FSP_UP, mtr, mtr);
- if (page == FIL_NULL) {
+ if (block == NULL) {
fsp_free_seg_inode(space, zip_size, inode, mtr);
goto funct_exit;
}
- block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
+ ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
+
header = byte_offset + buf_block_get_frame(block);
- mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE,
+ mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
}
@@ -2511,8 +2587,10 @@ fseg_fill_free_list(
Allocates a free extent for the segment: looks first in the free list of the
segment, then tries to allocate from the space free list. NOTE that the extent
returned still resides in the segment free list, it is not yet taken off it!
-@return allocated extent, still placed in the segment free list, NULL
-if could not be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
xdes_t*
fseg_alloc_free_extent(
@@ -2564,22 +2642,30 @@ fseg_alloc_free_extent(
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return the allocated page number, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
static
-ulint
+buf_block_t*
fseg_alloc_free_page_low(
/*=====================*/
ulint space, /*!< in: space */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
- ulint hint, /*!< in: hint of which page would be desirable */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction, /*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
direction they go alphabetically: FSP_DOWN,
FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
{
fsp_header_t* space_header;
ulint space_size;
@@ -2590,7 +2676,6 @@ fseg_alloc_free_page_low(
ulint ret_page; /*!< the allocated page offset, FIL_NULL
if could not be allocated */
xdes_t* ret_descr; /*!< the extent of the allocated page */
- ibool frag_page_allocated = FALSE;
ibool success;
ulint n;
@@ -2612,6 +2697,7 @@ fseg_alloc_free_page_low(
if (descr == NULL) {
/* Hint outside space or too high above free limit: reset
hint */
+ /* The file space header page is always allocated. */
hint = 0;
descr = xdes_get_descriptor(space, zip_size, hint, mtr);
}
@@ -2623,15 +2709,19 @@ fseg_alloc_free_page_low(
mtr), seg_id))
&& (xdes_get_bit(descr, XDES_FREE_BIT,
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
-
+take_hinted_page:
/* 1. We can take the hinted page
=================================*/
ret_descr = descr;
ret_page = hint;
+ /* Skip the check for extending the tablespace. If the
+ page hint were not within the size of the tablespace,
+ we would have got (descr == NULL) above and reset the hint. */
+ goto got_hinted_page;
/*-----------------------------------------------------------*/
- } else if ((xdes_get_state(descr, mtr) == XDES_FREE)
- && ((reserved - used) < reserved / FSEG_FILLFACTOR)
- && (used >= FSEG_FRAG_LIMIT)) {
+ } else if (xdes_get_state(descr, mtr) == XDES_FREE
+ && reserved - used < reserved / FSEG_FILLFACTOR
+ && used >= FSEG_FRAG_LIMIT) {
/* 2. We allocate the free extent from space and can take
=========================================================
@@ -2649,7 +2739,7 @@ fseg_alloc_free_page_low(
/* Try to fill the segment free list */
fseg_fill_free_list(seg_inode, space, zip_size,
hint + FSP_EXTENT_SIZE, mtr);
- ret_page = hint;
+ goto take_hinted_page;
/*-----------------------------------------------------------*/
} else if ((direction != FSP_NO_DIR)
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
@@ -2698,7 +2788,7 @@ fseg_alloc_free_page_low(
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
} else {
ut_error;
- return(FIL_NULL);
+ return(NULL);
}
ret_descr = xdes_lst_get_descriptor(space, zip_size,
@@ -2710,20 +2800,23 @@ fseg_alloc_free_page_low(
} else if (used < FSEG_FRAG_LIMIT) {
/* 6. We allocate an individual page from the space
===================================================*/
- ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
- ret_descr = NULL;
-
- frag_page_allocated = TRUE;
+ buf_block_t* block = fsp_alloc_free_page(
+ space, zip_size, hint, mtr, init_mtr);
- if (ret_page != FIL_NULL) {
+ if (block != NULL) {
/* Put the page in the fragment page array of the
segment */
n = fseg_find_free_frag_page_slot(seg_inode, mtr);
- ut_a(n != FIL_NULL);
+ ut_a(n != ULINT_UNDEFINED);
- fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
- mtr);
+ fseg_set_nth_frag_page_no(
+ seg_inode, n, buf_block_get_page_no(block),
+ mtr);
}
+
+ /* fsp_alloc_free_page() invoked fsp_init_file_page()
+ already. */
+ return(block);
/*-----------------------------------------------------------*/
} else {
/* 7. We allocate a new extent and take its first page
@@ -2741,7 +2834,7 @@ fseg_alloc_free_page_low(
if (ret_page == FIL_NULL) {
/* Page could not be allocated */
- return(FIL_NULL);
+ return(NULL);
}
if (space != 0) {
@@ -2759,38 +2852,22 @@ fseg_alloc_free_page_low(
" the space size %lu. Page no %lu.\n",
(ulong) space, (ulong) space_size,
(ulong) ret_page);
- return(FIL_NULL);
+ return(NULL);
}
success = fsp_try_extend_data_file_with_pages(
space, ret_page, space_header, mtr);
if (!success) {
/* No disk space left */
- return(FIL_NULL);
+ return(NULL);
}
}
}
- if (!frag_page_allocated) {
- /* Initialize the allocated page to buffer pool, so that it
- can be obtained immediately with buf_page_get without need
- for a disk read */
- buf_block_t* block;
- ulint zip_size = dict_table_flags_to_zip_size(
- mach_read_from_4(FSP_SPACE_FLAGS + space_header));
-
- block = buf_page_create(space, ret_page, zip_size, mtr);
- buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
-
- if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
- ret_page, RW_X_LATCH,
- mtr))) {
- ut_error;
- }
-
- /* The prior contents of the page should be ignored */
- fsp_init_file_page(block, mtr);
-
+got_hinted_page:
+ /* ret_descr == NULL if the block was allocated from free_frag
+ (XDES_FREE_FRAG) */
+ if (ret_descr != NULL) {
/* At this point we know the extent and the page offset.
The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */
@@ -2803,20 +2880,28 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr);
}
- return(ret_page);
+ return(fsp_page_create(
+ space, dict_table_flags_to_zip_size(
+ mach_read_from_4(FSP_SPACE_FLAGS
+ + space_header)),
+ ret_page, mtr, init_mtr));
}
/**********************************************************************//**
Allocates a single free page from a segment. This function implements
the intelligent allocation strategy which tries to minimize file space
fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
+@retval NULL if no page could be allocated
+@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
+(init_mtr == mtr, or the page was not previously freed in mtr)
+@retval block (not allocated or initialized) otherwise */
UNIV_INTERN
-ulint
+buf_block_t*
fseg_alloc_free_page_general(
/*=========================*/
fseg_header_t* seg_header,/*!< in/out: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
+ ulint hint, /*!< in: hint of which page would be
+ desirable */
byte direction,/*!< in: if the new page is needed because
of an index page split, and records are
inserted there in order, into which
@@ -2827,15 +2912,18 @@ fseg_alloc_free_page_general(
with fsp_reserve_free_extents, then there
is no need to do the check for this individual
page */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+ mtr_t* mtr, /*!< in/out: mini-transaction handle */
+ mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
+ in which the page should be initialized.
+ If init_mtr!=mtr, but the page is already
+ latched in mtr, do not initialize the page. */
{
fseg_inode_t* inode;
ulint space;
ulint flags;
ulint zip_size;
rw_lock_t* latch;
- ibool success;
- ulint page_no;
+ buf_block_t* block;
ulint n_reserved;
space = page_get_space_id(page_align(seg_header));
@@ -2860,43 +2948,20 @@ fseg_alloc_free_page_general(
inode = fseg_inode_get(seg_header, space, zip_size, mtr);
- if (!has_done_reservation) {
- success = fsp_reserve_free_extents(&n_reserved, space, 2,
- FSP_NORMAL, mtr);
- if (!success) {
- return(FIL_NULL);
- }
+ if (!has_done_reservation
+ && !fsp_reserve_free_extents(&n_reserved, space, 2,
+ FSP_NORMAL, mtr)) {
+ return(NULL);
}
- page_no = fseg_alloc_free_page_low(space, zip_size,
- inode, hint, direction, mtr);
+ block = fseg_alloc_free_page_low(space, zip_size,
+ inode, hint, direction,
+ mtr, init_mtr);
if (!has_done_reservation) {
fil_space_release_free_extents(space, n_reserved);
}
- return(page_no);
-}
-
-/**********************************************************************//**
-Allocates a single free page from a segment. This function implements
-the intelligent allocation strategy which tries to minimize file space
-fragmentation.
-@return allocated page offset, FIL_NULL if no page could be allocated */
-UNIV_INTERN
-ulint
-fseg_alloc_free_page(
-/*=================*/
- fseg_header_t* seg_header,/*!< in: segment header */
- ulint hint, /*!< in: hint of which page would be desirable */
- byte direction,/*!< in: if the new page is needed because
- of an index page split, and records are
- inserted there in order, into which
- direction they go alphabetically: FSP_DOWN,
- FSP_UP, FSP_NO_DIR */
- mtr_t* mtr) /*!< in: mtr handle */
-{
- return(fseg_alloc_free_page_general(seg_header, hint, direction,
- FALSE, mtr));
+ return(block);
}
/**********************************************************************//**
@@ -3412,6 +3477,8 @@ crash:
descr + XDES_FLST_NODE, mtr);
fsp_free_extent(space, zip_size, page, mtr);
}
+
+ mtr->n_freed_pages++;
}
/**********************************************************************//**