[sheepdog] [PATCH 1/5] shared lib: add VDI operation: snapshot
Hitoshi Mitake
mitake.hitoshi at gmail.com
Thu Jun 4 15:25:41 CEST 2015
At Thu, 4 Jun 2015 20:31:45 +0800,
Yu Yang wrote:
>
> 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(+)
Applied this series, thanks.
Hitoshi
>
> 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
>
> --
> sheepdog mailing list
> sheepdog at lists.wpkg.org
> https://lists.wpkg.org/mailman/listinfo/sheepdog
More information about the sheepdog
mailing list