[sheepdog] [PATCH 2/2] migrate: create backup before upgrading store

MORITA Kazutaka morita.kazutaka at lab.ntt.co.jp
Thu Oct 4 22:28:51 CEST 2012


Upgrading cluster can break store layout if the upgrade process fails.
To avoid the worst case, this patch creates backup files before
beforehand.

Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 sheep/migrate.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sheep/store.c   |    3 ++
 2 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/sheep/migrate.c b/sheep/migrate.c
index d253ead..69ccd0e 100644
--- a/sheep/migrate.c
+++ b/sheep/migrate.c
@@ -11,8 +11,10 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/time.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <time.h>
 
 #include "sheep_priv.h"
 
@@ -60,6 +62,91 @@ struct sheepdog_config_v1 {
 	uint64_t space;
 };
 
+/* copy file from 'fname' to 'fname.suffix' */
+static int backup_file(char *fname, char *suffix)
+{
+	char dst_file[PATH_MAX];
+	int fd = -1, ret, len;
+	struct stat stbuf;
+	void *buf = NULL;
+
+	snprintf(dst_file, sizeof(dst_file), "%s.%s", fname, suffix);
+
+	fd = open(fname, O_RDONLY);
+	if (fd < 0) {
+		if (errno != ENOENT) {
+			eprintf("failed to open %s, %m\n", fname);
+			ret = -1;
+		} else
+			ret = 0;
+		goto out;
+	}
+
+	ret = stat(fname, &stbuf);
+	if (ret < 0) {
+		eprintf("failed to stat %s, %m\n", fname);
+		goto out;
+	}
+	len = stbuf.st_size;
+
+	buf = xmalloc(len);
+	ret = xread(fd, buf, len);
+	if (ret != len) {
+		eprintf("failed to read %s, %d %m\n", fname, ret);
+		ret = -1;
+		goto out;
+	}
+
+	close(fd);
+
+	fd = open(dst_file, O_CREAT | O_WRONLY | O_DSYNC, 0644);
+	if (fd < 0) {
+		eprintf("failed to create %s, %m\n", dst_file);
+		ret = -1;
+		goto out;
+	}
+
+	ret = xwrite(fd, buf, len);
+	if (ret != len) {
+		eprintf("failed to write to %s, %d %m\n", dst_file, ret);
+		ret = -1;
+	}
+out:
+	if (fd >= 0)
+		close(fd);
+	free(buf);
+
+	return ret;
+}
+
+/* backup config and epoch info */
+static int backup_store(void)
+{
+	char suffix[256];
+	struct timeval tv;
+	struct tm tm;
+	int ret, epoch, le;
+
+	gettimeofday(&tv, NULL);
+	localtime_r(&tv.tv_sec, &tm);
+	strftime(suffix, sizeof(suffix), "%Y-%m-%d_%H%M%S", &tm);
+
+	ret = backup_file(config_path, suffix);
+	if (ret < 0)
+		return ret;
+
+	le = get_latest_epoch();
+	for (epoch = 1; epoch <= le; epoch++) {
+		char path[PATH_MAX];
+		snprintf(path, sizeof(path), "%s%08u", epoch_path, epoch);
+
+		ret = backup_file(path, suffix);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
 
 static int migrate_from_v0_to_v1(void)
 {
@@ -174,6 +261,12 @@ int sd_migrate_store(int from, int to)
 
 	assert(to <= sizeof(migrate));
 
+	ret = backup_store();
+	if (ret != 0) {
+		eprintf("failed to backup the old store\n");
+		return ret;
+	}
+
 	for (ver = from; ver < to; ver++) {
 		ret = migrate[ver]();
 		if (ret < 0)
diff --git a/sheep/store.c b/sheep/store.c
index a194f27..d3d50e1 100644
--- a/sheep/store.c
+++ b/sheep/store.c
@@ -157,6 +157,9 @@ uint32_t get_latest_epoch(void)
 		if (d->d_name == p)
 			continue;
 
+		if (strlen(d->d_name) != 8)
+			continue;
+
 		if (e > epoch)
 			epoch = e;
 	}
-- 
1.7.2.5




More information about the sheepdog mailing list