<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 23, 2015 at 9:22 PM, Hitoshi Mitake <span dir="ltr"><<a href="mailto:mitake.hitoshi@lab.ntt.co.jp" target="_blank">mitake.hitoshi@lab.ntt.co.jp</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Vasiliy Tolstov <<a href="mailto:v.tolstov@selfip.ru">v.tolstov@selfip.ru</a>><br>
<br>
This patch implements a blockdriver function bdrv_snapshot_delete() in<br>
the sheepdog driver. With the new function, snapshots of sheepdog can<br>
be deleted from libvirt.<br>
<br>
Cc: Jeff Cody <<a href="mailto:jcody@redhat.com">jcody@redhat.com</a>><br>
Signed-off-by: Hitoshi Mitake <<a href="mailto:mitake.hitoshi@lab.ntt.co.jp">mitake.hitoshi@lab.ntt.co.jp</a>><br>
Signed-off-by: Vasiliy Tolstov <<a href="mailto:v.tolstov@selfip.ru">v.tolstov@selfip.ru</a>><br></blockquote><div><br></div><div>ping, Jeff?</div><div><br></div><div>Thanks,</div><div>Hitoshi</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
 block/sheepdog.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-<br>
 1 file changed, 123 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/block/sheepdog.c b/block/sheepdog.c<br>
index d80e4ed..0a4f2fc 100644<br>
--- a/block/sheepdog.c<br>
+++ b/block/sheepdog.c<br>
@@ -283,6 +283,12 @@ static inline bool is_snapshot(struct SheepdogInode *inode)<br>
     return !!inode->snap_ctime;<br>
 }<br>
<br>
+static inline size_t count_data_objs(const struct SheepdogInode *inode)<br>
+{<br>
+    return DIV_ROUND_UP(inode->vdi_size,<br>
+                        (1UL << inode->block_size_shift));<br>
+}<br>
+<br>
 #undef DPRINTF<br>
 #ifdef DEBUG_SDOG<br>
 #define DPRINTF(fmt, args...)                                       \<br>
@@ -2479,13 +2485,128 @@ out:<br>
     return ret;<br>
 }<br>
<br>
+#define NR_BATCHED_DISCARD 128<br>
+<br>
+static bool remove_objects(BDRVSheepdogState *s)<br>
+{<br>
+    int fd, i = 0, nr_objs = 0;<br>
+    Error *local_err = NULL;<br>
+    int ret = 0;<br>
+    bool result = true;<br>
+    SheepdogInode *inode = &s->inode;<br>
+<br>
+    fd = connect_to_sdog(s, &local_err);<br>
+    if (fd < 0) {<br>
+        error_report_err(local_err);<br>
+        return false;<br>
+    }<br>
+<br>
+    nr_objs = count_data_objs(inode);<br>
+    while (i < nr_objs) {<br>
+        int start_idx, nr_filled_idx;<br>
+<br>
+        while (i < nr_objs && !inode->data_vdi_id[i]) {<br>
+            i++;<br>
+        }<br>
+        start_idx = i;<br>
+<br>
+        nr_filled_idx = 0;<br>
+        while (i < nr_objs && nr_filled_idx < NR_BATCHED_DISCARD) {<br>
+            if (inode->data_vdi_id[i]) {<br>
+                inode->data_vdi_id[i] = 0;<br>
+                nr_filled_idx++;<br>
+            }<br>
+<br>
+            i++;<br>
+        }<br>
+<br>
+        ret = write_object(fd, s->aio_context,<br>
+                           (char *)&inode->data_vdi_id[start_idx],<br>
+                           vid_to_vdi_oid(s->inode.vdi_id), inode->nr_copies,<br>
+                           (i - start_idx) * sizeof(uint32_t),<br>
+                           offsetof(struct SheepdogInode,<br>
+                                    data_vdi_id[start_idx]),<br>
+                           false, s->cache_flags);<br>
+        if (ret < 0) {<br>
+            error_report("failed to discard snapshot inode.");<br>
+            result = false;<br>
+            goto out;<br>
+        }<br>
+    }<br>
+<br>
+out:<br>
+    closesocket(fd);<br>
+    return result;<br>
+}<br>
+<br>
 static int sd_snapshot_delete(BlockDriverState *bs,<br>
                               const char *snapshot_id,<br>
                               const char *name,<br>
                               Error **errp)<br>
 {<br>
-    /* FIXME: Delete specified snapshot id.  */<br>
-    return 0;<br>
+    uint32_t snap_id = 0;<br>
+    char snap_tag[SD_MAX_VDI_TAG_LEN];<br>
+    Error *local_err = NULL;<br>
+    int fd, ret;<br>
+    char buf[SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN];<br>
+    BDRVSheepdogState *s = bs->opaque;<br>
+    unsigned int wlen = SD_MAX_VDI_LEN + SD_MAX_VDI_TAG_LEN, rlen = 0;<br>
+    uint32_t vid;<br>
+    SheepdogVdiReq hdr = {<br>
+        .opcode = SD_OP_DEL_VDI,<br>
+        .data_length = wlen,<br>
+        .flags = SD_FLAG_CMD_WRITE,<br>
+    };<br>
+    SheepdogVdiRsp *rsp = (SheepdogVdiRsp *)&hdr;<br>
+<br>
+    if (!remove_objects(s)) {<br>
+        return -1;<br>
+    }<br>
+<br>
+    memset(buf, 0, sizeof(buf));<br>
+    memset(snap_tag, 0, sizeof(snap_tag));<br>
+    pstrcpy(buf, SD_MAX_VDI_LEN, s->name);<br>
+    if (qemu_strtoul(snapshot_id, NULL, 10, (unsigned long *)&snap_id)) {<br>
+        return -1;<br>
+    }<br>
+<br>
+    if (snap_id) {<br>
+        hdr.snapid = snap_id;<br>
+    } else {<br>
+        pstrcpy(snap_tag, sizeof(snap_tag), snapshot_id);<br>
+        pstrcpy(buf + SD_MAX_VDI_LEN, SD_MAX_VDI_TAG_LEN, snap_tag);<br>
+    }<br>
+<br>
+    ret = find_vdi_name(s, s->name, snap_id, snap_tag, &vid, true,<br>
+                        &local_err);<br>
+    if (ret) {<br>
+        return ret;<br>
+    }<br>
+<br>
+    fd = connect_to_sdog(s, &local_err);<br>
+    if (fd < 0) {<br>
+        error_report_err(local_err);<br>
+        return -1;<br>
+    }<br>
+<br>
+    ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr,<br>
+                 buf, &wlen, &rlen);<br>
+    closesocket(fd);<br>
+    if (ret) {<br>
+        return ret;<br>
+    }<br>
+<br>
+    switch (rsp->result) {<br>
+    case SD_RES_NO_VDI:<br>
+        error_report("%s was already deleted", s->name);<br>
+    case SD_RES_SUCCESS:<br>
+        break;<br>
+    default:<br>
+        error_report("%s, %s", sd_strerror(rsp->result), s->name);<br>
+        return -1;<br>
+    }<br>
+<br>
+    return ret;<br>
 }<br>
<br>
 static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.9.1<br>
<br>
</font></span></blockquote></div><br></div></div>