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,
ds_file_t *dstfile = NULL;
datafile_cur_t cursor;
xb_fil_cur_result_t res;
DBUG_ASSERT(datasink->datasink->remove);
const char *dst_path =
(xtrabackup_copy_back || xtrabackup_move_back)?
dst_file_path : trim_dotslash(dst_file_path);
......@@ -1091,6 +1092,7 @@ copy_file(ds_ctxt_t *datasink,
if (ds_write(dstfile, cursor.buf, cursor.buf_read)) {
goto error;
}
DBUG_EXECUTE_IF("copy_file_error", errno=ENOSPC;goto error;);
}
if (res == XB_FIL_CUR_ERROR) {
......@@ -1112,6 +1114,7 @@ copy_file(ds_ctxt_t *datasink,
error:
datafile_close(&cursor);
if (dstfile != NULL) {
datasink->datasink->remove(dstfile->path);
ds_close(dstfile);
}
......@@ -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_errno == EXDEV) {
bool ret;
ret = copy_file(datasink, src_file_path,
dst_file_path, thread_n);
/* Fallback to copy/unlink */
if(!copy_file(datasink, src_file_path,
dst_file_path, thread_n))
return false;
msg(thread_n,"Removing %s", src_file_path);
if (unlink(src_file_path) != 0) {
my_strerror(errbuf, sizeof(errbuf), errno);
msg("Error: unlink %s failed: %s",
msg("Warning: unlink %s failed: %s",
src_file_path,
errbuf);
}
return(ret);
return true;
}
my_strerror(errbuf, sizeof(errbuf), my_errno);
msg("Can not move file %s to %s: %s",
......
......@@ -50,9 +50,15 @@ struct datasink_struct {
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 (*close)(ds_file_t *file);
int (*remove)(const char *path);
void (*deinit)(ds_ctxt_t *ctxt);
};
static inline int dummy_remove(const char *) {
return 0;
}
/* Supported datasink types */
typedef enum {
DS_TYPE_STDOUT,
......
......@@ -56,6 +56,7 @@ datasink_t datasink_archive = {
&archive_open,
&archive_write,
&archive_close,
&dummy_remove,
&archive_deinit
};
......
......@@ -54,6 +54,7 @@ datasink_t datasink_buffer = {
&buffer_open,
&buffer_write,
&buffer_close,
&dummy_remove,
&buffer_deinit
};
......
......@@ -74,6 +74,7 @@ datasink_t datasink_compress = {
&compress_open,
&compress_write,
&compress_close,
&dummy_remove,
&compress_deinit
};
......
......@@ -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 void local_deinit(ds_ctxt_t *ctxt);
static int local_remove(const char *path)
{
return unlink(path);
}
extern "C" {
datasink_t datasink_local = {
&local_init,
&local_open,
&local_write,
&local_close,
&local_remove,
&local_deinit
};
}
......
......@@ -39,6 +39,7 @@ datasink_t datasink_stdout = {
&stdout_open,
&stdout_write,
&stdout_close,
&dummy_remove,
&stdout_deinit
};
......
......@@ -50,6 +50,7 @@ datasink_t datasink_tmpfile = {
&tmpfile_open,
&tmpfile_write,
&tmpfile_close,
&dummy_remove,
&tmpfile_deinit
};
......
......@@ -50,6 +50,7 @@ datasink_t datasink_xbstream = {
&xbstream_open,
&xbstream_write,
&xbstream_close,
&dummy_remove,
&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