Copy all middle-nodes when clone a hyper volume.

Signed-off-by: Robin Dong <[email protected]>
---
 include/sheepdog_proto.h |    5 ++++-
 lib/sd_inode.c           |   34 ++++++++++++++++++++++++++++++++--
 sheep/vdi.c              |    4 +++-
 3 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index 56a606e..beab3cd 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -284,7 +284,10 @@ extern int sd_inode_write_vid(write_node_fn writer, struct 
sd_inode *inode,
                              uint32_t idx, uint32_t vid, uint32_t value,
                              int flags, bool create, bool direct);
 extern uint32_t sd_inode_get_meta_size(struct sd_inode *inode, size_t size);
-extern void sd_inode_copy_vdis(struct sd_inode *oldi, struct sd_inode *newi);
+extern void sd_inode_copy_vdis(write_node_fn writer, read_node_fn reader,
+                              uint32_t *data_vdi_id, uint8_t store_policy,
+                              uint8_t nr_copies, uint8_t copy_policy,
+                              struct sd_inode *newi);
 
 typedef void (*btree_cb_fn)(void *data, enum btree_node_type type, void *arg);
 extern void traverse_btree(read_node_fn reader, const struct sd_inode *inode,
diff --git a/lib/sd_inode.c b/lib/sd_inode.c
index c76a1bc..a59454e 100644
--- a/lib/sd_inode.c
+++ b/lib/sd_inode.c
@@ -659,8 +659,38 @@ out:
        return ret;
 }
 
-void sd_inode_copy_vdis(struct sd_inode *oldi, struct sd_inode *newi)
+void sd_inode_copy_vdis(write_node_fn writer, read_node_fn reader,
+                       uint32_t *data_vdi_id, uint8_t store_policy,
+                       uint8_t nr_copies, uint8_t copy_policy,
+                       struct sd_inode *newi)
 {
-       memcpy(newi->data_vdi_id, oldi->data_vdi_id, sizeof(newi->data_vdi_id));
+       struct sd_extent_header *header = EXT_HEADER(data_vdi_id);
+       struct sd_extent_header *leaf_node;
+       struct sd_extent_idx *last_idx, *old_iter_idx, *new_iter_idx;
+       uint64_t oid;
+       void *tmp;
+
+       memcpy(newi->data_vdi_id, data_vdi_id, sizeof(newi->data_vdi_id));
+
+       if (store_policy == 1 && header->depth > 1) {
+               /* for B-tree (> 1 level), it needs to copy all leaf-node */
+               last_idx = LAST_IDX(data_vdi_id);
+               old_iter_idx = FIRST_IDX(data_vdi_id);
+               new_iter_idx = FIRST_IDX(newi->data_vdi_id);
+               leaf_node = xmalloc(SD_INODE_DATA_INDEX_SIZE);
+               tmp = (void *)leaf_node;
+               while (old_iter_idx != last_idx) {
+                       reader(old_iter_idx->oid, &tmp,
+                              SD_INODE_DATA_INDEX_SIZE, 0);
+                       oid = vid_to_btree_oid(newi->vdi_id,
+                                              newi->btree_counter++);
+                       writer(oid, leaf_node, SD_INODE_DATA_INDEX_SIZE, 0, 0,
+                              nr_copies, copy_policy, true, false);
+                       new_iter_idx->oid = oid;
+                       old_iter_idx++;
+                       new_iter_idx++;
+               }
+               free(leaf_node);
+       }
 }
 
diff --git a/sheep/vdi.c b/sheep/vdi.c
index 77308fe..5b2be97 100644
--- a/sheep/vdi.c
+++ b/sheep/vdi.c
@@ -238,7 +238,9 @@ static struct sd_inode *alloc_inode(const struct vdi_iocb 
*iocb,
        new->snap_id = new_snapid;
        new->parent_vdi_id = iocb->base_vid;
        if (data_vdi_id)
-               memcpy(new->data_vdi_id, data_vdi_id, sizeof(new->data_vdi_id));
+               sd_inode_copy_vdis(sheep_bnode_writer, sheep_bnode_reader,
+                                  data_vdi_id, iocb->store_policy,
+                                  iocb->nr_copies, iocb->copy_policy, new);
        else if (new->store_policy)
                sd_inode_init(new->data_vdi_id, 1);
 
-- 
1.7.1

-- 
sheepdog mailing list
[email protected]
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to