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