[sheepdog] [PATCH 4/5] migrate: add support for upgrading from v0.5.5 or earlier
MORITA Kazutaka
morita.kazutaka at gmail.com
Fri May 31 19:15:49 CEST 2013
From: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Currently, running sheeepdog on the backend store which was formated
by v0.5.5 or earlier breaks epoch information. This adds support for
the migration.
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
sheep/config.c | 2 +-
sheep/migrate.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/sheep/config.c b/sheep/config.c
index 20ddbf2..bc7c98a 100644
--- a/sheep/config.c
+++ b/sheep/config.c
@@ -17,7 +17,7 @@
#include "sheep_priv.h"
-#define SD_FORMAT_VERSION 0x0001
+#define SD_FORMAT_VERSION 0x0002
static struct sheepdog_config {
uint64_t ctime;
diff --git a/sheep/migrate.c b/sheep/migrate.c
index 24fbfcc..ad3903a 100644
--- a/sheep/migrate.c
+++ b/sheep/migrate.c
@@ -61,6 +61,25 @@ struct sheepdog_config_v1 {
uint64_t space;
};
+/* sheepdog 0.6.0 */
+struct node_id_v2 {
+ uint8_t addr[16];
+ uint16_t port;
+ uint8_t io_addr[16];
+ uint16_t io_port;
+ uint8_t pad[4];
+};
+
+struct sd_node_v2 {
+ struct node_id_v2 nid;
+ uint16_t nr_vnodes;
+ uint32_t zone;
+ uint64_t space;
+};
+
+/* sheepdog_config_v2 is the same as v1 */
+#define sheepdog_config_v2 sheepdog_config_v1
+
static size_t get_file_size(const char *path)
{
struct stat stbuf;
@@ -299,8 +318,121 @@ static int migrate_from_v0_to_v1(void)
return ret;
}
+static int update_epoch_from_v1_to_v2(uint32_t epoch)
+{
+ char path[PATH_MAX];
+ struct sd_node_v1 nodes_v1[SD_MAX_NODES];
+ struct sd_node_v2 nodes_v2[SD_MAX_NODES];
+ size_t nr_nodes;
+ time_t *t;
+ int len, fd, ret;
+
+ snprintf(path, sizeof(path), "%s%08u", epoch_path, epoch);
+ fd = open(path, O_RDWR | O_DSYNC);
+ if (fd < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ sd_eprintf("failed to open epoch %"PRIu32" log", epoch);
+ return -1;
+ }
+
+ /*
+ * sheepdog 0.5.6 was released without incrementing the config version.
+ * We detect it by 1) checking the size of epoch file, and 2) checking
+ * the value of sd_node.nid.port
+ */
+ if ((get_file_size(path) - sizeof(time_t)) % sizeof(nodes_v1[0]) != 0) {
+ sd_dprintf("%s is not a v1 format", path);
+ close(fd);
+ return 0;
+ }
+
+ ret = xread(fd, nodes_v1, sizeof(nodes_v1));
+ if (ret < 0) {
+ sd_eprintf("failed to read epoch %"PRIu32" log", epoch);
+ close(fd);
+ return ret;
+ }
+
+ nr_nodes = ret / sizeof(nodes_v1[0]);
+ for (int i = 0; i < nr_nodes; i++) {
+ if (nodes_v1[i].nid.port == 0) {
+ sd_dprintf("%s is not a v1 format", path);
+ return 0;
+ }
+ memset(&nodes_v2[i].nid, 0, sizeof(nodes_v2[i].nid));
+ memcpy(nodes_v2[i].nid.addr, nodes_v1[i].nid.addr,
+ sizeof(nodes_v2[i].nid.addr));
+ nodes_v2[i].nid.port = nodes_v1[i].nid.port;
+ nodes_v2[i].nr_vnodes = nodes_v1[i].nr_vnodes;
+ nodes_v2[i].zone = nodes_v1[i].zone;
+ nodes_v2[i].space = nodes_v1[i].space;
+ }
+
+ len = sizeof(nodes_v2[0]) * nr_nodes;
+ ret = xpwrite(fd, nodes_v2, len, 0);
+ if (ret != len) {
+ sd_eprintf("failed to write epoch %"PRIu32" log",
+ epoch);
+ close(fd);
+ return -1;
+ }
+
+ t = (time_t *)&nodes_v1[nr_nodes];
+
+ ret = xpwrite(fd, t, sizeof(*t), len);
+ if (ret != sizeof(*t)) {
+ sd_eprintf("failed to write time to epoch %"
+ PRIu32" log", epoch);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+static int migrate_from_v1_to_v2(void)
+{
+ int fd, ret;
+ uint16_t version = 2;
+ char store[STORE_LEN] = "plain"; /* we have only the plain driver */
+
+ fd = open(config_path, O_WRONLY | O_DSYNC);
+ if (fd < 0) {
+ sd_eprintf("failed to open config file, %m");
+ return -1;
+ }
+
+ ret = xpwrite(fd, &version, sizeof(version),
+ offsetof(struct sheepdog_config_v2, version));
+ if (ret != sizeof(version)) {
+ sd_eprintf("failed to write config data, %m");
+ close(fd);
+ return -1;
+ }
+
+ ret = xpwrite(fd, store, sizeof(store),
+ offsetof(struct sheepdog_config_v2, store));
+ if (ret != sizeof(store)) {
+ sd_eprintf("failed to write config data, %m");
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ /* upgrade epoch log */
+ for_each_epoch(update_epoch_from_v1_to_v2);
+
+ return ret;
+}
+
static int (*migrate[])(void) = {
migrate_from_v0_to_v1, /* from 0.4.0 or 0.5.0 to 0.5.1 */
+ migrate_from_v1_to_v2, /* from 0.5.x to 0.6.0 */
};
int sd_migrate_store(int from, int to)
--
1.7.9.5
More information about the sheepdog
mailing list