Commit 08cb5d84 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-25221 Do not remove source file, if copy_file() fails in mariabackup --move-back

Remove an incompletely copied destination file.
parent 35ee4aa4
...@@ -1066,6 +1066,7 @@ copy_file(ds_ctxt_t *datasink, ...@@ -1066,6 +1066,7 @@ copy_file(ds_ctxt_t *datasink,
ds_file_t *dstfile = NULL; ds_file_t *dstfile = NULL;
datafile_cur_t cursor; datafile_cur_t cursor;
xb_fil_cur_result_t res; xb_fil_cur_result_t res;
DBUG_ASSERT(datasink->datasink->remove);
const char *dst_path = const char *dst_path =
(xtrabackup_copy_back || xtrabackup_move_back)? (xtrabackup_copy_back || xtrabackup_move_back)?
dst_file_path : trim_dotslash(dst_file_path); dst_file_path : trim_dotslash(dst_file_path);
...@@ -1091,6 +1092,7 @@ copy_file(ds_ctxt_t *datasink, ...@@ -1091,6 +1092,7 @@ copy_file(ds_ctxt_t *datasink,
if (ds_write(dstfile, cursor.buf, cursor.buf_read)) { if (ds_write(dstfile, cursor.buf, cursor.buf_read)) {
goto error; goto error;
} }
DBUG_EXECUTE_IF("copy_file_error", errno=ENOSPC;goto error;);
} }
if (res == XB_FIL_CUR_ERROR) { if (res == XB_FIL_CUR_ERROR) {
...@@ -1112,6 +1114,7 @@ copy_file(ds_ctxt_t *datasink, ...@@ -1112,6 +1114,7 @@ copy_file(ds_ctxt_t *datasink,
error: error:
datafile_close(&cursor); datafile_close(&cursor);
if (dstfile != NULL) { if (dstfile != NULL) {
datasink->datasink->remove(dstfile->path);
ds_close(dstfile); ds_close(dstfile);
} }
...@@ -1156,17 +1159,18 @@ move_file(ds_ctxt_t *datasink, ...@@ -1156,17 +1159,18 @@ move_file(ds_ctxt_t *datasink,
if (my_rename(src_file_path, dst_file_path_abs, MYF(0)) != 0) { if (my_rename(src_file_path, dst_file_path_abs, MYF(0)) != 0) {
if (my_errno == EXDEV) { if (my_errno == EXDEV) {
bool ret; /* Fallback to copy/unlink */
ret = copy_file(datasink, src_file_path, if(!copy_file(datasink, src_file_path,
dst_file_path, thread_n); dst_file_path, thread_n))
return false;
msg(thread_n,"Removing %s", src_file_path); msg(thread_n,"Removing %s", src_file_path);
if (unlink(src_file_path) != 0) { if (unlink(src_file_path) != 0) {
my_strerror(errbuf, sizeof(errbuf), errno); my_strerror(errbuf, sizeof(errbuf), errno);
msg("Error: unlink %s failed: %s", msg("Warning: unlink %s failed: %s",
src_file_path, src_file_path,
errbuf); errbuf);
} }
return(ret); return true;
} }
my_strerror(errbuf, sizeof(errbuf), my_errno); my_strerror(errbuf, sizeof(errbuf), my_errno);
msg("Can not move file %s to %s: %s", msg("Can not move file %s to %s: %s",
......
...@@ -50,9 +50,15 @@ struct datasink_struct { ...@@ -50,9 +50,15 @@ struct datasink_struct {
ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat); ds_file_t *(*open)(ds_ctxt_t *ctxt, const char *path, MY_STAT *stat);
int (*write)(ds_file_t *file, const unsigned char *buf, size_t len); int (*write)(ds_file_t *file, const unsigned char *buf, size_t len);
int (*close)(ds_file_t *file); int (*close)(ds_file_t *file);
int (*remove)(const char *path);
void (*deinit)(ds_ctxt_t *ctxt); void (*deinit)(ds_ctxt_t *ctxt);
}; };
static inline int dummy_remove(const char *) {
return 0;
}
/* Supported datasink types */ /* Supported datasink types */
typedef enum { typedef enum {
DS_TYPE_STDOUT, DS_TYPE_STDOUT,
......
...@@ -56,6 +56,7 @@ datasink_t datasink_archive = { ...@@ -56,6 +56,7 @@ datasink_t datasink_archive = {
&archive_open, &archive_open,
&archive_write, &archive_write,
&archive_close, &archive_close,
&dummy_remove,
&archive_deinit &archive_deinit
}; };
......
...@@ -54,6 +54,7 @@ datasink_t datasink_buffer = { ...@@ -54,6 +54,7 @@ datasink_t datasink_buffer = {
&buffer_open, &buffer_open,
&buffer_write, &buffer_write,
&buffer_close, &buffer_close,
&dummy_remove,
&buffer_deinit &buffer_deinit
}; };
......
...@@ -74,6 +74,7 @@ datasink_t datasink_compress = { ...@@ -74,6 +74,7 @@ datasink_t datasink_compress = {
&compress_open, &compress_open,
&compress_write, &compress_write,
&compress_close, &compress_close,
&dummy_remove,
&compress_deinit &compress_deinit
}; };
......
...@@ -44,12 +44,18 @@ static int local_write(ds_file_t *file, const uchar *buf, size_t len); ...@@ -44,12 +44,18 @@ static int local_write(ds_file_t *file, const uchar *buf, size_t len);
static int local_close(ds_file_t *file); static int local_close(ds_file_t *file);
static void local_deinit(ds_ctxt_t *ctxt); static void local_deinit(ds_ctxt_t *ctxt);
static int local_remove(const char *path)
{
return unlink(path);
}
extern "C" { extern "C" {
datasink_t datasink_local = { datasink_t datasink_local = {
&local_init, &local_init,
&local_open, &local_open,
&local_write, &local_write,
&local_close, &local_close,
&local_remove,
&local_deinit &local_deinit
}; };
} }
......
...@@ -39,6 +39,7 @@ datasink_t datasink_stdout = { ...@@ -39,6 +39,7 @@ datasink_t datasink_stdout = {
&stdout_open, &stdout_open,
&stdout_write, &stdout_write,
&stdout_close, &stdout_close,
&dummy_remove,
&stdout_deinit &stdout_deinit
}; };
......
...@@ -50,6 +50,7 @@ datasink_t datasink_tmpfile = { ...@@ -50,6 +50,7 @@ datasink_t datasink_tmpfile = {
&tmpfile_open, &tmpfile_open,
&tmpfile_write, &tmpfile_write,
&tmpfile_close, &tmpfile_close,
&dummy_remove,
&tmpfile_deinit &tmpfile_deinit
}; };
......
...@@ -50,6 +50,7 @@ datasink_t datasink_xbstream = { ...@@ -50,6 +50,7 @@ datasink_t datasink_xbstream = {
&xbstream_open, &xbstream_open,
&xbstream_write, &xbstream_write,
&xbstream_close, &xbstream_close,
&dummy_remove,
&xbstream_deinit &xbstream_deinit
}; };
......
CREATE TABLE t(i INT) ENGINE INNODB;
INSERT INTO t VALUES(1);
# xtrabackup backup
# xtrabackup prepare
# restart server
SELECT * FROM t;
i
1
DROP TABLE t;
--source include/have_debug.inc
CREATE TABLE t(i INT) ENGINE INNODB;
INSERT INTO t VALUES(1);
echo # xtrabackup backup;
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
--disable_result_log
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
--enable_result_log
echo # xtrabackup prepare;
--disable_result_log
exec $XTRABACKUP --prepare --target-dir=$targetdir;
let $_datadir= `SELECT @@datadir`;
--source include/shutdown_mysqld.inc
rmdir $_datadir;
error 1;
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir --dbug=+d,copy_file_error;
list_files $_datadir;
rmdir $_datadir;
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir=$_datadir --target-dir=$targetdir;
echo # restart server;
--source include/start_mysqld.inc
SELECT * FROM t;
DROP TABLE t;
rmdir $targetdir;
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