[sheepdog] [PATCH 1/5] shared lib: add VDI operation: snapshot
Yu Yang
yuyanggg at gmail.com
Thu Jun 4 14:31:45 CEST 2015
From: Yu Yang <yuyang at cmss.chinamobile.com>
Take a snapshot of a working VDI.
We do NOT import snapshot id for lib user, and snapshot tag
is necessary for any snapshot VDI.
Signed-off-by: Yu Yang <yuyang at cmss.chinamobile.com>
---
lib/shared/sheepdog.h | 11 +++
lib/shared/vdi.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 220 insertions(+)
diff --git a/lib/shared/sheepdog.h b/lib/shared/sheepdog.h
index 01efbd9..dd36bbe 100644
--- a/lib/shared/sheepdog.h
+++ b/lib/shared/sheepdog.h
@@ -126,4 +126,15 @@ int sd_vdi_write(struct sd_vdi *vdi, void *buf, size_t count, off_t offset);
*/
int sd_vdi_close(struct sd_vdi *vdi);
+/*
+ * Create a snapshot of a VDI
+ *
+ * @c: pointer to the cluster descriptor
+ * @name: the name of the VDI to snapshot
+ * @tag: the tag of the snapshot
+ *
+ * Return error code defined in sheepdog_proto.h.
+ */
+int sd_vdi_snapshot(struct sd_cluster *c, char *name, char *tag);
+
#endif
diff --git a/lib/shared/vdi.c b/lib/shared/vdi.c
index 7375094..2646d6f 100644
--- a/lib/shared/vdi.c
+++ b/lib/shared/vdi.c
@@ -13,6 +13,17 @@
#include "sheepdog.h"
#include "internal.h"
+#include "sheep.h"
+
+static int write_object(struct sd_cluster *c, uint64_t oid, uint64_t cow_oid,
+ void *data, unsigned int datalen, uint64_t offset, uint32_t flags,
+ uint8_t copies, uint8_t copy_policy, bool create, bool direct);
+
+static int read_object(struct sd_cluster *c, uint64_t oid, void *data,
+ unsigned int datalen, uint64_t offset, bool direct);
+
+static int vdi_read_inode(struct sd_cluster *c, char *name,
+ char *tag, struct sd_inode *inode, bool header);
static int lock_vdi(struct sd_vdi *vdi)
{
@@ -187,3 +198,201 @@ int sd_vdi_close(struct sd_vdi *vdi)
free_vdi(vdi);
return 0;
}
+
+static int do_vdi_create(struct sd_cluster *c, char *name, uint64_t vdi_size,
+ uint32_t base_vid, bool snapshot,
+ uint8_t nr_copies, uint8_t copy_policy,
+ uint8_t store_policy, uint8_t block_size_shift)
+{
+ struct sd_req hdr = {};
+ int ret;
+
+ sd_init_req(&hdr, SD_OP_NEW_VDI);
+ hdr.flags = SD_FLAG_CMD_WRITE;
+ hdr.data_length = SD_MAX_VDI_LEN;
+
+ hdr.vdi.base_vdi_id = base_vid;
+ hdr.vdi.snapid = snapshot ? 1 : 0;
+ hdr.vdi.vdi_size = vdi_size;
+ hdr.vdi.copies = nr_copies;
+ hdr.vdi.copy_policy = copy_policy;
+ hdr.vdi.store_policy = store_policy;
+ hdr.vdi.block_size_shift = block_size_shift;
+
+ ret = sd_run_sdreq(c, &hdr, name);
+
+ return ret;
+}
+
+static int write_object(struct sd_cluster *c, uint64_t oid, uint64_t cow_oid,
+ void *data, unsigned int datalen, uint64_t offset, uint32_t flags,
+ uint8_t copies, uint8_t copy_policy, bool create, bool direct)
+{
+ struct sd_req hdr = {};
+ int ret;
+
+ if (create)
+ sd_init_req(&hdr, SD_OP_CREATE_AND_WRITE_OBJ);
+ else
+ sd_init_req(&hdr, SD_OP_WRITE_OBJ);
+
+ hdr.data_length = datalen;
+ hdr.flags = flags | SD_FLAG_CMD_WRITE;
+
+ if (cow_oid)
+ hdr.flags |= SD_FLAG_CMD_COW;
+ if (direct)
+ hdr.flags |= SD_FLAG_CMD_DIRECT;
+
+ hdr.obj.copies = copies;
+ hdr.obj.copy_policy = copy_policy;
+ hdr.obj.oid = oid;
+ hdr.obj.cow_oid = cow_oid;
+ hdr.obj.offset = offset;
+
+ ret = sd_run_sdreq(c, &hdr, data);
+
+ return ret;
+}
+
+static int read_object(struct sd_cluster *c, uint64_t oid, void *data,
+ unsigned int datalen, uint64_t offset, bool direct)
+{
+ struct sd_req hdr = {};
+ int ret;
+
+ sd_init_req(&hdr, SD_OP_READ_OBJ);
+ hdr.data_length = datalen;
+ hdr.obj.oid = oid;
+ hdr.obj.offset = offset;
+ if (direct)
+ hdr.flags |= SD_FLAG_CMD_DIRECT;
+
+ ret = sd_run_sdreq(c, &hdr, data);
+
+ return ret;
+}
+
+static int find_vdi(struct sd_cluster *c, char *name,
+ char *tag, uint32_t *vid)
+{
+ struct sd_req hdr = {};
+ struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+ char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN];
+ int ret;
+
+ memset(buf, 0, sizeof(buf));
+ pstrcpy(buf, SD_MAX_VDI_LEN, name);
+ if (tag)
+ pstrcpy(buf + SD_MAX_VDI_LEN, SD_MAX_VDI_TAG_LEN, tag);
+
+ sd_init_req(&hdr, SD_OP_GET_VDI_INFO);
+ hdr.data_length = SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN;
+ hdr.flags = SD_FLAG_CMD_WRITE;
+
+ ret = sd_run_sdreq(c, &hdr, buf);
+ if (ret != SD_RES_SUCCESS)
+ return ret;
+
+ if (vid)
+ *vid = rsp->vdi.vdi_id;
+
+ return ret;
+}
+
+static int vdi_read_inode(struct sd_cluster *c, char *name,
+ char *tag, struct sd_inode *inode, bool onlyheader)
+{
+ int ret;
+ uint32_t vid = 0;
+ size_t len;
+
+ ret = find_vdi(c, name, tag, &vid);
+ if (ret != SD_RES_SUCCESS)
+ return ret;
+
+ if (onlyheader)
+ len = SD_INODE_HEADER_SIZE;
+ else
+ len = SD_INODE_SIZE;
+
+ ret = read_object(c, vid_to_vdi_oid(vid), inode, len, 0, true);
+
+ return SD_RES_SUCCESS;
+}
+
+/** FIXME: tgtd multi-path support **/
+int sd_vdi_snapshot(struct sd_cluster *c, char *name, char *snap_tag)
+{
+ struct sd_req hdr = {};
+ char buf[SD_INODE_HEADER_SIZE];
+ struct sd_inode *inode = (struct sd_inode *)buf;
+ int ret = 0;
+
+ if (!name || *name == '\0') {
+ fprintf(stderr, "VDI name can NOT be null\n");
+ return SD_RES_INVALID_PARMS;
+ }
+ if (!snap_tag || *snap_tag == '\0') {
+ fprintf(stderr, "Snapshot tag can NOT be null for snapshot\n");
+ return SD_RES_INVALID_PARMS;
+ }
+
+ ret = find_vdi(c, name, snap_tag, NULL);
+ if (ret == SD_RES_SUCCESS) {
+ fprintf(stderr, "VDI %s(tag: %s) is already existed\n",
+ name, snap_tag);
+ return SD_RES_INVALID_PARMS;
+
+ } else if (ret == SD_RES_NO_TAG) {
+ ret = vdi_read_inode(c, name, NULL, inode, true);
+ if (ret != SD_RES_SUCCESS)
+ return ret;
+
+ } else {
+ fprintf(stderr, "Failed to create snapshot:%s\n",
+ sd_strerror(ret));
+ return ret;
+ }
+
+ if (inode->store_policy) {
+ fprintf(stderr, "Creating a snapshot of hypervolume"
+ " is not supported\n");
+ return SD_RES_INVALID_PARMS;
+ }
+
+ sd_init_req(&hdr, SD_OP_PREVENT_INODE_UPDATE);
+ ret = sd_run_sdreq(c, &hdr, NULL);
+ if (ret != SD_RES_SUCCESS) {
+ fprintf(stderr, "Failed to prevent inode update: %s\n",
+ sd_strerror(ret));
+ return ret;
+ }
+
+ ret = write_object(c, vid_to_vdi_oid(inode->vdi_id), 0, snap_tag,
+ SD_MAX_VDI_TAG_LEN, offsetof(struct sd_inode, tag), 0,
+ inode->nr_copies, inode->copy_policy, false, false);
+ if (ret != SD_RES_SUCCESS) {
+ fprintf(stderr, "Failed to write object: %s\n",
+ sd_strerror(ret));
+ goto out;
+ }
+
+ ret = do_vdi_create(c, inode->name, inode->vdi_size,
+ inode->vdi_id, true, inode->nr_copies,
+ inode->copy_policy, inode->store_policy,
+ inode->block_size_shift);
+ if (ret != SD_RES_SUCCESS) {
+ fprintf(stderr, "Failed to create VDI: %s\n", sd_strerror(ret));
+ goto out;
+ }
+
+out:
+ sd_init_req(&hdr, SD_OP_ALLOW_INODE_UPDATE);
+ int ret2 = sd_run_sdreq(c, &hdr, NULL);
+ if (ret2 != SD_RES_SUCCESS)
+ fprintf(stderr, "allowing inode update failed:%s\n",
+ sd_strerror(ret));
+
+ return ret;
+}
--
1.7.9.5
More information about the sheepdog
mailing list