[sheepdog] [PATCH 1/2] sheep: check sheepdog data layout version before starting up

MORITA Kazutaka morita.kazutaka at lab.ntt.co.jp
Fri Sep 28 19:37:03 CEST 2012


This avoids data store corruption when there is no compatibility
between the running sheep and the existing data.  The format version
of 0.4.0 is 0, and one of 0.5.x is 1.

Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 sheep/Makefile.am  |    2 +-
 sheep/config.c     |  174 ++++++++++++++++++++++++++++++++++
 sheep/sheep_priv.h |    1 +
 sheep/store.c      |  263 ----------------------------------------------------
 4 files changed, 176 insertions(+), 264 deletions(-)
 create mode 100644 sheep/config.c

diff --git a/sheep/Makefile.am b/sheep/Makefile.am
index ed927d8..875542c 100644
--- a/sheep/Makefile.am
+++ b/sheep/Makefile.am
@@ -27,7 +27,7 @@ sbin_PROGRAMS		= sheep
 sheep_SOURCES		= sheep.c group.c request.c gateway.c store.c vdi.c work.c \
 			  journal.c ops.c recovery.c cluster/local.c \
 			  object_cache.c object_list_cache.c sockfd_cache.c \
-			  plain_store.c
+			  plain_store.c config.c
 
 if BUILD_COROSYNC
 sheep_SOURCES		+= cluster/corosync.c
diff --git a/sheep/config.c b/sheep/config.c
new file mode 100644
index 0000000..8a9115c
--- /dev/null
+++ b/sheep/config.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "sheep_priv.h"
+
+#define SD_FORMAT_VERSION 0x0001
+
+static struct sheepdog_config {
+	uint64_t ctime;
+	uint16_t flags;
+	uint8_t copies;
+	uint8_t store[STORE_LEN];
+	uint8_t __pad[3];
+	uint16_t version;
+	uint64_t space;
+} config;
+
+static char *config_path;
+
+#define CONFIG_PATH "/config"
+
+static int write_config(void)
+{
+	int fd, ret;
+	void *jd;
+
+	fd = open(config_path, O_DSYNC | O_WRONLY | O_CREAT, def_fmode);
+	if (fd < 0) {
+		eprintf("failed to open config file, %m\n");
+		return SD_RES_EIO;
+	}
+
+	jd = jrnl_begin(&config, sizeof(config), 0, config_path, jrnl_path);
+	if (!jd) {
+		eprintf("failed to write config data to journal, %m\n");
+		ret = SD_RES_EIO;
+		goto out;
+	}
+	ret = xwrite(fd, &config, sizeof(config));
+	if (ret != sizeof(config)) {
+		eprintf("failed to write config data, %m\n");
+		ret = SD_RES_EIO;
+	} else
+		ret = SD_RES_SUCCESS;
+
+	jrnl_end(jd);
+out:
+	close(fd);
+
+	return ret;
+}
+
+int init_config_path(const char *base_path)
+{
+	int fd, ret;
+
+	config_path = zalloc(strlen(base_path) + strlen(CONFIG_PATH) + 1);
+	sprintf(config_path, "%s" CONFIG_PATH, base_path);
+
+	fd = open(config_path, O_RDONLY);
+	if (fd < 0) {
+		if (errno != ENOENT) {
+			eprintf("failed to read config file, %m\n");
+			return -1;
+		}
+
+		config.version = SD_FORMAT_VERSION;
+		if (write_config() != SD_RES_SUCCESS)
+			return -1;
+
+		return 0;
+	}
+
+	ret = xread(fd, &config, sizeof(config));
+	if (ret < 0) {
+		eprintf("failed to read config file, %m\n");
+		goto out;
+	}
+
+	if (config.version != SD_FORMAT_VERSION) {
+		eprintf("This sheep version is not compatible with the existing "
+			"data layout, %d\n", config.version);
+		ret = -1;
+		goto out;
+	}
+	ret = 0;
+out:
+	close(fd);
+
+	return ret;
+}
+
+int set_cluster_ctime(uint64_t ct)
+{
+	config.ctime = ct;
+
+	return write_config();
+}
+
+uint64_t get_cluster_ctime(void)
+{
+	return config.ctime;
+}
+
+int set_cluster_copies(uint8_t copies)
+{
+	config.copies = copies;
+
+	return write_config();
+}
+
+int get_cluster_copies(uint8_t *copies)
+{
+	*copies = config.copies;
+
+	return SD_RES_SUCCESS;
+}
+
+int set_cluster_flags(uint16_t flags)
+{
+	config.flags = flags;
+
+	return write_config();
+}
+
+int get_cluster_flags(uint16_t *flags)
+{
+	*flags = config.flags;
+
+	return SD_RES_SUCCESS;
+}
+
+int set_cluster_store(const char *name)
+{
+	memset(config.store, 0, sizeof(config.store));
+	strcpy((char *)config.store, name);
+
+	return write_config();
+}
+
+int get_cluster_store(char *buf)
+{
+	memcpy(buf, config.store, sizeof(config.store));
+
+	return SD_RES_SUCCESS;
+}
+
+int set_cluster_space(uint64_t space)
+{
+	config.space = space;
+
+	return write_config();
+}
+
+int get_cluster_space(uint64_t *space)
+{
+	*space = config.space;
+
+	return SD_RES_SUCCESS;
+}
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index fcc4278..f80c5f8 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -283,6 +283,7 @@ int get_max_nr_copies_from(struct sd_node *entries, int nr);
 int epoch_log_read(uint32_t epoch, struct sd_node *nodes, int len);
 int epoch_log_read_remote(uint32_t epoch, struct sd_node *nodes, int len);
 uint32_t get_latest_epoch(void);
+int init_config_path(const char *base_path);
 int set_cluster_ctime(uint64_t ctime);
 uint64_t get_cluster_ctime(void);
 int get_obj_list(const struct sd_list_req *, struct sd_list_rsp *, void *);
diff --git a/sheep/store.c b/sheep/store.c
index 7f9ea29..a194f27 100644
--- a/sheep/store.c
+++ b/sheep/store.c
@@ -28,20 +28,10 @@
 #include "util.h"
 #include "farm/farm.h"
 
-struct sheepdog_config {
-	uint64_t ctime;
-	uint16_t flags;
-	uint8_t copies;
-	uint8_t store[STORE_LEN];
-	uint8_t __pad[5];
-	uint64_t space;
-};
-
 char *obj_path;
 char *mnt_path;
 char *jrnl_path;
 char *epoch_path;
-static char *config_path;
 
 mode_t def_dmode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP;
 mode_t def_fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
@@ -175,52 +165,6 @@ uint32_t get_latest_epoch(void)
 	return epoch;
 }
 
-int set_cluster_ctime(uint64_t ct)
-{
-	int fd, ret;
-	void *jd;
-
-	fd = open(config_path, O_DSYNC | O_WRONLY);
-	if (fd < 0)
-		return SD_RES_EIO;
-
-	jd = jrnl_begin(&ct, sizeof(ct),
-			offsetof(struct sheepdog_config, ctime),
-			config_path, jrnl_path);
-	if (!jd) {
-		ret = SD_RES_EIO;
-		goto err;
-	}
-	ret = xpwrite(fd, &ct, sizeof(ct), offsetof(struct sheepdog_config, ctime));
-	if (ret != sizeof(ct))
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-
-	jrnl_end(jd);
-err:
-	close(fd);
-	return ret;
-}
-
-uint64_t get_cluster_ctime(void)
-{
-	int fd, ret;
-	uint64_t ct;
-
-	fd = open(config_path, O_RDONLY);
-	if (fd < 0)
-		return 0;
-
-	ret = xpread(fd, &ct, sizeof(ct),
-		     offsetof(struct sheepdog_config, ctime));
-	close(fd);
-
-	if (ret != sizeof(ct))
-		return 0;
-	return ct;
-}
-
 static int init_path(const char *d, int *new)
 {
 	int ret, retry = 0;
@@ -388,18 +332,6 @@ static int init_jrnl_path(const char *base_path)
 	return 0;
 }
 
-#define CONFIG_PATH "/config"
-
-static int init_config_path(const char *base_path)
-{
-	config_path = zalloc(strlen(base_path) + strlen(CONFIG_PATH) + 1);
-	sprintf(config_path, "%s" CONFIG_PATH, base_path);
-
-	mknod(config_path, def_fmode, S_IFREG);
-
-	return 0;
-}
-
 static int init_store_driver(void)
 {
 	char driver_name[STORE_LEN], *p;
@@ -613,198 +545,3 @@ int remove_object(uint64_t oid, int copies)
 
 	return ret;
 }
-
-int set_cluster_copies(uint8_t copies)
-{
-	int fd, ret;
-	void *jd;
-
-	fd = open(config_path, O_DSYNC | O_WRONLY);
-	if (fd < 0)
-		return SD_RES_EIO;
-
-	jd = jrnl_begin(&copies, sizeof(copies),
-			offsetof(struct sheepdog_config, copies),
-			config_path, jrnl_path);
-	if (!jd) {
-		ret = SD_RES_EIO;
-		goto err;
-	}
-
-	ret = xpwrite(fd, &copies, sizeof(copies), offsetof(struct sheepdog_config, copies));
-	if (ret != sizeof(copies))
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-	jrnl_end(jd);
-err:
-	close(fd);
-	return ret;
-}
-
-int get_cluster_copies(uint8_t *copies)
-{
-	int fd, ret;
-
-	fd = open(config_path, O_RDONLY);
-	if (fd < 0)
-		return SD_RES_EIO;
-
-	ret = xpread(fd, copies, sizeof(*copies),
-		     offsetof(struct sheepdog_config, copies));
-	close(fd);
-
-	if (ret != sizeof(*copies))
-		return SD_RES_EIO;
-
-	return SD_RES_SUCCESS;
-}
-
-int set_cluster_flags(uint16_t flags)
-{
-	int fd, ret = SD_RES_EIO;
-	void *jd;
-
-	fd = open(config_path, O_DSYNC | O_WRONLY);
-	if (fd < 0)
-		goto out;
-
-	jd = jrnl_begin(&flags, sizeof(flags),
-			offsetof(struct sheepdog_config, flags),
-			config_path, jrnl_path);
-	if (!jd) {
-		ret = SD_RES_EIO;
-		goto err;
-	}
-	ret = xpwrite(fd, &flags, sizeof(flags), offsetof(struct sheepdog_config, flags));
-	if (ret != sizeof(flags))
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-	jrnl_end(jd);
-err:
-	close(fd);
-out:
-	return ret;
-}
-
-int get_cluster_flags(uint16_t *flags)
-{
-	int fd, ret = SD_RES_EIO;
-
-	fd = open(config_path, O_RDONLY);
-	if (fd < 0)
-		goto out;
-
-	ret = xpread(fd, flags, sizeof(*flags),
-		     offsetof(struct sheepdog_config, flags));
-	if (ret != sizeof(*flags))
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-
-	close(fd);
-out:
-	return ret;
-}
-
-int set_cluster_store(const char *name)
-{
-	int fd, ret = SD_RES_EIO, len;
-	void *jd;
-
-	fd = open(config_path, O_DSYNC | O_WRONLY);
-	if (fd < 0)
-		goto out;
-
-	len = strlen(name) + 1;
-	if (len > STORE_LEN)
-		goto err;
-	jd = jrnl_begin(name, len,
-			offsetof(struct sheepdog_config, store),
-			config_path, jrnl_path);
-	if (!jd) {
-		ret = SD_RES_EIO;
-		goto err;
-	}
-	ret = xpwrite(fd, name, len, offsetof(struct sheepdog_config, store));
-	if (ret != len)
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-	jrnl_end(jd);
-err:
-	close(fd);
-out:
-	return ret;
-}
-
-int get_cluster_store(char *buf)
-{
-	int fd, ret = SD_RES_EIO;
-
-	fd = open(config_path, O_RDONLY);
-	if (fd < 0)
-		goto out;
-
-	ret = pread(fd, buf, STORE_LEN,
-		    offsetof(struct sheepdog_config, store));
-
-	if (ret == -1)
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-
-	close(fd);
-out:
-	return ret;
-}
-
-int set_cluster_space(uint64_t space)
-{
-	int fd, ret = SD_RES_EIO;
-	void *jd;
-
-	fd = open(config_path, O_DSYNC | O_WRONLY);
-	if (fd < 0)
-		goto out;
-
-	jd = jrnl_begin(&space, sizeof(space),
-			offsetof(struct sheepdog_config, space),
-			config_path, jrnl_path);
-	if (!jd) {
-		ret = SD_RES_EIO;
-		goto err;
-	}
-	ret = xpwrite(fd, &space, sizeof(space),
-		      offsetof(struct sheepdog_config, space));
-	if (ret != sizeof(space))
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-	jrnl_end(jd);
-err:
-	close(fd);
-out:
-	return ret;
-}
-
-int get_cluster_space(uint64_t *space)
-{
-	int fd, ret = SD_RES_EIO;
-
-	fd = open(config_path, O_RDONLY);
-	if (fd < 0)
-		goto out;
-
-	ret = xpread(fd, space, sizeof(*space),
-		     offsetof(struct sheepdog_config, space));
-	if (ret != sizeof(*space))
-		ret = SD_RES_EIO;
-	else
-		ret = SD_RES_SUCCESS;
-
-	close(fd);
-out:
-	return ret;
-}
-- 
1.7.2.5




More information about the sheepdog mailing list