Skip to content

Commit 93cb024

Browse files
committed
race-condition safe implementation of mi_delete_table/maria_delete_table
1 parent 6d50324 commit 93cb024

File tree

5 files changed

+38
-40
lines changed

5 files changed

+38
-40
lines changed

include/my_sys.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,9 @@ extern File my_create_with_symlink(const char *linkname, const char *filename,
581581
extern int my_delete_with_symlink(const char *name, myf MyFlags);
582582
extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags);
583583
extern int my_symlink(const char *content, const char *linkname, myf MyFlags);
584+
extern int my_handler_delete_with_symlink(PSI_file_key key, const char *name,
585+
const char *ext, myf sync_dir);
586+
584587
extern size_t my_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags);
585588
extern size_t my_pread(File Filedes,uchar *Buffer,size_t Count,my_off_t offset,
586589
myf MyFlags);

mysys/my_symlink2.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,31 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags)
182182
DBUG_RETURN(result);
183183
#endif /* HAVE_READLINK */
184184
}
185+
186+
/** delete a - possibly symlinked - table file
187+
188+
This is used to delete a file that is part of a table (e.g. MYI or MYD
189+
file of MyISAM) when dropping a table. A file might be a symlink -
190+
if the table was created with DATA DIRECTORY or INDEX DIRECTORY -
191+
in this case both the symlink and the symlinked file are deleted,
192+
but only if the symlinked file is not in the datadir.
193+
*/
194+
int my_handler_delete_with_symlink(PSI_file_key key, const char *name,
195+
const char *ext, myf sync_dir)
196+
{
197+
char orig[FN_REFLEN], real[FN_REFLEN];
198+
int res= 0;
199+
DBUG_ENTER("my_handler_delete_with_symlink");
200+
201+
fn_format(orig, name, "", ext, MY_UNPACK_FILENAME | MY_APPEND_EXT);
202+
if (my_is_symlink(orig))
203+
{
204+
/*
205+
Delete the symlinked file only if the symlink is not
206+
pointing into datadir.
207+
*/
208+
if (!(my_realpath(real, orig, MYF(0)) || mysys_test_invalid_symlink(real)))
209+
res= mysql_file_delete(key, real, MYF(MY_NOSYMLINKS | MY_WME | sync_dir));
210+
}
211+
DBUG_RETURN(mysql_file_delete(key, orig, MYF(MY_WME | sync_dir)) || res);
212+
}

mysys/my_sync.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ int my_sync_dir_by_file(const char *file_name __attribute__((unused)),
199199
char dir_name[FN_REFLEN];
200200
size_t dir_name_length;
201201
dirname_part(dir_name, file_name, &dir_name_length);
202-
return my_sync_dir(dir_name, my_flags);
202+
return my_sync_dir(dir_name, my_flags & ~MY_NOSYMLINKS);
203203
#else
204204
return 0;
205205
#endif

storage/maria/ma_delete_table.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,10 @@ int maria_delete_table(const char *name)
8484

8585
int maria_delete_table_files(const char *name, myf sync_dir)
8686
{
87-
char from[FN_REFLEN];
8887
DBUG_ENTER("maria_delete_table_files");
8988

90-
fn_format(from,name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
91-
if (mysql_file_delete_with_symlink(key_file_kfile, from,
92-
MYF(MY_WME | sync_dir)))
89+
if (my_handler_delete_with_symlink(key_file_kfile, name, MARIA_NAME_IEXT, sync_dir) ||
90+
my_handler_delete_with_symlink(key_file_dfile, name, MARIA_NAME_DEXT, sync_dir))
9391
DBUG_RETURN(my_errno);
94-
fn_format(from,name,"",MARIA_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
95-
DBUG_RETURN(mysql_file_delete_with_symlink(key_file_dfile,
96-
from, MYF(MY_WME | sync_dir)) ?
97-
my_errno : 0);
92+
DBUG_RETURN(0);
9893
}

storage/myisam/mi_delete_table.c

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,42 +22,14 @@
2222

2323
int mi_delete_table(const char *name)
2424
{
25-
char from[FN_REFLEN];
2625
DBUG_ENTER("mi_delete_table");
2726

2827
#ifdef EXTRA_DEBUG
2928
check_table_is_closed(name,"delete");
3029
#endif
3130

32-
fn_format(from,name,"",MI_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
33-
if (my_is_symlink(from) && mysys_test_invalid_symlink(from))
34-
{
35-
/*
36-
Symlink is pointing to file in data directory.
37-
Remove symlink, keep file.
38-
*/
39-
if (mysql_file_delete(mi_key_file_kfile, from, MYF(MY_WME)))
40-
DBUG_RETURN(my_errno);
41-
}
42-
else
43-
{
44-
if (mysql_file_delete_with_symlink(mi_key_file_kfile, from, MYF(MY_WME)))
45-
DBUG_RETURN(my_errno);
46-
}
47-
fn_format(from,name,"",MI_NAME_DEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
48-
if (my_is_symlink(from) && mysys_test_invalid_symlink(from))
49-
{
50-
/*
51-
Symlink is pointing to file in data directory.
52-
Remove symlink, keep file.
53-
*/
54-
if (mysql_file_delete(mi_key_file_dfile, from, MYF(MY_WME)))
55-
DBUG_RETURN(my_errno);
56-
}
57-
else
58-
{
59-
if (mysql_file_delete_with_symlink(mi_key_file_dfile, from, MYF(MY_WME)))
60-
DBUG_RETURN(my_errno);
61-
}
31+
if (my_handler_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, 0) ||
32+
my_handler_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, 0))
33+
DBUG_RETURN(my_errno);
6234
DBUG_RETURN(0);
6335
}

0 commit comments

Comments
 (0)