[sheepdog] [PATCH v4 4/8] recovery: make IO request to wait when recovery is in RW_INIT

levin li levin108 at gmail.com
Fri May 25 04:30:56 CEST 2012


From: levin li <xingke.lwp at taobao.com>

When recovery is in RW_INIT state, the IO request would be
marked as recovering, then the sender will busy retrying,
we should make the request wait until recovery enters RW_RUN
state to determine whether the object requested is in recovery
instead of just return SD_RES_NEW_NODE_VER.

Signed-off-by: levin li <xingke.lwp at taobao.com>
---
 include/sheepdog_proto.h |    1 +
 sheep/recovery.c         |   34 +++++++++++++++++++++++++++++-----
 sheep/sdnet.c            |   12 +++++++++---
 sheep/sheep_priv.h       |    1 +
 4 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index 0cd8d9d..e20254e 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -65,6 +65,7 @@
 #define SD_RES_NO_STORE         0x20 /* No targeted backend store */
 #define SD_RES_NO_SUPPORT       0x21 /* Operation is not supported by backend store */
 #define SD_RES_CLUSTER_RECOVERING 0x22 /* Cluster is recovering. */
+#define SD_RES_OBJ_RECOVERING     0x23 /* Object is recovering */
 
 /*
  * Object ID rules
diff --git a/sheep/recovery.c b/sheep/recovery.c
index de4bc62..72c74c7 100644
--- a/sheep/recovery.c
+++ b/sheep/recovery.c
@@ -329,6 +329,13 @@ int node_in_recovery(void)
 	return !!recovering_work;
 }
 
+int is_recovery_init(void)
+{
+	struct recovery_work *rw = recovering_work;
+
+	return rw->state == RW_INIT;
+}
+
 int is_recoverying_oid(uint64_t oid)
 {
 	uint64_t hval = fnv_64a_buf(&oid, sizeof(uint64_t), FNV1A_64_INIT);
@@ -347,14 +354,14 @@ int is_recoverying_oid(uint64_t oid)
 	if (before(rw->epoch, sys->epoch))
 		return 1;
 
-	if (rw->state == RW_INIT)
-		return 1;
-
 	if (sd_store->exist(oid)) {
 		dprintf("the object %" PRIx64 " is already recoverd\n", oid);
 		return 0;
 	}
 
+	if (rw->state == RW_INIT)
+		return 1;
+
 	/* the first 'rw->nr_blocking' objects were already scheduled to be done earlier */
 	for (i = 0; i < rw->nr_blocking; i++)
 		if (rw->oids[rw->done + i] == oid)
@@ -384,14 +391,31 @@ int is_recoverying_oid(uint64_t oid)
 	return 0;
 }
 
+static void resume_wait_recovery_requests(void)
+{
+	struct request *req, *t;
+
+	list_for_each_entry_safe(req, t, &sys->wait_rw_queue,
+				 request_list) {
+		dprintf("resume wait oid %" PRIx64 "\n", req->local_oid);
+		if (req->rp.result == SD_RES_OBJ_RECOVERING) {
+			list_del(&req->request_list);
+			list_add_tail(&req->request_list, &sys->request_queue);
+		}
+	}
+
+	process_request_event_queues();
+}
+
 static void do_recover_main(struct work *work)
 {
 	struct recovery_work *rw = container_of(work, struct recovery_work, work);
 	uint64_t oid;
 
-	if (rw->state == RW_INIT)
+	if (rw->state == RW_INIT) {
 		rw->state = RW_RUN;
-	else if (!rw->retry) {
+		resume_wait_recovery_requests();
+	} else if (!rw->retry) {
 		rw->done++;
 		if (rw->nr_blocking > 0)
 			rw->nr_blocking--;
diff --git a/sheep/sdnet.c b/sheep/sdnet.c
index c94df89..0e127d1 100644
--- a/sheep/sdnet.c
+++ b/sheep/sdnet.c
@@ -215,9 +215,15 @@ static int check_request(struct request *req)
 	if (is_recoverying_oid(req->local_oid)) {
 		if (req->rq.flags & SD_FLAG_CMD_IO_LOCAL) {
 			/* Sheep peer request */
-			req->rp.result = SD_RES_NEW_NODE_VER;
-			sys->nr_outstanding_io++;
-			req->work.done(&req->work);
+			if (is_recovery_init()) {
+				req->rp.result = SD_RES_OBJ_RECOVERING;
+				list_add_tail(&req->request_list,
+						&sys->wait_rw_queue);
+			} else {
+				req->rp.result = SD_RES_NEW_NODE_VER;
+				sys->nr_outstanding_io++;
+				req->work.done(&req->work);
+			}
 		} else {
 			/* Gateway request */
 			list_add_tail(&req->request_list, &sys->req_wait_for_obj_list);
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index ba29a2a..b9ae438 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -305,6 +305,7 @@ int get_obj_list(const struct sd_list_req *, struct sd_list_rsp *, void *);
 int start_recovery(uint32_t epoch);
 void resume_recovery_work(void);
 int is_recoverying_oid(uint64_t oid);
+int is_recovery_init(void);
 int node_in_recovery(void);
 
 int write_object(struct vnode_info *vnodes, uint32_t node_version,
-- 
1.7.10




More information about the sheepdog mailing list