[sheepdog] [PATCH 3/4] dog/farm: add snap log header

Liu Yuan namei.unix at gmail.com
Fri Mar 14 13:04:39 CET 2014


We don't store any previous cluster state for farm, so we can't restore old state
like redundancy scheme.

This patch introduce a header for snap file and as a side effect, we add a magic
and version check capability for cluster snapshot.

This will break the compatibility of old cluster snapshot. For simplicity, we just
error out if we are operating on the old snapshot data.

Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
 dog/cluster.c   |  2 +-
 dog/farm/farm.c | 48 +++++++++++++++++++++++++++-----
 dog/farm/farm.h | 15 +++++++++-
 dog/farm/snap.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 135 insertions(+), 16 deletions(-)

diff --git a/dog/cluster.c b/dog/cluster.c
index dbdc92e..5e99028 100644
--- a/dog/cluster.c
+++ b/dog/cluster.c
@@ -269,7 +269,7 @@ static int list_snapshot(int argc, char **argv)
 		goto out;
 
 	buf = snap_log_read(&log_nr);
-	if (!buf)
+	if (IS_ERR(buf))
 		goto out;
 
 	print_list(buf, log_nr * sizeof(struct snap_log));
diff --git a/dog/farm/farm.c b/dog/farm/farm.c
index c5af9ed..fb2b08d 100644
--- a/dog/farm/farm.c
+++ b/dog/farm/farm.c
@@ -178,7 +178,7 @@ static int get_trunk_sha1(uint32_t idx, const char *tag, unsigned char *outsha1)
 	struct snap_log *log_buf, *log_free = NULL;
 
 	log_free = log_buf = snap_log_read(&nr_logs);
-	if (nr_logs < 0)
+	if (IS_ERR(log_free))
 		goto out;
 
 	for (int i = 0; i < nr_logs; i++, log_buf++) {
@@ -312,32 +312,66 @@ int farm_save_snapshot(const char *tag)
 	unsigned char trunk_sha1[SHA1_DIGEST_SIZE];
 	struct strbuf trunk_buf;
 	void *snap_log = NULL;
-	int log_nr, idx, ret = -1;
+	int log_nr, idx, ret;
 	uint64_t nr_objects = object_tree_size();
 
 	snap_log = snap_log_read(&log_nr);
-	if (!snap_log)
+	if (IS_ERR(snap_log)) {
+		ret = -1;
 		goto out;
+	}
 
 	idx = log_nr + 1;
+	if (!log_nr) {
+		struct sd_req hdr;
+		struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+		struct cluster_info cinfo;
+		struct snap_log_hdr log_hdr;
+
+		sd_init_req(&hdr, SD_OP_CLUSTER_INFO);
+		hdr.data_length = sizeof(cinfo);
+		ret = dog_exec_req(&sd_nid, &hdr, &cinfo);
+		if (ret < 0) {
+			sd_err("Fail to execute request");
+			goto out;
+		}
+		if (rsp->result != SD_RES_SUCCESS) {
+			sd_err("%s", sd_strerror(rsp->result));
+			ret = -1;
+			goto out;
+		}
+		log_hdr.magic = FARM_MAGIC;
+		log_hdr.version = FARM_VERSION;
+		log_hdr.copy_number = cinfo.nr_copies;
+		log_hdr.copy_policy = cinfo.copy_policy;
+		snap_log_write_hdr(&log_hdr);
+	}
 
 	strbuf_init(&trunk_buf, sizeof(struct trunk_entry) * nr_objects);
 
 	wq = create_work_queue("save snapshot", WQ_ORDERED);
 	if (for_each_object_in_tree(queue_save_snapshot_work,
-				    &trunk_buf) < 0)
+				    &trunk_buf) < 0) {
+		ret = -1;
 		goto out;
+	}
 
 	work_queue_wait(wq);
-	if (uatomic_is_true(&work_error))
+	if (uatomic_is_true(&work_error)) {
+		ret = -1;
 		goto out;
+	}
 
 	if (trunk_file_write(nr_objects, (struct trunk_entry *)trunk_buf.buf,
-			     trunk_sha1) < 0)
+			     trunk_sha1) < 0) {
+		ret = -1;
 		goto out;
+	}
 
-	if (snap_log_write(idx, tag, trunk_sha1) < 0)
+	if (snap_log_append(idx, tag, trunk_sha1) < 0) {
+		ret = -1;
 		goto out;
+	}
 
 	ret = 0;
 out:
diff --git a/dog/farm/farm.h b/dog/farm/farm.h
index e838a58..95dcfca 100644
--- a/dog/farm/farm.h
+++ b/dog/farm/farm.h
@@ -31,6 +31,17 @@ struct trunk_file {
 	struct trunk_entry *entries;
 };
 
+#define FARM_VERSION 1
+#define FARM_MAGIC 0xfee1c001
+
+struct snap_log_hdr {
+	uint32_t magic;
+	uint32_t version;
+	uint8_t copy_number;
+	uint8_t copy_policy;
+	uint8_t reserved[22];
+};
+
 struct snap_log {
 	uint32_t idx;
 	char tag[SD_MAX_SNAPSHOT_TAG_LEN];
@@ -57,7 +68,9 @@ uint64_t trunk_get_count(void);
 /* snap.c */
 int snap_init(const char *path);
 void *snap_log_read(int *out_nr);
-int snap_log_write(uint32_t idx, const char *tag, unsigned char *sha1);
+int snap_log_read_hdr(struct snap_log_hdr *);
+int snap_log_append(uint32_t idx, const char *tag, unsigned char *sha1);
+int snap_log_write_hdr(struct snap_log_hdr *);
 
 /* sha1_file.c */
 int sha1_file_write(void *buf, size_t len, unsigned char *sha1);
diff --git a/dog/farm/snap.c b/dog/farm/snap.c
index 5e889d7..df98a78 100644
--- a/dog/farm/snap.c
+++ b/dog/farm/snap.c
@@ -49,7 +49,7 @@ out:
 	return ret;
 }
 
-int snap_log_write(uint32_t idx, const char *tag, unsigned char *sha1)
+int snap_log_append(uint32_t idx, const char *tag, unsigned char *sha1)
 {
 	int fd, ret = -1;
 	struct strbuf buf = STRBUF_INIT;
@@ -78,11 +78,65 @@ out:
 	return ret;
 }
 
+/*
+ * Empty file, return 0;
+ * Failure, return -1;
+ * Success, return > 0;
+ */
+int snap_log_read_hdr(struct snap_log_hdr *hdr)
+{
+	struct stat st;
+	int fd, ret = -1;
+
+	fd = open(snap_log_path, O_RDONLY);
+	if (fd < 0) {
+		sd_err("%m");
+		goto out;
+	}
+
+	if (fstat(fd, &st) < 0) {
+		sd_err("%m");
+		goto out_close;
+	}
+
+	if (st.st_size == 0) {
+		ret = 0;
+		goto out_close;
+	}
+
+	ret = xread(fd, hdr, sizeof(*hdr));
+	if (ret != sizeof(*hdr)) {
+		sd_err("failed to read log header, %m, ret = %d", ret);
+		ret = -1;
+		goto out_close;
+	}
+	if (hdr->magic != FARM_MAGIC) {
+		sd_err("magic number mismatch");
+		ret = -1;
+		goto out_close;
+	}
+	/* If we don't keep backward compatibility, check version */
+out_close:
+	close(fd);
+out:
+	return ret;
+}
+
 void *snap_log_read(int *out_nr)
 {
 	struct stat st;
-	void *buffer = NULL;
-	int len, fd;
+	void *buffer = (void *)-1;
+	struct snap_log_hdr hdr;
+	int len, fd, ret;
+
+	ret = snap_log_read_hdr(&hdr);
+	if (ret < 0)
+		goto out;
+	else if (ret == 0) {
+		*out_nr = 0;
+		buffer = NULL;
+		goto out;
+	}
 
 	fd = open(snap_log_path, O_RDONLY);
 	if (fd < 0) {
@@ -94,12 +148,12 @@ void *snap_log_read(int *out_nr)
 		goto out_close;
 	}
 
-	len = st.st_size;
+	len = st.st_size - sizeof(hdr);
 	buffer = xmalloc(len);
-	len = xread(fd, buffer, len);
-	if (len != st.st_size) {
+	ret = xpread(fd, buffer, len, sizeof(hdr));
+	if (len != len) {
 		free(buffer);
-		buffer = NULL;
+		buffer = (void *)-1;
 		goto out_close;
 	}
 	*out_nr = len / sizeof(struct snap_log);
@@ -108,3 +162,21 @@ out_close:
 out:
 	return buffer;
 }
+
+int snap_log_write_hdr(struct snap_log_hdr *hdr)
+{
+	int fd, ret;
+
+	fd = open(snap_log_path, O_WRONLY);
+	if (fd < 0) {
+		sd_err("%m");
+		return -1;
+	}
+
+	ret = xwrite(fd, hdr, sizeof(*hdr));
+	if (ret != sizeof(*hdr)) {
+		sd_err("failed to write log hdr, %m, ret = %d", ret);
+		return -1;
+	}
+	return 0;
+}
-- 
1.8.1.2




More information about the sheepdog mailing list