[sheepdog] [PATCH v2 3/4] sheepdev: make it safe to open a snapshot VDI

levin li levin108 at gmail.com
Mon Jan 7 07:42:47 CET 2013


From: levin li <xingke.lwp at taobao.com>

In case we open a snapshot VDI to make it as a block device, we immediately
create a new writable VDI for this snapshot just as what QEMU does, then we
can safely write to this VDI

Signed-off-by: levin li <xingke.lwp at taobao.com>
---
 sheepdev/sheep.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/sheepdev/sheep.c b/sheepdev/sheep.c
index 61e761e..2157bb4 100644
--- a/sheepdev/sheep.c
+++ b/sheepdev/sheep.c
@@ -13,6 +13,11 @@
 
 #include "sheep.h"
 
+static int is_snapshot(struct sheepdog_inode *inode)
+{
+	return !!inode->snap_ctime;
+}
+
 static void sd_init_req(struct sd_req *req, uint8_t opcode)
 {
 	memset(req, 0, sizeof(*req));
@@ -105,6 +110,40 @@ int send_write_req(struct sheepdev *dev, uint64_t oid, uint64_t cow_oid,
 	return SD_RES_SUCCESS;
 }
 
+static int vdi_snapshot(struct sheepdev *dev, uint64_t vdi_size,
+			uint32_t base_vid, int nr_copies)
+{
+	int ret;
+	struct sd_req hdr;
+	struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+	char buf[SD_MAX_VDI_LEN];
+
+	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.vdi_size = vdi_size;
+	hdr.vdi.snapid = 1;
+	hdr.vdi.copies = nr_copies;
+
+	memset(buf, 0, sizeof(buf));
+	strncpy(buf, dev->vdiname, SD_MAX_VDI_LEN);
+
+	ret = exec_req(dev->sock, &hdr, buf);
+	if (ret)
+		return -EIO;
+
+	if (rsp->result != SD_RES_SUCCESS) {
+		DBPRT("Can not create new VDI snapshot for %s\n", dev->vdiname);
+		return -EIO;
+	}
+
+	dev->vid = rsp->vdi.vdi_id;
+
+	return 0;
+}
+
 static int find_vdi_name(struct sheepdev *dev, const char *vdiname,
 			 uint32_t snapid, const char *tag)
 {
@@ -165,6 +204,26 @@ int sheep_vdi_setup(struct sheepdev *dev)
 		goto out;
 	}
 
+	/*
+	 * In case we open a snapshot VDI, we create a writable VDI for
+	 * the new device to read and write
+	 */
+	if (is_snapshot(inode)) {
+		ret = vdi_snapshot(dev, inode->vdi_size, inode->vdi_id,
+				   inode->nr_copies);
+		if (ret) {
+			ret = -EIO;
+			goto out;
+		}
+
+		ret = read_object(dev, vid_to_vdi_oid(dev->vid), inode,
+				  SD_INODE_SIZE, 0);
+		if (ret != SD_RES_SUCCESS) {
+			ret = -EIO;
+			goto out;
+		}
+	}
+
 	dev->size = inode->vdi_size - SHEEP_OBJECT_SIZE;
 	dev->sectors = dev->size / KERNEL_SECTOR_SIZE;
 	dev->inode = inode;
-- 
1.7.1




More information about the sheepdog mailing list