[sheepdog] [PATCH v4 7/8] sheepdev: make it safe to open a snapshot VDI

levin li levin108 at gmail.com
Wed Jan 23 08:56:31 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 | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/sheepdev/sheep.c b/sheepdev/sheep.c
index 39f00f9..eedeb7b 100644
--- a/sheepdev/sheep.c
+++ b/sheepdev/sheep.c
@@ -13,6 +13,11 @@
 
 #include "sheepdev.h"
 
+static int is_snapshot(struct sheepdog_inode *inode)
+{
+	return !!inode->snap_ctime;
+}
+
 static int read_object(struct sheepdev *dev, uint64_t oid, void *data,
 		       unsigned int datalen, uint64_t offset)
 {
@@ -112,6 +117,41 @@ 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];
+
+	memset(&hdr, 0, sizeof(hdr));
+	hdr.opcode = 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)
 {
@@ -173,6 +213,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;
 	dev->sectors = dev->size / KERNEL_SECTOR_SIZE;
 	dev->snapshot_id = inode->snap_id;
-- 
1.7.11.7




More information about the sheepdog mailing list