From 2464a326b8cd53e22b3389b6bdd49d7aefd9fad2 Mon Sep 17 00:00:00 2001 From: Lon Hohberger Date: Fri, 21 Aug 2009 15:31:02 -0400 Subject: [PATCH] Drop duplicate fencing requests XVM shotguns packets from all interfaces on the system. This means the server can get the same request from multiple interfaces at the same time. This records a history of fencing requests and drops duplicates for a few seconds. Signed-off-by: Lon Hohberger --- server/mcast.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/server/mcast.c b/server/mcast.c index 2b2f912..e58cb3c 100644 --- a/server/mcast.c +++ b/server/mcast.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -72,9 +73,18 @@ typedef struct _mcast_options { unsigned int flags; } mcast_options; + +typedef struct _history_node { + list_head(); + fence_req_t req; + time_t when; +} history_node; + + typedef struct _mcast_info { uint64_t magic; void *priv; + history_node *history; char key[MAX_KEY_LEN]; mcast_options args; const fence_callbacks_t *cb; @@ -84,6 +94,56 @@ typedef struct _mcast_info { } mcast_info; +/* + * See if we fenced this node recently (successfully) + * If so, ignore the request for a few seconds. + * + * We purge our history when the entries time out. + */ +static int +check_history(history_node **list, fence_req_t *req) +{ + history_node *entry = NULL; + time_t now; + int x; + + now = time(NULL); + +loop_again: + list_for(list, entry, x) { + if (entry->when < (now - 10)) { + list_remove(list, entry); + free(entry); + goto loop_again; + } + + if (entry->req.request == req->request && + !strcasecmp((const char *)entry->req.domain, + (const char *)req->domain)) { + return 1; + } + } + return 0; +} + + +static int +record_history(history_node **list, fence_req_t *req) +{ + history_node *entry = NULL; + + entry = malloc(sizeof(*entry)); + if (!entry) + return -1; /* non-fatal */ + + memset(entry, 0, sizeof(*entry)); + memcpy(&entry->req, req, sizeof(*req)); + entry->when = time(NULL); + list_insert(list, entry); + return 0; +} + + static int connect_tcp(fence_req_t *req, fence_auth_type_t auth, void *key, size_t key_len) @@ -181,6 +241,12 @@ do_fence_request_tcp(fence_req_t *req, mcast_info *info) if (write(fd, &response, 1) < 0) { perror("write"); } + + /* XVM shotguns multicast packets, so we want to avoid + * acting on the same request multiple times if the first + * attempt was successful. + */ + record_history(&info->history, req); out: if (fd != -1) close(fd); @@ -246,6 +312,11 @@ mcast_dispatch(srv_context_t c, struct timeval *timeout) } printf("Request %d domain %s\n", data.request, data.domain); + + if (check_history(&info->history, &data) == 1) { + printf("We just did this request; dropping packet\n"); + return 0; + } switch(info->args.auth) { case AUTH_NONE: