[sheepdog] [PATCH v6 8/9] copy middle-node when vdi_clone() for hyper volume

Robin Dong robin.k.dong at gmail.com
Mon Nov 11 07:55:34 CET 2013


Copy all middle-nodes when clone a hyper volume.

Signed-off-by: Robin Dong <sanbai at taobao.com>
---
 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 9111ca1..f5ae9dd 100644
--- a/lib/sd_inode.c
+++ b/lib/sd_inode.c
@@ -655,8 +655,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




More information about the sheepdog mailing list