| Bug #15991 | innodb-file-per-table + symlink database + rename = crash | ||
|---|---|---|---|
| Submitted: | 26 Dec 2005 20:53 | Modified: | 2 Feb 2006 5:31 |
| Reporter: | Timothy Smith | ||
| Status: | Closed | ||
| Category: | Server: InnoDB | Severity: | S1 (Critical) |
| Version: | 4.1, 5.0 | OS: | Linux (linux, freebsd) |
| Assigned to: | Bugs System | Target Version: | |
[26 Dec 2005 20:53]
Timothy Smith
[26 Dec 2005 20:55]
Timothy Smith
I forgot to mention, I tested this on FreeBSD 5-STABLE, using MySQL 4.1.16 and 5.0.18 (current BK). I'm sure it will be the same on any Unix OS, and any MySQL version that supports innodb-file-per-table.
[29 Dec 2005 17:57]
Heikki Tuuri
Hi!
I am assigning this bug to Marko.
Fix: make os_file_rename() to return an error, and not assert a failure.
The only important use of the function is in the code below. Test that it handles success
== FALSE correctly.
Regards,
Heikki
/***********************************************************************
Renames a single-table tablespace. The tablespace must be cached in the
tablespace memory cache. */
ibool
fil_rename_tablespace(
/*==================*/
/* out: TRUE if success */
const char* old_name, /* in: old table name in the standard
databasename/tablename format of
InnoDB, or NULL if we do the rename
based on the space id only */
ulint id, /* in: space id */
const char* new_name) /* in: new table name in the standard
databasename/tablename format
of InnoDB */
{
fil_system_t* system = fil_system;
ibool success;
fil_space_t* space;
fil_node_t* node;
ulint count = 0;
char* path;
ibool old_name_was_specified = TRUE;
char* old_path;
ut_a(id != 0);
...
/* Rename the tablespace and the node in the memory cache */
path = fil_make_ibd_name(new_name, FALSE);
success = fil_rename_tablespace_in_mem(space, node, path);
if (success) {
success = os_file_rename(old_path, path);
if (!success) {
/* We have to revert the changes we made
to the tablespace memory cache */
ut_a(fil_rename_tablespace_in_mem(space, node,
old_path));
}
}
[30 Dec 2005 12:21]
Marko Mäkelä
I made os_file_get_last_error() map EXDEV, EISDIR and ENOTDIR to the new error code OS_FILE_PATH_ERROR. The functions os_file_handle_error() and os_file_handle_error_no_exit() will treat these errors similarly to OS_FILE_ALREADY_EXISTS. I tested that RENAME TABLE fails gracefully on EXDEV and ENOTDIR with the patch. The ENOTDIR was triggered by replacing a database subdirectory in the mysql_datadir with a file. EISDIR (tested by replacing an .ibd file with a directory) still causes an assertion failure in fil_node_open_file() on ha_innobase::open(), but RENAME does not seem to care about the type of the .ibd file.
[17 Jan 2006 17:16]
Alexander Ivanov
Fixed in 4.1.17, 5.0.19
[2 Feb 2006 5:31]
Mike Hillyer
Documented in 4.1.17, 5.0.19 changelogs:
<listitem>
<para>
Performing a <literal>RENAME TABLE</literal> on an InnoDB
table when the server is started with the
<literal>--innodb-file-per-table</literal> and the data
directory is a symlink caused a server crash. (Bug #15991)
</para>
</listitem>
