Bug #15991 innodb-file-per-table + symlink database + rename = crash
Submitted: 26 Dec 2005 19:53 Modified: 18 Jun 2010 22:49
Reporter: Timothy Smith Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S1 (Critical)
Version:4.1, 5.0 OS:Linux (linux, freebsd)
Assigned to: CPU Architecture:Any

[26 Dec 2005 19:53] Timothy Smith
Description:
A "RENAME TABLE symlinked_db.innodb_table TO other_filesystem_db.innodb_table" will crash the server.  It gives this in the error log:

051227 08:33:24  mysqld started
051227  8:33:24  InnoDB: Started; log sequence number 0 22580259
051227  8:33:24 [Note] /usr/home/tim/m/50/m/bin/mysqld: ready for connections.
Version: '5.0.18-debug-log'  socket: 'mysql.sock'  port: 33500  Source distribut
ion
051227  8:33:40  InnoDB: Operating system error number 18 in a file operation.
InnoDB: Error number 18 means 'Cross-device link'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/mysql/en/Operating_System_error_codes.html
InnoDB: File name ./innotest/foobar.ibd
InnoDB: File operation call: 'rename'.
InnoDB: Cannot continue operation.
051227 08:33:40  mysqld restarted
051227  8:33:40  InnoDB: Started; log sequence number 0 22580259
051227  8:33:40 [Note] Recovering after a crash using binlog

How to repeat:
Create a directory on a filesystem other than where your main data directory is.  E.g., /tmp/innotest.

Link that into your data directory:

cd /path/to/mysql-data
ln -s /tmp/innotest .

Start mysqld with the --innodb-file-per-table option.

Then run:

mysql innotest
create table t (a int) engine=innodb;
rename table t to test.this_will_break;

Suggested fix:
I'm not sure.  It's fine that the RENAME command fails.  But it should not cause the server to quit.
[26 Dec 2005 19: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 16: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 11: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 16:16] Alexander Ivanov
Fixed in 4.1.17, 5.0.19
[2 Feb 2006 4: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>
[5 May 2010 15:04] Bugs System
Pushed into 5.1.47 (revid:joro@sun.com-20100505145753-ivlt4hclbrjy8eye) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[6 May 2010 1:46] Paul DuBois
Push resulted from incorporation of InnoDB tree. No changes pertinent to this bug. Re-closing.
[28 May 2010 6:00] Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100524190136-egaq7e8zgkwb9aqi) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (pib:16)
[28 May 2010 6:29] Bugs System
Pushed into 6.0.14-alpha (revid:alik@sun.com-20100524190941-nuudpx60if25wsvx) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[28 May 2010 6:56] Bugs System
Pushed into 5.5.5-m3 (revid:alik@sun.com-20100524185725-c8k5q7v60i5nix3t) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[29 May 2010 15:07] Paul DuBois
Push resulted from incorporation of InnoDB tree. No changes pertinent to this bug.
Re-closing.
[17 Jun 2010 12:03] Bugs System
Pushed into 5.1.47-ndb-7.0.16 (revid:martin.skold@mysql.com-20100617114014-bva0dy24yyd67697) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[17 Jun 2010 12:45] Bugs System
Pushed into 5.1.47-ndb-6.2.19 (revid:martin.skold@mysql.com-20100617115448-idrbic6gbki37h1c) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)
[17 Jun 2010 13:30] Bugs System
Pushed into 5.1.47-ndb-6.3.35 (revid:martin.skold@mysql.com-20100617114611-61aqbb52j752y116) (version source revid:vasil.dimov@oracle.com-20100331130613-8ja7n0vh36a80457) (merge vers: 5.1.46) (pib:16)