[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