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