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 <lhh@redhat.com>
This commit is contained in:
parent
4ba33b27b9
commit
2464a326b8
@ -42,6 +42,7 @@
|
||||
#include <pthread.h>
|
||||
#include <nss.h>
|
||||
#include <libgen.h>
|
||||
#include <list.h>
|
||||
#include <simpleconfig.h>
|
||||
#include <server_plugin.h>
|
||||
|
||||
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user