Description:
If mysqld is run with data directory in a symlinked dir, the creation of a table with DATA DIRECTORY set to the synlink dir will fail.
This occurs as the symlink name is canonicalized with my_realpath and that will "expand" the symlinkname to the physical name.
How to repeat:
ln -s var var7
cd var/master-data
mysqld &
mysql> create table t1 (i int) data directory = "<full_path>/var/master-data/test/"
failed: 25: Can't create symlink './test/t1.MYD' pointing at '/Users/henry/pb/mysql-4.1-maint/66/mysql-4.1.23-pb66/mysql-test/var/master-data/test/t1.MYD' (Error 17)
Or, much more easy:
./mysql-test-run.pl --do-test=symlink --var=var7
<snip>
symlink [ fail ]
Errors are (from /Users/henry/pb/mysql-4.1-maint/66/mysql-4.1.23-pb66/mysql-test/var/log/mysqltest-time) :
mysqltest: At line 126: query 'create table t1 (i int) data directory = "$MYSQL_TEST_DIR/var/master-data/test/"' failed: 25: Can't create symlink './test/t1.MYD' pointing at '/Users/henry/pb/mysql-4.1-maint/66/mysql-4.1.23-pb66/mysql-test/var/master-data/test/t1.MYD' (Error 17)
(the last lines may be the most important ones)
Result from queries before failure can be found in r/symlink.log
Stopping All Servers
Restoring snapshot of databases
Resuming Tests
The above way to test works only in 4.1, in higher versions the --var switch will no create a symlink but pass the path directly to mysqld.
Suggested fix:
===== my_symlink2.c 1.8 vs edited =====
--- 1.8/mysys/my_symlink2.c 2006-11-03 10:43:54 +01:00
+++ edited/my_symlink2.c 2006-11-03 10:43:10 +01:00
@@ -32,7 +32,7 @@ File my_create_with_symlink(const char *
int tmp_errno;
/* Test if we should create a link */
int create_link;
- char abs_linkname[FN_REFLEN];
+ char abs_linkname[FN_REFLEN], abs_filename[FN_REFLEN];
DBUG_ENTER("my_create_with_symlink");
if (my_disable_symlinks)
@@ -45,8 +45,11 @@ File my_create_with_symlink(const char *
else
{
if (linkname)
+ {
my_realpath(abs_linkname, linkname, MYF(0));
- create_link= (linkname && strcmp(abs_linkname,filename));
+ my_realpath(abs_filename, filename, MYF(0));
+ }
+ create_link= (linkname && strcmp(abs_linkname, abs_filename));
}
if (!(MyFlags & MY_DELETE_OLD))
But maybe there is a nicer way to do this that doesn't relies so heavily on realpath. I would suggest some new function like "my_same_path" that traverse the to links from bottom and exits as soon as a different path part is found.