[sheepdog] [PATCH] sheep/dog: introduce new bitmap for delete vdi

Saeki Masaki saeki.masaki at po.ntts.co.jp
Wed Nov 26 02:50:46 CET 2014


For day-to-day backup, repeatedly create snapshot and delete snapshot.
but inode file remains even after delete snapshot.
"dog vdi list" command would read all inode files, even if vdi/snapshot was deleted.
this behavior is inefficient to get current VDI list.

This patch manages the deleted VDI in a bit map. 
And, referring VDI bit map when you get VDI list, to open only the necessary files.

Assessment procedure of this patch are below

1. create VDI 1000 times
2. clearing file cache
3. execute "dog vdi list -T"
===> execution time assessment [case1]
4. create and delete snapshot 4000 times
5. clearing file cache
6. execute "dog vdi list -T"
===> execution time assessment [case2]
7. create and delete snapshot 5000 times
8. clearing file cache
9. execute "dog vdi list -T"
===> execution time assessment [case3]

results are follow.

* Current Sheepdog
[case1] Elapsed time: 0.963 seconds
[case2] Elapsed time: 6.522 seconds
[case3] Elapsed time: 23.376 seconds

* Patch applied Sheepdog
[case1] Elapsed time: 0.714 seconds
[case2] Elapsed time: 0.979 seconds
[case3] Elapsed time: 0.921 seconds

Signed-off-by: Masaki Saeki <saeki.masaki at po.ntts.co.jp>
---
 dog/common.c             |   15 +++++++++++++++
 include/internal_proto.h |    2 +-
 include/sheepdog_proto.h |    1 +
 sheep/group.c            |    1 +
 sheep/ops.c              |   17 +++++++++++++++++
 sheep/plain_store.c      |    4 ++++
 sheep/sheep_priv.h       |    2 ++
 sheep/vdi.c              |   14 ++++++++++++++
 8 files changed, 55 insertions(+), 1 deletions(-)

diff --git a/dog/common.c b/dog/common.c
index 3c4f6f5..2d8a173 100644
--- a/dog/common.c
+++ b/dog/common.c
@@ -137,6 +137,7 @@ int parse_vdi(vdi_parser_func_t func, size_t size, void *data,
 	struct sd_req req;
 	struct sd_rsp *rsp = (struct sd_rsp *)&req;
 	static DECLARE_BITMAP(vdi_inuse, SD_NR_VDIS);
+	static DECLARE_BITMAP(vdi_deleted, SD_NR_VDIS);
 	uint32_t rlen;
 
 	sd_init_req(&req, SD_OP_READ_VDIS);
@@ -150,10 +151,24 @@ int parse_vdi(vdi_parser_func_t func, size_t size, void *data,
 		goto out;
 	}
 
+	sd_init_req(&req, SD_OP_READ_DEL_VDIS);
+	req.data_length = sizeof(vdi_deleted);
+
+	ret = dog_exec_req(&sd_nid, &req, vdi_deleted);
+	if (ret < 0)
+		goto out;
+	if (rsp->result != SD_RES_SUCCESS) {
+		sd_err("%s", sd_strerror(rsp->result));
+		goto out;
+	}
+
 	FOR_EACH_VDI(nr, vdi_inuse) {
 		uint64_t oid;
 		uint32_t snapid;
 
+		if (test_bit(nr, vdi_deleted))
+			continue;
+
 		oid = vid_to_vdi_oid(nr);
 
 		/* for B-tree inode, we also need sd_index_header */
diff --git a/include/internal_proto.h b/include/internal_proto.h
index 85f66b8..faed3f6 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -24,7 +24,7 @@
 #include "rbtree.h"
 #include "fec.h"
 
-#define SD_SHEEP_PROTO_VER 0x09
+#define SD_SHEEP_PROTO_VER 0x0a
 
 #define SD_DEFAULT_COPIES 3
 /*
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index c25e9f1..3785f26 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -45,6 +45,7 @@
 #define SD_OP_READ_VDIS      0x15
 #define SD_OP_FLUSH_VDI      0x16
 #define SD_OP_DEL_VDI        0x17
+#define SD_OP_READ_DEL_VDIS  0x18
 
 /* macros in the SD_FLAG_CMD_XXX group are mutually exclusive */
 #define SD_FLAG_CMD_WRITE    0x01
diff --git a/sheep/group.c b/sheep/group.c
index f1104c1..a45904e 100644
--- a/sheep/group.c
+++ b/sheep/group.c
@@ -19,6 +19,7 @@ struct node {
 struct get_vdis_work {
 	struct work work;
 	DECLARE_BITMAP(vdi_inuse, SD_NR_VDIS);
+	DECLARE_BITMAP(vdi_deleted, SD_NR_VDIS);
 	struct sd_node joined;
 	struct rb_root nroot;
 };
diff --git a/sheep/ops.c b/sheep/ops.c
index 9eb3280..4b54780 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -188,6 +188,9 @@ static int post_cluster_del_vdi(const struct sd_req *req, struct sd_rsp *rsp,
 	struct cache_deletion_work *dw;
 	int ret = rsp->result;
 
+	if (ret == SD_RES_SUCCESS)
+		atomic_set_bit(vid, sys->vdi_deleted);
+
 	if (!sys->enable_object_cache)
 		return ret;
 
@@ -288,6 +291,7 @@ static int cluster_make_fs(const struct sd_req *req, struct sd_rsp *rsp,
 		remove_epoch(i);
 
 	memset(sys->vdi_inuse, 0, sizeof(sys->vdi_inuse));
+	memset(sys->vdi_deleted, 0, sizeof(sys->vdi_deleted));
 	clean_vdi_state();
 
 	sys->cinfo.epoch = 0;
@@ -410,6 +414,12 @@ static int local_read_vdis(const struct sd_req *req, struct sd_rsp *rsp,
 	return read_vdis(data, req->data_length, &rsp->data_length);
 }
 
+static int local_read_del_vdis(const struct sd_req *req, struct sd_rsp *rsp,
+			   void *data, const struct sd_node *sender)
+{
+	return read_del_vdis(data, req->data_length, &rsp->data_length);
+}
+
 static int local_get_vdi_copies(const struct sd_req *req, struct sd_rsp *rsp,
 				void *data, const struct sd_node *sender)
 {
@@ -1574,6 +1584,13 @@ static struct sd_op_template sd_ops[] = {
 		.process_main = local_read_vdis,
 	},
 
+	[SD_OP_READ_DEL_VDIS] = {
+		.name = "READ_DEL_VDIS",
+		.type = SD_OP_TYPE_LOCAL,
+		.force = true,
+		.process_main = local_read_del_vdis,
+	},
+
 	[SD_OP_GET_VDI_COPIES] = {
 		.name = "GET_VDI_COPIES",
 		.type = SD_OP_TYPE_LOCAL,
diff --git a/sheep/plain_store.c b/sheep/plain_store.c
index 876582c..1b7b66c 100644
--- a/sheep/plain_store.c
+++ b/sheep/plain_store.c
@@ -283,6 +283,10 @@ static int init_vdi_state(uint64_t oid, const char *wd, uint32_t epoch)
 
 	add_vdi_state(oid_to_vid(oid), inode->nr_copies,
 		      vdi_is_snapshot(inode), inode->copy_policy);
+
+	if (inode->name[0] == '\0')
+		atomic_set_bit(oid_to_vid(oid), sys->vdi_deleted);
+
 	atomic_set_bit(oid_to_vid(oid), sys->vdi_inuse);
 
 	ret = SD_RES_SUCCESS;
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index ba2c684..3e6adc2 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -131,6 +131,7 @@ struct system_info {
 	uint64_t disk_space;
 
 	DECLARE_BITMAP(vdi_inuse, SD_NR_VDIS);
+	DECLARE_BITMAP(vdi_deleted, SD_NR_VDIS);
 
 	int local_req_efd;
 
@@ -357,6 +358,7 @@ void remove_node_from_participants(const struct node_id *left);
 extern int ec_max_data_strip;
 
 int read_vdis(char *data, int len, unsigned int *rsp_len);
+int read_del_vdis(char *data, int len, unsigned int *rsp_len);
 
 int get_vdi_attr(struct sheepdog_vdi_attr *vattr, int data_len, uint32_t vid,
 		uint32_t *attrid, uint64_t ctime, bool write,
diff --git a/sheep/vdi.c b/sheep/vdi.c
index 4252585..b03421a 100644
--- a/sheep/vdi.c
+++ b/sheep/vdi.c
@@ -1387,6 +1387,17 @@ int read_vdis(char *data, int len, unsigned int *rsp_len)
 	return SD_RES_SUCCESS;
 }
 
+int read_del_vdis(char *data, int len, unsigned int *rsp_len)
+{
+	if (len != sizeof(sys->vdi_deleted))
+		return SD_RES_INVALID_PARMS;
+
+	memcpy(data, sys->vdi_deleted, sizeof(sys->vdi_deleted));
+	*rsp_len = sizeof(sys->vdi_deleted);
+
+	return SD_RES_SUCCESS;
+}
+
 struct deletion_work {
 	struct work work;
 	uint32_t target_vid;
@@ -1518,6 +1529,7 @@ static void delete_vdi_done(struct work *work)
 static int start_deletion(struct request *req, uint32_t vid)
 {
 	struct deletion_work *dw = NULL;
+	struct sd_rsp *rsp = &req->rp;
 	int ret = SD_RES_SUCCESS, finish_fd;
 
 	dw = xzalloc(sizeof(*dw));
@@ -1541,6 +1553,8 @@ static int start_deletion(struct request *req, uint32_t vid)
 	eventfd_xread(finish_fd);
 	close(finish_fd);
 
+	rsp->vdi.vdi_id = vid;
+
 	return ret;
 out:
 	free(dw);
-- 
1.7.1


-- 
NTTソフトウェア株式会社
クラウド事業部
第一事業ユニット
佐伯 昌樹
TEL: 045-212-7393
FAX: 045-662-7856
Mail: saeki.masaki at po.ntts.co.jp
--




More information about the sheepdog mailing list