summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Vaintroub <wlad@mariadb.com>2021-03-31 14:23:56 +0200
committerVladislav Vaintroub <wlad@mariadb.com>2021-03-31 14:23:56 +0200
commit08cb5d848314006111b0c379db6a1fce220579aa (patch)
tree4ec72ec98bd35530d8e21924b511d15f87e588ff
parent35ee4aa4e3bf391b7de78b3e95f3e484394fd1ac (diff)
downloadmariadb-git-08cb5d848314006111b0c379db6a1fce220579aa.tar.gz
MDEV-25221 Do not remove source file, if copy_file() fails in mariabackup --move-back
Remove an incompletely copied destination file.
-rw-r--r--extra/mariabackup/backup_copy.cc14
-rw-r--r--extra/mariabackup/datasink.h6
-rw-r--r--extra/mariabackup/ds_archive.cc1
-rw-r--r--extra/mariabackup/ds_buffer.cc1
-rw-r--r--extra/mariabackup/ds_compress.cc1
-rw-r--r--extra/mariabackup/ds_local.cc6
-rw-r--r--extra/mariabackup/ds_stdout.cc1
-rw-r--r--extra/mariabackup/ds_tmpfile.cc1
-rw-r--r--extra/mariabackup/ds_xbstream.cc1
-rw-r--r--mysql-test/suite/mariabackup/error_during_copyback.result9
-rw-r--r--mysql-test/suite/mariabackup/error_during_copyback.test25
11 files changed, 61 insertions, 5 deletions
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index d3fa3605c21..5637ec3d4d7 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -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",
diff --git a/extra/mariabackup/datasink.h b/extra/mariabackup/datasink.h
index 201bbfd3267..5c82556b9ba 100644
--- a/extra/mariabackup/datasink.h
+++ b/extra/mariabackup/datasink.h
@@ -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,
diff --git a/extra/mariabackup/ds_archive.cc b/extra/mariabackup/ds_archive.cc
index 3826029e120..18f13fbcf3a 100644
--- a/extra/mariabackup/ds_archive.cc
+++ b/extra/mariabackup/ds_archive.cc
@@ -56,6 +56,7 @@ datasink_t datasink_archive = {
&archive_open,
&archive_write,
&archive_close,
+ &dummy_remove,
&archive_deinit
};
diff --git a/extra/mariabackup/ds_buffer.cc b/extra/mariabackup/ds_buffer.cc
index e906edc9e84..9dc040d533b 100644
--- a/extra/mariabackup/ds_buffer.cc
+++ b/extra/mariabackup/ds_buffer.cc
@@ -54,6 +54,7 @@ datasink_t datasink_buffer = {
&buffer_open,
&buffer_write,
&buffer_close,
+ &dummy_remove,
&buffer_deinit
};
diff --git a/extra/mariabackup/ds_compress.cc b/extra/mariabackup/ds_compress.cc
index fb4f3a75bb6..23de4d85116 100644
--- a/extra/mariabackup/ds_compress.cc
+++ b/extra/mariabackup/ds_compress.cc
@@ -74,6 +74,7 @@ datasink_t datasink_compress = {
&compress_open,
&compress_write,
&compress_close,
+ &dummy_remove,
&compress_deinit
};
diff --git a/extra/mariabackup/ds_local.cc b/extra/mariabackup/ds_local.cc
index 0f13ddfe9a9..2f0ad2d8705 100644
--- a/extra/mariabackup/ds_local.cc
+++ b/extra/mariabackup/ds_local.cc
@@ -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
};
}
diff --git a/extra/mariabackup/ds_stdout.cc b/extra/mariabackup/ds_stdout.cc
index 9398482feb9..a4abbe426b6 100644
--- a/extra/mariabackup/ds_stdout.cc
+++ b/extra/mariabackup/ds_stdout.cc
@@ -39,6 +39,7 @@ datasink_t datasink_stdout = {
&stdout_open,
&stdout_write,
&stdout_close,
+ &dummy_remove,
&stdout_deinit
};
diff --git a/extra/mariabackup/ds_tmpfile.cc b/extra/mariabackup/ds_tmpfile.cc
index ddb23bf469d..9eadd36bec0 100644
--- a/extra/mariabackup/ds_tmpfile.cc
+++ b/extra/mariabackup/ds_tmpfile.cc
@@ -50,6 +50,7 @@ datasink_t datasink_tmpfile = {
&tmpfile_open,
&tmpfile_write,
&tmpfile_close,
+ &dummy_remove,
&tmpfile_deinit
};
diff --git a/extra/mariabackup/ds_xbstream.cc b/extra/mariabackup/ds_xbstream.cc
index 105c89d05f7..3b60456f8ed 100644
--- a/extra/mariabackup/ds_xbstream.cc
+++ b/extra/mariabackup/ds_xbstream.cc
@@ -50,6 +50,7 @@ datasink_t datasink_xbstream = {
&xbstream_open,
&xbstream_write,
&xbstream_close,
+ &dummy_remove,
&xbstream_deinit
};
diff --git a/mysql-test/suite/mariabackup/error_during_copyback.result b/mysql-test/suite/mariabackup/error_during_copyback.result
new file mode 100644
index 00000000000..9b12c1135d2
--- /dev/null
+++ b/mysql-test/suite/mariabackup/error_during_copyback.result
@@ -0,0 +1,9 @@
+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;
diff --git a/mysql-test/suite/mariabackup/error_during_copyback.test b/mysql-test/suite/mariabackup/error_during_copyback.test
new file mode 100644
index 00000000000..3ec9fbfc3c3
--- /dev/null
+++ b/mysql-test/suite/mariabackup/error_during_copyback.test
@@ -0,0 +1,25 @@
+--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;
+