[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