From: levin li <xingke....@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....@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

-- 
sheepdog mailing list
sheepdog@lists.wpkg.org
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to