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 |   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

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

Reply via email to