summaryrefslogtreecommitdiff
path: root/storage/innobase/fil/fil0fil.c
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@oracle.com>2010-05-24 14:45:24 +0300
committerMarko Mäkelä <marko.makela@oracle.com>2010-05-24 14:45:24 +0300
commit68ce054f5d3a3d78dab52d02fa6b7c5994f66381 (patch)
treeda5ec33bcdf696efacf0c9cdc1028d6cab96426d /storage/innobase/fil/fil0fil.c
parentc2b0ebb55bb3a725c6d64a60539364d5789b2a58 (diff)
downloadmariadb-git-68ce054f5d3a3d78dab52d02fa6b7c5994f66381.tar.gz
Merge a change from mysql-5.1-innodb:
------------------------------------------------------------ revno: 3479 revision-id: marko.makela@oracle.com-20100524110439-fazi70rlmt07tzd9 parent: vasil.dimov@oracle.com-20100520133157-42uk5q3pp0vsinac committer: Marko Mäkelä <marko.makela@oracle.com> branch nick: 5.1-innodb timestamp: Mon 2010-05-24 14:04:39 +0300 message: Bug#53578: assert on invalid page access, in fil_io() Store the max_space_id in the data dictionary header in order to avoid space_id reuse. DICT_HDR_MIX_ID: Renamed to DICT_HDR_MAX_SPACE_ID, DICT_HDR_MIX_ID_LOW. dict_hdr_get_new_id(): Return table_id, index_id, space_id or a subset of them. fil_system_t: Add ibool space_id_reuse_warned. fil_create_new_single_table_tablespace(): Get the space_id from the caller. fil_space_create(): Issue a warning if the fil_system->max_assigned_id is exceeded. fil_assign_new_space_id(): Return TRUE/FALSE and take a pointer to the space_id as a parameter. Make the function public. fil_init(): Initialize all fil_system fields by mem_zalloc(). Remove explicit initializations of certain fields to 0 or NULL.
Diffstat (limited to 'storage/innobase/fil/fil0fil.c')
-rw-r--r--storage/innobase/fil/fil0fil.c117
1 files changed, 59 insertions, 58 deletions
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index 9064710d062..ce788ed0bfc 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
@@ -289,6 +289,10 @@ struct fil_system_struct {
request */
UT_LIST_BASE_NODE_T(fil_space_t) space_list;
/*!< list of all file spaces */
+ ibool space_id_reuse_warned;
+ /* !< TRUE if fil_space_create()
+ has issued a warning about
+ potential space_id reuse */
};
/** The tablespace memory cache. This variable is NULL before the module is
@@ -1210,7 +1214,19 @@ try_again:
space->tablespace_version = fil_system->tablespace_version;
space->mark = FALSE;
- if (purpose == FIL_TABLESPACE && id > fil_system->max_assigned_id) {
+ if (UNIV_LIKELY(purpose == FIL_TABLESPACE)
+ && UNIV_UNLIKELY(id > fil_system->max_assigned_id)) {
+ if (!fil_system->space_id_reuse_warned) {
+ fil_system->space_id_reuse_warned = TRUE;
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Warning: allocated tablespace %lu,"
+ " old maximum was %lu\n",
+ (ulong) id,
+ (ulong) fil_system->max_assigned_id);
+ }
+
fil_system->max_assigned_id = id;
}
@@ -1248,19 +1264,25 @@ try_again:
Assigns a new space id for a new single-table tablespace. This works simply by
incrementing the global counter. If 4 billion id's is not enough, we may need
to recycle id's.
-@return new tablespace id; ULINT_UNDEFINED if could not assign an id */
-static
-ulint
-fil_assign_new_space_id(void)
-/*=========================*/
+@return TRUE if assigned, FALSE if not */
+UNIV_INTERN
+ibool
+fil_assign_new_space_id(
+/*====================*/
+ ulint* space_id) /*!< in/out: space id */
{
- ulint id;
+ ulint id;
+ ibool success;
mutex_enter(&fil_system->mutex);
- fil_system->max_assigned_id++;
+ id = *space_id;
- id = fil_system->max_assigned_id;
+ if (id < fil_system->max_assigned_id) {
+ id = fil_system->max_assigned_id;
+ }
+
+ id++;
if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) {
ut_print_timestamp(stderr);
@@ -1276,7 +1298,11 @@ fil_assign_new_space_id(void)
(ulong) SRV_LOG_SPACE_FIRST_ID);
}
- if (id >= SRV_LOG_SPACE_FIRST_ID) {
+ success = (id < SRV_LOG_SPACE_FIRST_ID);
+
+ if (success) {
+ *space_id = fil_system->max_assigned_id = id;
+ } else {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: You have run out of single-table"
@@ -1286,14 +1312,12 @@ fil_assign_new_space_id(void)
" have to dump all your tables and\n"
"InnoDB: recreate the whole InnoDB installation.\n",
(ulong) id);
- fil_system->max_assigned_id--;
-
- id = ULINT_UNDEFINED;
+ *space_id = ULINT_UNDEFINED;
}
mutex_exit(&fil_system->mutex);
- return(id);
+ return(success);
}
/*******************************************************************//**
@@ -1529,7 +1553,7 @@ fil_init(
ut_a(hash_size > 0);
ut_a(max_n_open > 0);
- fil_system = mem_alloc(sizeof(fil_system_t));
+ fil_system = mem_zalloc(sizeof(fil_system_t));
mutex_create(fil_system_mutex_key,
&fil_system->mutex, SYNC_ANY_LATCH);
@@ -1539,16 +1563,7 @@ fil_init(
UT_LIST_INIT(fil_system->LRU);
- fil_system->n_open = 0;
fil_system->max_n_open = max_n_open;
-
- fil_system->modification_counter = 0;
- fil_system->max_assigned_id = 0;
-
- fil_system->tablespace_version = 0;
-
- UT_LIST_INIT(fil_system->unflushed_spaces);
- UT_LIST_INIT(fil_system->space_list);
}
/*******************************************************************//**
@@ -2133,7 +2148,7 @@ fil_op_log_parse_or_replay(
fil_create_directory_for_tablename(name);
if (fil_create_new_single_table_tablespace(
- &space_id, name, FALSE, flags,
+ space_id, name, FALSE, flags,
FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
ut_error;
}
@@ -2580,9 +2595,7 @@ UNIV_INTERN
ulint
fil_create_new_single_table_tablespace(
/*===================================*/
- ulint* space_id, /*!< in/out: space id; if this is != 0,
- then this is an input parameter,
- otherwise output */
+ ulint space_id, /*!< in: space id */
const char* tablename, /*!< in: the table name in the usual
databasename/tablename format
of InnoDB, or a dir path to a temp
@@ -2602,6 +2615,8 @@ fil_create_new_single_table_tablespace(
ibool success;
char* path;
+ ut_a(space_id > 0);
+ ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
/* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
ROW_FORMAT=COMPACT
@@ -2659,38 +2674,21 @@ fil_create_new_single_table_tablespace(
return(DB_ERROR);
}
- buf2 = ut_malloc(3 * UNIV_PAGE_SIZE);
- /* Align the memory for file i/o if we might have O_DIRECT set */
- page = ut_align(buf2, UNIV_PAGE_SIZE);
-
ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0);
if (!ret) {
- ut_free(buf2);
- os_file_close(file);
- os_file_delete(path);
-
- mem_free(path);
- return(DB_OUT_OF_FILE_SPACE);
- }
-
- if (*space_id == 0) {
- *space_id = fil_assign_new_space_id();
- }
-
- /* printf("Creating tablespace %s id %lu\n", path, *space_id); */
-
- if (*space_id == ULINT_UNDEFINED) {
- ut_free(buf2);
+ err = DB_OUT_OF_FILE_SPACE;
error_exit:
os_file_close(file);
error_exit2:
os_file_delete(path);
mem_free(path);
- return(DB_ERROR);
+ return(err);
}
+ /* printf("Creating tablespace %s id %lu\n", path, space_id); */
+
/* We have to write the space id to the file immediately and flush the
file to disk. This is because in crash recovery we must be aware what
tablespaces exist and what are their space id's, so that we can apply
@@ -2700,10 +2698,14 @@ error_exit2:
with zeros from the call of os_file_set_size(), until a buffer pool
flush would write to it. */
+ buf2 = ut_malloc(3 * UNIV_PAGE_SIZE);
+ /* Align the memory for file i/o if we might have O_DIRECT set */
+ page = ut_align(buf2, UNIV_PAGE_SIZE);
+
memset(page, '\0', UNIV_PAGE_SIZE);
- fsp_header_init_fields(page, *space_id, flags);
- mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, *space_id);
+ fsp_header_init_fields(page, space_id, flags);
+ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
if (!(flags & DICT_TF_ZSSIZE_MASK)) {
buf_flush_init_for_writing(page, NULL, 0);
@@ -2734,6 +2736,7 @@ error_exit2:
" to tablespace ", stderr);
ut_print_filename(stderr, path);
putc('\n', stderr);
+ err = DB_ERROR;
goto error_exit;
}
@@ -2743,22 +2746,20 @@ error_exit2:
fputs("InnoDB: Error: file flush of tablespace ", stderr);
ut_print_filename(stderr, path);
fputs(" failed\n", stderr);
+ err = DB_ERROR;
goto error_exit;
}
os_file_close(file);
- if (*space_id == ULINT_UNDEFINED) {
- goto error_exit2;
- }
-
- success = fil_space_create(path, *space_id, flags, FIL_TABLESPACE);
+ success = fil_space_create(path, space_id, flags, FIL_TABLESPACE);
if (!success) {
+ err = DB_ERROR;
goto error_exit2;
}
- fil_node_create(path, size, *space_id, FALSE);
+ fil_node_create(path, size, space_id, FALSE);
#ifndef UNIV_HOTBACKUP
{
@@ -2769,7 +2770,7 @@ error_exit2:
fil_op_write_log(flags
? MLOG_FILE_CREATE2
: MLOG_FILE_CREATE,
- *space_id,
+ space_id,
is_temp ? MLOG_FILE_FLAG_TEMP : 0,
flags,
tablename, NULL, &mtr);