[Sheepdog] [PATCH v6 09/17] farm: add snapshot object
Liu Yuan
namei.unix at gmail.com
Thu Jan 12 14:37:20 CET 2012
From: Liu Yuan <tailai.ly at taobao.com>
snap object is the meta data that describes the snapshot.
Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
include/sheepdog_proto.h | 8 ++
sheep/farm/farm.h | 8 ++-
sheep/farm/snap.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 184 insertions(+), 1 deletions(-)
create mode 100644 sheep/farm/snap.c
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index de326ee..9cc5a99 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -198,6 +198,14 @@ struct sheepdog_vdi_attr {
char value[SD_MAX_VDI_ATTR_VALUE_LEN];
};
+#define SHA1_LEN 20
+
+struct snap_log {
+ int epoch;
+ uint64_t time;
+ unsigned char sha1[SHA1_LEN];
+};
+
/*
* 64 bit FNV-1a non-zero initial basis
*/
diff --git a/sheep/farm/farm.h b/sheep/farm/farm.h
index bf8654c..1e9120b 100644
--- a/sheep/farm/farm.h
+++ b/sheep/farm/farm.h
@@ -20,7 +20,6 @@
#include "logger.h"
#include "strbuf.h"
-#define SHA1_LEN 20
#define HEX_LEN 40
#define NAME_LEN HEX_LEN
@@ -65,4 +64,11 @@ extern void trunk_reset(void);
extern void trunk_put_entry(uint64_t oid);
extern void trunk_get_entry(uint64_t oid);
+/* snap.c */
+extern int snap_init(void);
+extern void *snap_file_read(unsigned char *sha1, struct sha1_file_hdr *outhdr);
+extern int snap_file_write(int epoch, unsigned char *outsha1, int user);
+extern void *snap_log_read(int *, int user);
+extern int snap_log_write(int epoch, unsigned char *sha1, int user);
+
#endif
diff --git a/sheep/farm/snap.c b/sheep/farm/snap.c
new file mode 100644
index 0000000..92f57d5
--- /dev/null
+++ b/sheep/farm/snap.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2011 Taobao Inc.
+ *
+ * Liu Yuan <namei.unix at gmail.com>
+ *
+ * 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/>.
+ */
+
+/*
+ * Snap object is the meta data that describes the snapshot, either triggered
+ * by recovery logic or end users.
+ */
+#include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "farm.h"
+#include "sheep_priv.h"
+
+int snap_init(void)
+{
+ int fd, ret = 0;
+ struct strbuf buf = STRBUF_INIT;
+
+ strbuf_addstr(&buf, farm_dir);
+ strbuf_addf(&buf, "/%s", "sys_snap");
+
+ fd = open(buf.buf, O_CREAT | O_EXCL, 0666);
+ if (fd < 0) {
+ if (errno != EEXIST) {
+ ret = -1;
+ goto out;
+ }
+ }
+ close(fd);
+
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, farm_dir);
+ strbuf_addf(&buf, "/%s", "user_snap");
+
+ fd = open(buf.buf, O_CREAT | O_EXCL, 0666);
+ if (fd < 0) {
+ if (errno != EEXIST) {
+ ret = -1;
+ goto out;
+ }
+ }
+ close(fd);
+
+out:
+ strbuf_release(&buf);
+ return ret;
+}
+
+int snap_log_write(int epoch, unsigned char *sha1, int user)
+{
+ int fd, ret = -1;
+ struct strbuf buf = STRBUF_INIT;
+ struct snap_log log = { .epoch = epoch,
+ .time = time(NULL) };
+
+ memcpy(log.sha1, sha1, SHA1_LEN);
+ strbuf_addstr(&buf, farm_dir);
+ strbuf_addf(&buf, "/%s", user ? "user_snap" : "sys_snap");
+
+ fd = open(buf.buf, O_WRONLY | O_APPEND);
+ if (fd < 0) {
+ dprintf("%m\n");
+ goto out;
+ }
+
+ strbuf_reset(&buf);
+ strbuf_add(&buf, &log, sizeof(log));
+ ret = xwrite(fd, buf.buf, buf.len);
+ if (ret != buf.len)
+ ret = -1;
+
+ close(fd);
+out:
+ strbuf_release(&buf);
+ return ret;
+}
+
+void *snap_log_read(int *out_nr, int user)
+{
+ struct strbuf buf = STRBUF_INIT;
+ struct stat st;
+ void *buffer = NULL;
+ int len, fd;
+
+ strbuf_addstr(&buf, farm_dir);
+ strbuf_addf(&buf, "/%s", user ? "user_snap" : "sys_snap");
+
+ fd = open(buf.buf, O_RDONLY);
+ if (fd < 0) {
+ dprintf("%m\n");
+ goto out;
+ }
+ if (fstat(fd, &st) < 0) {
+ dprintf("%m\n");
+ goto out_close;
+ }
+
+ len = st.st_size;
+ buffer = xmalloc(len);
+ len = xread(fd, buffer, len);
+ if (len != st.st_size) {
+ free(buffer);
+ buffer = NULL;
+ goto out_close;
+ }
+ *out_nr = len / sizeof(struct snap_log);
+out_close:
+ close(fd);
+out:
+ strbuf_release(&buf);
+ return buffer;
+}
+
+void *snap_file_read(unsigned char *sha1, struct sha1_file_hdr *outhdr)
+{
+ void *buffer = NULL;
+
+ dprintf("%s\n", sha1_to_hex(sha1));
+ buffer = sha1_file_read(sha1, outhdr);
+ if (!buffer)
+ return NULL;
+ if (strcmp(outhdr->tag, TAG_SNAP) != 0) {
+ free(buffer);
+ return NULL;
+ }
+
+ return buffer;
+}
+
+int snap_file_write(int epoch, unsigned char *outsha1, int user)
+{
+ int ret = 0;
+ struct strbuf buf = STRBUF_INIT;
+ struct sd_node nodes[SD_MAX_NODES];
+ int tgt_epoch = user ? sys->epoch : epoch;
+ uint64_t epoch_size = epoch_log_read(tgt_epoch, (char *)nodes, sizeof(nodes));
+ unsigned char trunk[SHA1_LEN];
+ struct sha1_file_hdr hdr = { .size = epoch_size + SHA1_LEN,
+ .priv = tgt_epoch };
+ memcpy(hdr.tag, TAG_SNAP, TAG_LEN);
+
+ if (trunk_file_write(trunk, user) < 0) {
+ ret = -1;
+ goto err;
+ }
+ strbuf_add(&buf, &hdr, sizeof(hdr));
+ strbuf_add(&buf, trunk, SHA1_LEN);
+ strbuf_add(&buf, (char *)nodes, epoch_size);
+ if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) {
+ ret = -1;
+ goto err;
+ }
+
+ dprintf("epoch %u, sha1: %s\n", epoch, sha1_to_hex(outsha1));
+err:
+ strbuf_release(&buf);
+ return ret;
+}
--
1.7.8.2
More information about the sheepdog
mailing list