Commit 8e198589 authored by unknown's avatar unknown

Bug #13116225 LIVE DOWNGRADE CRASHES WITH INNODB_PAGE_SIZE=4K

This bug ensures that a live downgrade from an InnoDB 5.6 with WL5756 and
a database created with innodb-page-size=8k or 4k will make a version 5.5
installation politely refuse to start. Instead of crashing or giving some
indication about a corrupted database, it will indicate the page size
difference. 

This patch takes only that part of the Wl5756 patch that is needed to
protect against opening a tablespace that is stamped with a different
page size.

It also contains the change in dict_index_find_on_id_low() just in case
a database with another page size is created by recompiling a pre-WL5756
InnoDB.
parent 9b42c9b9
......@@ -911,6 +911,11 @@ dict_index_find_on_id_low(
dict_table_t* table;
dict_index_t* index;
/* This can happen if the system tablespace is the wrong page size */
if (dict_sys == NULL) {
return(NULL);
}
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
while (table) {
......
......@@ -1803,36 +1803,44 @@ fil_write_flushed_lsn_to_data_files(
}
/*******************************************************************//**
Reads the flushed lsn and arch no fields from a data file at database
startup. */
Reads the flushed lsn, arch no, and tablespace flag fields from a data
file at database startup. */
UNIV_INTERN
void
fil_read_flushed_lsn_and_arch_log_no(
/*=================================*/
fil_read_first_page(
/*================*/
os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< in/out: */
ulint* max_arch_log_no, /*!< in/out: */
ulint* min_arch_log_no, /*!< out: min of archived
log numbers in data files */
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
ib_uint64_t* max_flushed_lsn) /*!< in/out: */
ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
ib_uint64_t* max_flushed_lsn) /*!< out: max of flushed
lsn values in data files */
{
byte* buf;
byte* buf2;
page_t* page;
ib_uint64_t flushed_lsn;
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
buf = ut_malloc(2 * UNIV_PAGE_SIZE);
/* Align the memory for a possible read from a raw device */
buf = ut_align(buf2, UNIV_PAGE_SIZE);
page = ut_align(buf, UNIV_PAGE_SIZE);
os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
os_file_read(data_file, page, 0, 0, UNIV_PAGE_SIZE);
flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
*flags = mach_read_from_4(page +
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS);
ut_free(buf2);
flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
ut_free(buf);
if (!one_read_already) {
*min_flushed_lsn = flushed_lsn;
......
/*****************************************************************************
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, 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
*****************************************************************************/
......@@ -50,67 +50,6 @@ Created 11/29/1995 Heikki Tuuri
#include "dict0mem.h"
#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
within a file page */
/* The data structures in files are defined just as byte strings in C */
typedef byte fsp_header_t;
typedef byte xdes_t;
/* SPACE HEADER
============
File space header data structure: this data structure is contained in the
first page of a space. The space for this header is reserved in every extent
descriptor page, but used only in the first. */
/*-------------------------------------*/
#define FSP_SPACE_ID 0 /* space id */
#define FSP_NOT_USED 4 /* this field contained a value up to
which we know that the modifications
in the database have been flushed to
the file space; not used now */
#define FSP_SIZE 8 /* Current size of the space in
pages */
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
free list has not been initialized:
the pages >= this limit are, by
definition, free; note that in a
single-table tablespace where size
< 64 pages, this number is 64, i.e.,
we have initialized the space
about the first extent, but have not
physically allocted those pages to the
file */
#define FSP_SPACE_FLAGS 16 /* table->flags & ~DICT_TF_COMPACT */
#define FSP_FRAG_N_USED 20 /* number of used pages in the
FSP_FREE_FRAG list */
#define FSP_FREE 24 /* list of free extents */
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
/* list of partially free extents not
belonging to any segment */
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
/* list of full extents not belonging
to any segment */
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
/* 8 bytes which give the first unused
segment id */
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where all the segment inode
slots are reserved */
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where not all the segment
header slots are reserved */
/*-------------------------------------*/
/* File space header size */
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
#define FSP_FREE_ADD 4 /* this many free extents are added
to the free list from above
FSP_FREE_LIMIT at a time */
/* FILE SEGMENT INODE
==================
......
......@@ -328,18 +328,23 @@ Reads the flushed lsn and arch no fields from a data file at database
startup. */
UNIV_INTERN
void
fil_read_flushed_lsn_and_arch_log_no(
/*=================================*/
fil_read_first_page(
/*================*/
os_file_t data_file, /*!< in: open data file */
ibool one_read_already, /*!< in: TRUE if min and max
parameters below already
contain sensible data */
ulint* flags, /*!< out: tablespace flags */
#ifdef UNIV_LOG_ARCHIVE
ulint* min_arch_log_no, /*!< in/out: */
ulint* max_arch_log_no, /*!< in/out: */
ulint* min_arch_log_no, /*!< out: min of archived
log numbers in data files */
ulint* max_arch_log_no, /*!< out: max of archived
log numbers in data files */
#endif /* UNIV_LOG_ARCHIVE */
ib_uint64_t* min_flushed_lsn, /*!< in/out: */
ib_uint64_t* max_flushed_lsn); /*!< in/out: */
ib_uint64_t* min_flushed_lsn, /*!< out: min of flushed
lsn values in data files */
ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed
lsn values in data files */
/*******************************************************************//**
Increments the count of pending insert buffer page merges, if space is not
being deleted.
......
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, 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
*****************************************************************************/
......@@ -34,6 +34,90 @@ Created 12/18/1995 Heikki Tuuri
#include "page0types.h"
#include "fsp0types.h"
/* @defgroup fsp_flags InnoDB Tablespace Flag Constants @{ */
/** Number of flag bits used to indicate the tablespace page size */
#define FSP_FLAGS_WIDTH_PAGE_SSIZE 4
/** Zero relative shift position of the PAGE_SSIZE field */
#define FSP_FLAGS_POS_PAGE_SSIZE 6
/** Bit mask of the PAGE_SSIZE field */
#define FSP_FLAGS_MASK_PAGE_SSIZE \
((~(~0 << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
/** Return the value of the PAGE_SSIZE field */
#define FSP_FLAGS_GET_PAGE_SSIZE(flags) \
((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \
>> FSP_FLAGS_POS_PAGE_SSIZE)
/* @} */
/* @defgroup Tablespace Header Constants (moved from fsp0fsp.c) @{ */
/** Offset of the space header within a file page */
#define FSP_HEADER_OFFSET FIL_PAGE_DATA
/* The data structures in files are defined just as byte strings in C */
typedef byte fsp_header_t;
typedef byte xdes_t;
/* SPACE HEADER
============
File space header data structure: this data structure is contained in the
first page of a space. The space for this header is reserved in every extent
descriptor page, but used only in the first. */
/*-------------------------------------*/
#define FSP_SPACE_ID 0 /* space id */
#define FSP_NOT_USED 4 /* this field contained a value up to
which we know that the modifications
in the database have been flushed to
the file space; not used now */
#define FSP_SIZE 8 /* Current size of the space in
pages */
#define FSP_FREE_LIMIT 12 /* Minimum page number for which the
free list has not been initialized:
the pages >= this limit are, by
definition, free; note that in a
single-table tablespace where size
< 64 pages, this number is 64, i.e.,
we have initialized the space
about the first extent, but have not
physically allocted those pages to the
file */
#define FSP_SPACE_FLAGS 16 /* fsp_space_t.flags, similar to
dict_table_t::flags */
#define FSP_FRAG_N_USED 20 /* number of used pages in the
FSP_FREE_FRAG list */
#define FSP_FREE 24 /* list of free extents */
#define FSP_FREE_FRAG (24 + FLST_BASE_NODE_SIZE)
/* list of partially free extents not
belonging to any segment */
#define FSP_FULL_FRAG (24 + 2 * FLST_BASE_NODE_SIZE)
/* list of full extents not belonging
to any segment */
#define FSP_SEG_ID (24 + 3 * FLST_BASE_NODE_SIZE)
/* 8 bytes which give the first unused
segment id */
#define FSP_SEG_INODES_FULL (32 + 3 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where all the segment inode
slots are reserved */
#define FSP_SEG_INODES_FREE (32 + 4 * FLST_BASE_NODE_SIZE)
/* list of pages containing segment
headers, where not all the segment
header slots are reserved */
/*-------------------------------------*/
/* File space header size */
#define FSP_HEADER_SIZE (32 + 5 * FLST_BASE_NODE_SIZE)
#define FSP_FREE_ADD 4 /* this many free extents are added
to the free list from above
FSP_FREE_LIMIT at a time */
/* @} */
/* @} */
/**********************************************************************//**
Initializes the file space system. */
UNIV_INTERN
......@@ -352,6 +436,18 @@ fseg_print(
mtr_t* mtr); /*!< in: mtr */
#endif /* UNIV_BTR_PRINT */
/********************************************************************//**
Extract the page size from tablespace flags.
This feature, storing the page_ssize into the tablespace flags, is added
to InnoDB 5.6.4. This is here only to protect against a crash if a newer
database is opened with this code branch.
@return page size of the tablespace in bytes */
UNIV_INLINE
ulint
fsp_flags_get_page_size(
/*====================*/
ulint flags); /*!< in: tablespace flags */
#ifndef UNIV_NONINL
#include "fsp0fsp.ic"
#endif
......
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2011, 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
*****************************************************************************/
......@@ -43,3 +43,31 @@ fsp_descr_page(
return(UNIV_UNLIKELY((page_no & (zip_size - 1)) == FSP_XDES_OFFSET));
}
/********************************************************************//**
Extract the page size from tablespace flags.
This feature, storing the page_ssize into the tablespace flags, is added
to InnoDB 5.6.4. This is here only to protect against a crash if a newer
database is opened with this code branch.
@return page size of the tablespace in bytes */
UNIV_INLINE
ulint
fsp_flags_get_page_size(
/*====================*/
ulint flags) /*!< in: tablespace flags */
{
ulint page_size = 0;
ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
/* Convert from a 'log2 minus 9' to a page size in bytes. */
if (UNIV_UNLIKELY(ssize)) {
page_size = (512 << ssize);
ut_ad(page_size <= UNIV_PAGE_SIZE);
} else {
/* If the page size was not stored, then it is the
original 16k. */
page_size = UNIV_PAGE_SIZE;
}
return(page_size);
}
......@@ -733,6 +733,7 @@ open_or_create_data_files(
ibool one_created = FALSE;
ulint size;
ulint size_high;
ulint flags;
ulint rounded_size_pages;
char name[10000];
......@@ -914,12 +915,31 @@ open_or_create_data_files(
return(DB_ERROR);
}
skip_size_check:
fil_read_flushed_lsn_and_arch_log_no(
files[i], one_opened,
fil_read_first_page(
files[i], one_opened, &flags,
#ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn);
if (UNIV_PAGE_SIZE
!= fsp_flags_get_page_size(flags)) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: data file %s"
" uses page size %lu,\n",
name,
fsp_flags_get_page_size(flags));
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: but the only supported"
" page size in this release is=%lu\n",
(ulong) UNIV_PAGE_SIZE);
return(DB_ERROR);
}
one_opened = TRUE;
} else {
/* We created the data file and now write it full of
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment