static void shm_queue_init(void) { int ret; shmfd = open(shmfile, O_CREAT | O_RDWR, 0644); if (shmfd < 0) panic("cannot open shared file, %s\n", shmfile); shm_queue_lock(); ret = ftruncate(shmfd, sizeof(*shm_queue)); assert(ret == 0); shm_queue = mmap(0, sizeof(*shm_queue), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); assert(shm_queue != MAP_FAILED); if (is_shm_queue_valid()) event_pos = shm_queue->pos; else { /* initialize shared memory */ event_pos = 0; ret = ftruncate(shmfd, 0); assert(ret == 0); ret = ftruncate(shmfd, sizeof(*shm_queue)); assert(ret == 0); shm_queue_set_chksum(); } shm_queue_unlock(); }
/* * Returns true if an event is processed */ static bool local_process_event(void) { struct local_event *ev; enum cluster_join_result res; ev = shm_queue_peek(); if (!ev) return false; switch (ev->type) { case EVENT_JOIN_REQUEST: if (!node_eq(&ev->nodes[0], &this_node)) return false; res = sd_check_join_cb(&ev->sender, ev->buf); ev->join_result = res; ev->type = EVENT_JOIN_RESPONSE; msync(ev, sizeof(*ev), MS_SYNC); shm_queue_notify(); if (res == CJ_RES_MASTER_TRANSFER) { eprintf("failed to join sheepdog cluster: " "please retry when master is up\n"); shm_queue_unlock(); exit(1); } return false; case EVENT_JOIN_RESPONSE: if (ev->join_result == CJ_RES_MASTER_TRANSFER) { /* FIXME: This code is tricky, but Sheepdog assumes that */ /* nr_nodes = 1 when join_result = MASTER_TRANSFER... */ ev->nr_nodes = 1; ev->nodes[0] = this_node; ev->pids[0] = getpid(); shm_queue_set_chksum(); } 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; } return true; }
static void shm_queue_notify(void) { int i; size_t nr; pid_t pids[SD_MAX_NODES]; shm_queue_set_chksum(); nr = get_nodes(NULL, pids); for (i = 0; i < nr; i++) kill(pids[i], SIGUSR1); }
static int local_dispatch(void) { int ret; struct signalfd_siginfo siginfo; struct local_event *ev; enum cluster_join_result res; static struct work work = { .fn = local_block, .done = local_block_done, }; dprintf("read siginfo\n"); ret = read(sigfd, &siginfo, sizeof(siginfo)); assert(ret == sizeof(siginfo)); shm_queue_lock(); ev = shm_queue_peek(); if (!ev) goto out; switch (ev->type) { case EVENT_JOIN: if (ev->blocked) { if (node_cmp(&ev->nodes[0], &this_node) == 0) { res = local_check_join_cb(&ev->sender, ev->buf); ev->join_result = res; ev->blocked = 0; msync(ev, sizeof(*ev), MS_SYNC); shm_queue_notify(); if (res == CJ_RES_MASTER_TRANSFER) { eprintf("failed to join sheepdog cluster: please retry when master is up\n"); shm_queue_unlock(); exit(1); } } goto out; } if (ev->join_result == CJ_RES_MASTER_TRANSFER) { /* FIXME: This code is tricky, but Sheepdog assumes that */ /* nr_nodes = 1 when join_result = MASTER_TRANSFER... */ ev->nr_nodes = 1; ev->nodes[0] = this_node; ev->pids[0] = getpid(); shm_queue_set_chksum(); } lhdlrs.join_handler(&ev->sender, ev->nodes, ev->nr_nodes, ev->join_result, ev->buf); break; case EVENT_LEAVE: lhdlrs.leave_handler(&ev->sender, ev->nodes, ev->nr_nodes); break; case EVENT_NOTIFY: if (ev->blocked) { if (node_cmp(&ev->sender, &this_node) == 0) { if (!ev->callbacked) { queue_work(local_block_wq, &work); ev->callbacked = 1; } } goto out; } lhdlrs.notify_handler(&ev->sender, ev->buf, ev->buf_len); break; } shm_queue_pop(); out: shm_queue_unlock(); return 0; }