[sheepdog] [PATCH 3/7] local: use a different queue for block operations
MORITA Kazutaka
morita.kazutaka at lab.ntt.co.jp
Tue Sep 4 10:05:39 CEST 2012
This is the same change which was done in corosync driver to avoid
deadlock of vdi creations.
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
sheep/cluster/local.c | 102 +++++++++++++++++++++++++++++++------------------
1 files changed, 65 insertions(+), 37 deletions(-)
diff --git a/sheep/cluster/local.c b/sheep/cluster/local.c
index 1fcce19..f861d23 100644
--- a/sheep/cluster/local.c
+++ b/sheep/cluster/local.c
@@ -30,7 +30,8 @@
const char *shmfile = "/tmp/sheepdog_shm";
static int shmfd;
static int sigfd;
-static int event_pos;
+static int block_event_pos;
+static int nonblock_event_pos;
static struct sd_node this_node;
enum local_event_type {
@@ -45,6 +46,8 @@ struct local_event {
enum local_event_type type;
struct sd_node sender;
+ bool removed;
+
size_t buf_len;
uint8_t buf[SD_MAX_EVENT_BUF_SIZE];
@@ -59,8 +62,10 @@ struct local_event {
/* shared memory queue */
struct shm_queue {
- int pos;
- struct local_event events[MAX_EVENTS];
+ int block_event_pos;
+ struct local_event block_events[MAX_EVENTS];
+ int nonblock_event_pos;
+ struct local_event nonblock_events[MAX_EVENTS];
} *shm_queue;
static void shm_queue_lock(void)
@@ -73,16 +78,11 @@ static void shm_queue_unlock(void)
flock(shmfd, LOCK_UN);
}
-static int shm_queue_empty(void)
-{
- return event_pos == shm_queue->pos;
-}
-
static size_t get_nodes(struct sd_node *n, pid_t *p)
{
struct local_event *ev;
- ev = shm_queue->events + shm_queue->pos;
+ ev = shm_queue->nonblock_events + shm_queue->nonblock_event_pos;
if (n)
memcpy(n, ev->nodes, sizeof(ev->nodes));
@@ -97,31 +97,57 @@ static int process_exists(pid_t pid)
return kill(pid, 0) == 0;
}
-static struct local_event *shm_queue_peek(void)
+static struct local_event *shm_queue_peek_block_event(void)
{
- if (shm_queue_empty())
- return NULL;
-
- return shm_queue->events + (event_pos + 1) % MAX_EVENTS;
+ return shm_queue->block_events + (block_event_pos + 1) % MAX_EVENTS;
}
-static void shm_queue_push(struct local_event *ev)
+static struct local_event *shm_queue_peek_nonblock_event(void)
{
- shm_queue->pos = (shm_queue->pos + 1) % MAX_EVENTS;
- shm_queue->events[shm_queue->pos] = *ev;
-
- msync(shm_queue->events + shm_queue->pos, sizeof(*ev), MS_SYNC);
- msync(&shm_queue->pos, sizeof(shm_queue->pos), MS_SYNC);
+ return shm_queue->nonblock_events +
+ (nonblock_event_pos + 1) % MAX_EVENTS;
}
-static struct local_event *shm_queue_pop(void)
+static struct local_event *shm_queue_peek(void)
{
- if (shm_queue_empty())
+ /* try to peek nonblock queue first */
+ if (nonblock_event_pos != shm_queue->nonblock_event_pos)
+ return shm_queue_peek_nonblock_event();
+ else if (block_event_pos != shm_queue->block_event_pos)
+ return shm_queue_peek_block_event();
+ else
return NULL;
+}
- event_pos = (event_pos + 1) % MAX_EVENTS;
+static void shm_queue_push(struct local_event *ev)
+{
+ if (ev->type == EVENT_BLOCK) {
+ shm_queue->block_event_pos =
+ (shm_queue->block_event_pos + 1) % MAX_EVENTS;
+ shm_queue->block_events[shm_queue->block_event_pos] = *ev;
+
+ msync(shm_queue->block_events +
+ shm_queue->block_event_pos, sizeof(*ev), MS_SYNC);
+ msync(&shm_queue->block_event_pos,
+ sizeof(shm_queue->block_event_pos), MS_SYNC);
+ } else {
+ shm_queue->nonblock_event_pos =
+ (shm_queue->nonblock_event_pos + 1) % MAX_EVENTS;
+ shm_queue->nonblock_events[shm_queue->nonblock_event_pos] = *ev;
+
+ msync(shm_queue->nonblock_events +
+ shm_queue->nonblock_event_pos, sizeof(*ev), MS_SYNC);
+ msync(&shm_queue->nonblock_event_pos,
+ sizeof(shm_queue->nonblock_event_pos), MS_SYNC);
+ }
+}
- return shm_queue->events + event_pos;
+static void shm_queue_remove(struct local_event *ev)
+{
+ if (ev == shm_queue_peek_block_event())
+ block_event_pos = (block_event_pos + 1) % MAX_EVENTS;
+ else
+ nonblock_event_pos = (nonblock_event_pos + 1) % MAX_EVENTS;
}
static void shm_queue_notify(void)
@@ -171,11 +197,13 @@ static void shm_queue_init(void)
PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
assert(shm_queue != MAP_FAILED);
- if (is_shm_queue_valid())
- event_pos = shm_queue->pos;
- else {
+ if (is_shm_queue_valid()) {
+ block_event_pos = shm_queue->block_event_pos;
+ nonblock_event_pos = shm_queue->nonblock_event_pos;
+ } else {
/* initialize shared memory */
- event_pos = 0;
+ block_event_pos = 0;
+ nonblock_event_pos = 0;
ret = ftruncate(shmfd, 0);
assert(ret == 0);
ret = ftruncate(shmfd, sizeof(*shm_queue));
@@ -305,15 +333,12 @@ static void local_unblock(void *msg, size_t msg_len)
shm_queue_lock();
- ev = shm_queue_peek();
+ ev = shm_queue_peek_block_event();
- ev->type = EVENT_NOTIFY;
- ev->buf_len = msg_len;
- if (msg)
- memcpy(ev->buf, msg, msg_len);
+ ev->removed = true;
msync(ev, sizeof(*ev), MS_SYNC);
- shm_queue_notify();
+ add_event(EVENT_NOTIFY, &this_node, msg, msg_len);
shm_queue_unlock();
}
@@ -330,6 +355,9 @@ static bool local_process_event(void)
if (!ev)
return false;
+ if (ev->removed)
+ goto out;
+
switch (ev->type) {
case EVENT_JOIN_REQUEST:
if (!node_eq(&ev->nodes[0], &this_node))
@@ -356,24 +384,24 @@ static bool local_process_event(void)
ev->nr_nodes = 1;
ev->nodes[0] = this_node;
ev->pids[0] = getpid();
+ msync(ev, sizeof(*ev), MS_SYNC);
}
sd_join_handler(&ev->sender, ev->nodes, ev->nr_nodes,
ev->join_result, ev->buf);
- shm_queue_pop();
break;
case EVENT_LEAVE:
sd_leave_handler(&ev->sender, ev->nodes, ev->nr_nodes);
- shm_queue_pop();
break;
case EVENT_BLOCK:
sd_block_handler(&ev->sender);
return false;
case EVENT_NOTIFY:
sd_notify_handler(&ev->sender, ev->buf, ev->buf_len);
- shm_queue_pop();
break;
}
+out:
+ shm_queue_remove(ev);
return true;
}
--
1.7.2.5
More information about the sheepdog
mailing list