Commit 93cb0246 authored by Sergei Golubchik's avatar Sergei Golubchik

race-condition safe implementation of mi_delete_table/maria_delete_table

parent 6d503245
......@@ -581,6 +581,9 @@ extern File my_create_with_symlink(const char *linkname, const char *filename,
extern int my_delete_with_symlink(const char *name, myf MyFlags);
extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags);
extern int my_symlink(const char *content, const char *linkname, myf MyFlags);
extern int my_handler_delete_with_symlink(PSI_file_key key, const char *name,
const char *ext, myf sync_dir);
extern size_t my_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags);
extern size_t my_pread(File Filedes,uchar *Buffer,size_t Count,my_off_t offset,
myf MyFlags);
......
......@@ -182,3 +182,31 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags)
DBUG_RETURN(result);
#endif /* HAVE_READLINK */
}
/** delete a - possibly symlinked - table file
This is used to delete a file that is part of a table (e.g. MYI or MYD
file of MyISAM) when dropping a table. A file might be a symlink -
if the table was created with DATA DIRECTORY or INDEX DIRECTORY -
in this case both the symlink and the symlinked file are deleted,
but only if the symlinked file is not in the datadir.
*/
int my_handler_delete_with_symlink(PSI_file_key key, const char *name,
const char *ext, myf sync_dir)
{
char orig[FN_REFLEN], real[FN_REFLEN];
int res= 0;
DBUG_ENTER("my_handler_delete_with_symlink");
fn_format(orig, name, "", ext, MY_UNPACK_FILENAME | MY_APPEND_EXT);
if (my_is_symlink(orig))
{
/*
Delete the symlinked file only if the symlink is not
pointing into datadir.
*/
if (!(my_realpath(real, orig, MYF(0)) || mysys_test_invalid_symlink(real)))
res= mysql_file_delete(key, real, MYF(MY_NOSYMLINKS | MY_WME | sync_dir));
}
DBUG_RETURN(mysql_file_delete(key, orig, MYF(MY_WME | sync_dir)) || res);
}
......@@ -199,7 +199,7 @@ int my_sync_dir_by_file(const char *file_name __attribute__((unused)),
char dir_name[FN_REFLEN];
size_t dir_name_length;
dirname_part(dir_name, file_name, &dir_name_length);
return my_sync_dir(dir_name, my_flags);
return my_sync_dir(dir_name, my_flags & ~MY_NOSYMLINKS);
#else
return 0;
#endif
......
......@@ -84,15 +84,10 @@ int maria_delete_table(const char *name)
int maria_delete_table_files(const char *name, myf sync_dir)
{
char from[FN_REFLEN];
DBUG_ENTER("maria_delete_table_files");
fn_format(from,name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (mysql_file_delete_with_symlink(key_file_kfile, from,
MYF(MY_WME | sync_dir)))
if (my_handler_delete_with_symlink(key_file_kfile, name, MARIA_NAME_IEXT, sync_dir) ||
my_handler_delete_with_symlink(key_file_dfile, name, MARIA_NAME_DEXT, sync_dir))
DBUG_RETURN(my_errno);
fn_format(from,name,"",MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
DBUG_RETURN(mysql_file_delete_with_symlink(key_file_dfile,
from, MYF(MY_WME | sync_dir)) ?
my_errno : 0);
DBUG_RETURN(0);
}
......@@ -22,42 +22,14 @@
int mi_delete_table(const char *name)
{
char from[FN_REFLEN];
DBUG_ENTER("mi_delete_table");
#ifdef EXTRA_DEBUG
check_table_is_closed(name,"delete");
#endif
fn_format(from,name,"",MI_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (my_is_symlink(from) && mysys_test_invalid_symlink(from))
{
/*
Symlink is pointing to file in data directory.
Remove symlink, keep file.
*/
if (mysql_file_delete(mi_key_file_kfile, from, MYF(MY_WME)))
if (my_handler_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, 0) ||
my_handler_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, 0))
DBUG_RETURN(my_errno);
}
else
{
if (mysql_file_delete_with_symlink(mi_key_file_kfile, from, MYF(MY_WME)))
DBUG_RETURN(my_errno);
}
fn_format(from,name,"",MI_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (my_is_symlink(from) && mysys_test_invalid_symlink(from))
{
/*
Symlink is pointing to file in data directory.
Remove symlink, keep file.
*/
if (mysql_file_delete(mi_key_file_dfile, from, MYF(MY_WME)))
DBUG_RETURN(my_errno);
}
else
{
if (mysql_file_delete_with_symlink(mi_key_file_dfile, from, MYF(MY_WME)))
DBUG_RETURN(my_errno);
}
DBUG_RETURN(0);
}
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