[sheepdog] [RFC PATCH 2/3] add strict check in list_del and list_linked

MORITA Kazutaka morita.kazutaka at gmail.com
Wed Sep 25 20:12:10 CEST 2013


From: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>

This adds a list_head argument to list_del() and list_linked() to
ensure that the specified list_node is linked to the head.

This prepares for the next patch.

Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 dog/treeview.c            |  2 +-
 include/list.h            | 34 +++++++++++++++++++++++++++-------
 include/util.h            |  1 -
 lib/logger.c              |  1 +
 lib/util.c                |  1 +
 lib/work.c                |  4 ++--
 sheep/cluster/corosync.c  | 19 +++++++++++++------
 sheep/cluster/shepherd.c  |  5 ++++-
 sheep/cluster/zookeeper.c |  4 ++--
 sheep/group.c             | 15 ++++++++++-----
 sheep/object_cache.c      |  8 ++++----
 sheep/request.c           | 18 +++++++++---------
 sheep/vdi.c               |  2 +-
 shepherd/shepherd.c       | 10 +++++-----
 14 files changed, 80 insertions(+), 44 deletions(-)

diff --git a/dog/treeview.c b/dog/treeview.c
index c5bad44..c407f2d 100644
--- a/dog/treeview.c
+++ b/dog/treeview.c
@@ -13,7 +13,7 @@
 #include <string.h>
 #include <stdint.h>
 
-#include "util.h"
+#include "list.h"
 #include "treeview.h"
 
 #ifndef MAX_DEPTH
diff --git a/include/list.h b/include/list.h
index c1bd583..03250ae 100644
--- a/include/list.h
+++ b/include/list.h
@@ -5,7 +5,7 @@
 
 #include <stdbool.h>
 
-#include "compiler.h"
+#include "util.h"
 
 struct list_node {
 	struct list_node *next;
@@ -44,11 +44,6 @@ static inline bool list_empty(const struct list_head *head)
 	return head->n.next == &head->n;
 }
 
-static inline bool list_linked(const struct list_node *node)
-{
-	return node->next != NULL;
-}
-
 #define list_entry(ptr, type, member) \
 	container_of(ptr, type, member)
 
@@ -69,6 +64,29 @@ static inline bool list_linked(const struct list_node *node)
 						   typeof(*LOCAL(n)),	\
 						   member))
 
+static inline bool __list_linked(const struct list_node *node,
+				 const struct list_head *head)
+{
+	struct list_node *pos;
+
+	list_for_each(pos, head) {
+		if (pos == node)
+			return true;
+	}
+
+	return false;
+}
+
+static inline bool list_linked(const struct list_node *node,
+			       const struct list_head *head)
+{
+	bool ret = (node->next != NULL);
+
+	assert(ret == __list_linked(node, head));
+
+	return ret;
+}
+
 static inline void __list_add(struct list_node *new,
 			      struct list_node *prev,
 			      struct list_node *next)
@@ -100,8 +118,10 @@ static inline void __list_del_entry(struct list_node *entry)
 	__list_del(entry->prev, entry->next);
 }
 
-static inline void list_del(struct list_node *entry)
+static inline void list_del(struct list_node *entry,
+			    const struct list_head *head)
 {
+	assert(__list_linked(entry, head));
 	__list_del(entry->prev, entry->next);
 	entry->next = entry->prev = NULL;
 }
diff --git a/include/util.h b/include/util.h
index fb59192..05fd8dc 100644
--- a/include/util.h
+++ b/include/util.h
@@ -14,7 +14,6 @@
 #include <errno.h>
 
 #include "logger.h"
-#include "list.h"
 #include "compiler.h"
 
 #define SECTOR_SIZE (1U << 9)
diff --git a/lib/logger.c b/lib/logger.c
index 6c6a315..5a75498 100644
--- a/lib/logger.c
+++ b/lib/logger.c
@@ -36,6 +36,7 @@
 #include <linux/limits.h>
 
 #include "util.h"
+#include "list.h"
 
 static bool colorize;
 static const char * const log_color[] = {
diff --git a/lib/util.c b/lib/util.c
index 7c7785d..bde6833 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -21,6 +21,7 @@
 #include <fcntl.h>
 
 #include "util.h"
+#include "list.h"
 
 mode_t sd_def_dmode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP;
 mode_t sd_def_fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
diff --git a/lib/work.c b/lib/work.c
index ec626e8..f88056e 100644
--- a/lib/work.c
+++ b/lib/work.c
@@ -249,7 +249,7 @@ static void worker_thread_request_done(int fd, int events, void *data)
 
 		while (!list_empty(&list)) {
 			work = list_first_entry(&list, struct work, w_list);
-			list_del(&work->w_list);
+			list_del(&work->w_list, &list);
 
 			work->done(work);
 			uatomic_dec(&wi->nr_workers);
@@ -303,7 +303,7 @@ retest:
 		work = list_first_entry(&wi->q.pending_list,
 				       struct work, w_list);
 
-		list_del(&work->w_list);
+		list_del(&work->w_list, &wi->q.pending_list);
 		pthread_mutex_unlock(&wi->pending_lock);
 
 		if (work->fn)
diff --git a/sheep/cluster/corosync.c b/sheep/cluster/corosync.c
index acc9e1c..7898c73 100644
--- a/sheep/cluster/corosync.c
+++ b/sheep/cluster/corosync.c
@@ -376,12 +376,16 @@ static void __corosync_dispatch(void)
 
 	while (!list_empty(&corosync_block_event_list) ||
 	       !list_empty(&corosync_nonblock_event_list)) {
-		if (!list_empty(&corosync_nonblock_event_list))
+		bool block;
+		if (!list_empty(&corosync_nonblock_event_list)) {
 			cevent = list_first_entry(&corosync_nonblock_event_list,
 						  typeof(*cevent), list);
-		else
+			block = false;
+		} else {
 			cevent = list_first_entry(&corosync_block_event_list,
 						  typeof(*cevent), list);
+			block = true;
+		}
 
 		join_finished = update_join_status(cevent);
 
@@ -398,7 +402,10 @@ static void __corosync_dispatch(void)
 			}
 		}
 
-		list_del(&cevent->list);
+		if (block)
+			list_del(&cevent->list, &corosync_block_event_list);
+		else
+			list_del(&cevent->list, &corosync_nonblock_event_list);
 		free(cevent->msg);
 		free(cevent);
 	}
@@ -461,7 +468,7 @@ static void cdrv_cpg_deliver(cpg_handle_t handle,
 		cevent = update_event(COROSYNC_EVENT_TYPE_BLOCK, &cmsg->sender,
 				      cmsg->msg, cmsg->msg_len);
 		if (cevent) {
-			list_del(&cevent->list);
+			list_del(&cevent->list, &corosync_block_event_list);
 			free(cevent->msg);
 			free(cevent);
 		}
@@ -581,7 +588,7 @@ static void cdrv_cpg_confchg(cpg_handle_t handle,
 		cevent = find_event(COROSYNC_EVENT_TYPE_JOIN, left_sheep + i);
 		if (cevent) {
 			/* the node left before joining */
-			list_del(&cevent->list);
+			list_del(&cevent->list, &corosync_nonblock_event_list);
 			free(cevent->msg);
 			free(cevent);
 			continue;
@@ -590,7 +597,7 @@ static void cdrv_cpg_confchg(cpg_handle_t handle,
 		cevent = find_event(COROSYNC_EVENT_TYPE_BLOCK, left_sheep + i);
 		if (cevent) {
 			/* the node left before sending UNBLOCK */
-			list_del(&cevent->list);
+			list_del(&cevent->list, &corosync_block_event_list);
 			free(cevent->msg);
 			free(cevent);
 		}
diff --git a/sheep/cluster/shepherd.c b/sheep/cluster/shepherd.c
index 9453ff8..494af01 100644
--- a/sheep/cluster/shepherd.c
+++ b/sheep/cluster/shepherd.c
@@ -213,7 +213,10 @@ static bool sph_process_event(void)
 	}
 
 remove:
-	list_del(&ev->event_list);
+	if (nonblock)
+		list_del(&ev->event_list, &nonblocked_event_list);
+	else
+		list_del(&ev->event_list, &blocked_event_list);
 	free(ev->msg);
 	free(ev);
 
diff --git a/sheep/cluster/zookeeper.c b/sheep/cluster/zookeeper.c
index b3966bc..18c7ef4 100644
--- a/sheep/cluster/zookeeper.c
+++ b/sheep/cluster/zookeeper.c
@@ -902,7 +902,7 @@ static void block_event_list_del(struct zk_node *n)
 
 	list_for_each_entry(ev, &zk_block_list, list) {
 		if (node_eq(&ev->node, &n->node)) {
-			list_del(&ev->list);
+			list_del(&ev->list, &zk_block_list);
 			free(ev);
 		}
 	}
@@ -945,7 +945,7 @@ static void zk_handle_unblock(struct zk_event *ev)
 	block = list_first_entry(&zk_block_list, typeof(*block), list);
 	sd_notify_handler(&ev->sender.node, ev->buf, ev->buf_len);
 
-	list_del(&block->list);
+	list_del(&block->list, &zk_block_list);
 	free(block);
 }
 
diff --git a/sheep/group.c b/sheep/group.c
index 718258f..88afc45 100644
--- a/sheep/group.c
+++ b/sheep/group.c
@@ -248,7 +248,7 @@ static void cluster_op_done(struct work *work)
 	req->status = REQUEST_DONE;
 	return;
 drop:
-	list_del(&req->pending_list);
+	list_del(&req->pending_list, main_thread_get(pending_block_list));
 	req->rp.result = SD_RES_CLUSTER_ERROR;
 	put_request(req);
 	cluster_op_running = false;
@@ -699,15 +699,19 @@ main_fn void sd_notify_handler(const struct sd_node *sender, void *data,
 		 node_to_str(sender));
 
 	if (node_is_local(sender)) {
-		if (has_process_work(op))
+		if (has_process_work(op)) {
 			req = list_first_entry(
 				main_thread_get(pending_block_list),
 				struct request, pending_list);
-		else
+			list_del(&req->pending_list,
+				 main_thread_get(pending_block_list));
+		} else {
 			req = list_first_entry(
 				main_thread_get(pending_notify_list),
 				struct request, pending_list);
-		list_del(&req->pending_list);
+			list_del(&req->pending_list,
+				 main_thread_get(pending_notify_list));
+		}
 	}
 
 	if (ret == SD_RES_SUCCESS && has_process_main(op))
@@ -809,7 +813,8 @@ static void requeue_cluster_request(void)
 			/* this request has never been executed, re-queue it */
 			sd_debug("requeue a block request, op: %s",
 				 op_name(req->op));
-			list_del(&req->pending_list);
+			list_del(&req->pending_list,
+				 main_thread_get(pending_block_list));
 			queue_cluster_request(req);
 			break;
 		case REQUEST_QUEUED:
diff --git a/sheep/object_cache.c b/sheep/object_cache.c
index 4b554cf..07ce50b 100644
--- a/sheep/object_cache.c
+++ b/sheep/object_cache.c
@@ -250,7 +250,7 @@ static void del_from_dirty_list(struct object_cache_entry *entry)
 {
 	struct object_cache *oc = entry->oc;
 
-	list_del(&entry->dirty_list);
+	list_del(&entry->dirty_list, &oc->dirty_head);
 	uatomic_dec(&oc->dirty_count);
 }
 
@@ -272,9 +272,9 @@ free_cache_entry(struct object_cache_entry *entry)
 	struct object_cache *oc = entry->oc;
 
 	rb_erase(entry, &oc->lru_tree);
-	list_del(&entry->lru_list);
+	list_del(&entry->lru_list, &oc->lru_head);
 	oc->total_count--;
-	if (list_linked(&entry->dirty_list))
+	if (list_linked(&entry->dirty_list, &oc->dirty_head))
 		del_from_dirty_list(entry);
 	sd_destroy_lock(&entry->lock);
 	free(entry);
@@ -417,7 +417,7 @@ static int write_cache_object(struct object_cache_entry *entry, void *buf,
 	write_lock_cache(oc);
 	if (writeback) {
 		entry->bmap |= calc_object_bmap(oid, count, offset);
-		if (!list_linked(&entry->dirty_list))
+		if (!list_linked(&entry->dirty_list, &oc->dirty_head))
 			add_to_dirty_list(entry);
 	}
 	list_move_tail(&entry->lru_list, &oc->lru_head);
diff --git a/sheep/request.c b/sheep/request.c
index 5113fca..863b9a5 100644
--- a/sheep/request.c
+++ b/sheep/request.c
@@ -15,9 +15,9 @@
 
 static void requeue_request(struct request *req);
 
-static void del_requeue_request(struct request *req)
+static void del_requeue_request(struct request *req, struct list_head *head)
 {
-	list_del(&req->request_list);
+	list_del(&req->request_list, head);
 	requeue_request(req);
 }
 
@@ -217,7 +217,7 @@ void wakeup_requests_on_epoch(void)
 			assert(is_gateway_op(req->op));
 			sd_debug("gateway %"PRIx64, req->rq.obj.oid);
 			req->rq.epoch = sys->cinfo.epoch;
-			del_requeue_request(req);
+			del_requeue_request(req, &pending_list);
 			break;
 		case SD_RES_NEW_NODE_VER:
 			/*
@@ -226,7 +226,7 @@ void wakeup_requests_on_epoch(void)
 			 */
 			assert(!is_gateway_op(req->op));
 			sd_debug("peer %"PRIx64, req->rq.obj.oid);
-			del_requeue_request(req);
+			del_requeue_request(req, &pending_list);
 			break;
 		default:
 			break;
@@ -248,7 +248,7 @@ void wakeup_requests_on_oid(uint64_t oid)
 		if (req->local_oid != oid)
 			continue;
 		sd_debug("retry %" PRIx64, req->local_oid);
-		del_requeue_request(req);
+		del_requeue_request(req, &pending_list);
 	}
 	list_splice_init(&pending_list, &sys->req_wait_queue);
 }
@@ -262,7 +262,7 @@ void wakeup_all_requests(void)
 
 	list_for_each_entry(req, &pending_list, request_list) {
 		sd_debug("%"PRIx64, req->rq.obj.oid);
-		del_requeue_request(req);
+		del_requeue_request(req, &pending_list);
 	}
 }
 
@@ -691,7 +691,7 @@ static void clear_client_info(struct client_info *ci)
 	sd_debug("connection seems to be dead");
 
 	list_for_each_entry(req, &ci->done_reqs, request_list) {
-		list_del(&req->request_list);
+		list_del(&req->request_list, &ci->done_reqs);
 		free_request(req);
 	}
 
@@ -771,7 +771,7 @@ static void client_handler(int fd, int events, void *data)
 		assert(ci->tx_req == NULL);
 		ci->tx_req = list_first_entry(&ci->done_reqs, struct request,
 					      request_list);
-		list_del(&ci->tx_req->request_list);
+		list_del(&ci->tx_req->request_list, &ci->done_reqs);
 
 		/*
 		 * Increment refcnt so that the client_info isn't freed while
@@ -868,7 +868,7 @@ static void local_req_handler(int listen_fd, int events, void *data)
 	pthread_mutex_unlock(&sys->local_req_lock);
 
 	list_for_each_entry(req, &pending_list, request_list) {
-		list_del(&req->request_list);
+		list_del(&req->request_list, &pending_list);
 		queue_request(req);
 	}
 }
diff --git a/sheep/vdi.c b/sheep/vdi.c
index 64f4f9c..490f69e 100644
--- a/sheep/vdi.c
+++ b/sheep/vdi.c
@@ -855,7 +855,7 @@ static void delete_one_done(struct work *work)
 		return;
 	}
 
-	list_del(&dw->list);
+	list_del(&dw->list, &deletion_work_list);
 
 	put_request(req);
 
diff --git a/shepherd/shepherd.c b/shepherd/shepherd.c
index fd59229..449da0f 100644
--- a/shepherd/shepherd.c
+++ b/shepherd/shepherd.c
@@ -139,6 +139,8 @@ static int notify_remove_sheep(struct sheep *leaving)
 	return failed;
 }
 
+static LIST_HEAD(join_wait_queue);
+
 static void remove_handler(int fd, int events, void *data)
 {
 	struct sheep *s;
@@ -179,8 +181,8 @@ del:
 	unregister_event(s->fd);
 	close(s->fd);
 
-	list_del(&s->sheep_list);
-	list_del(&s->join_wait_list);
+	list_del(&s->sheep_list, &sheep_list_head);
+	list_del(&s->join_wait_list, &join_wait_queue);
 	free(s);
 
 	if (--nr_removed)
@@ -190,8 +192,6 @@ end:
 	sd_debug("nodes which failed during remove_handler(): %d", failed);
 }
 
-static LIST_HEAD(join_wait_queue);
-
 static int release_joining_sheep(void)
 {
 	ssize_t wbytes;
@@ -205,7 +205,7 @@ retry:
 
 	waiting = list_first_entry(&join_wait_queue,
 				struct sheep, join_wait_list);
-	list_del(&waiting->join_wait_list);
+	list_del(&waiting->join_wait_list, &join_wait_queue);
 
 	memset(&snd, 0, sizeof(snd));
 	snd.type = SPH_SRV_MSG_JOIN_RETRY;
-- 
1.8.1.2




More information about the sheepdog mailing list