Egbert Eich
3317d2586d
If-connect-fails-let-other-side-accept-connection-and-come-back.patch by: Reset-delay-for-unixsock-connect-from-inotify.patch: Upstream chose to fix bsc#1101647 slightly differently. OBS-URL: https://build.opensuse.org/package/show/network:cluster/conman?expand=0&rev=29
136 lines
5.4 KiB
Diff
136 lines
5.4 KiB
Diff
From: Egbert Eich <eich@suse.com>
|
|
Date: Wed Jul 18 11:26:07 2018 +0200
|
|
Subject: Reset delay for unixsock connect from inotify
|
|
Patch-mainline: Not yet
|
|
Git-repo: https://github.com/dun/conman
|
|
Git-commit: 8f5bd09162307a23efb8532a95c4e4a562ce30fe
|
|
References: bsc#1101647
|
|
|
|
Consoles over UNIX domain sockets use inotify to detect when their
|
|
socket appears in the filesystem. This inotify event is triggered
|
|
when the remote has successfully called bind(). However, the remote
|
|
may not have called listen() before the inotify event is serviced
|
|
by conmand. In such a case, connect() will fail with ECONNREFUSED,
|
|
after which the connection delay will be increased before the next
|
|
connection attempt. This can result in connection establishment
|
|
taking up to UNIXSOCK_MAX_TIMEOUT seconds once the socket appears.
|
|
|
|
To handle this case, reset the connection delay to UNIXSOCK_MIN_TIMEOUT
|
|
when a connection attempt triggered by inotify fails.
|
|
|
|
[cdunlap@llnl.gov: Restructured to use isViaInotify flag]
|
|
Signed-off-by: Egbert Eich <eich@suse.com>
|
|
Signed-off-by: Chris Dunlap <cdunlap@llnl.gov>
|
|
Closes #28
|
|
Closes #29
|
|
Signed-off-by: Egbert Eich <eich@suse.de>
|
|
---
|
|
server-unixsock.c | 36 ++++++++++++++++++++++++++++++++++--
|
|
server.h | 1 +
|
|
2 files changed, 35 insertions(+), 2 deletions(-)
|
|
diff --git a/server-unixsock.c b/server-unixsock.c
|
|
index e683ec7..b44adb4 100644
|
|
--- a/server-unixsock.c
|
|
+++ b/server-unixsock.c
|
|
@@ -45,6 +45,7 @@
|
|
#include "util-str.h"
|
|
|
|
|
|
+static int open_unixsock_obj_via_inotify(obj_t *unixsock);
|
|
static size_t max_unixsock_dev_strlen(void);
|
|
static int connect_unixsock_obj(obj_t *unixsock);
|
|
static int disconnect_unixsock_obj(obj_t *unixsock);
|
|
@@ -140,6 +141,7 @@ obj_t * create_unixsock_obj(server_conf_t *conf, char *name, char *dev,
|
|
unixsock->aux.unixsock.logfile = NULL;
|
|
unixsock->aux.unixsock.timer = -1;
|
|
unixsock->aux.unixsock.state = CONMAN_UNIXSOCK_DOWN;
|
|
+ unixsock->aux.unixsock.isViaInotify = 0;
|
|
unixsock->aux.unixsock.delay = UNIXSOCK_MIN_TIMEOUT;
|
|
/*
|
|
* Add obj to the master conf->objs list.
|
|
@@ -147,7 +149,7 @@ obj_t * create_unixsock_obj(server_conf_t *conf, char *name, char *dev,
|
|
list_append(conf->objs, unixsock);
|
|
|
|
rv = inevent_add(unixsock->aux.unixsock.dev,
|
|
- (inevent_cb_f) open_unixsock_obj, unixsock);
|
|
+ (inevent_cb_f) open_unixsock_obj_via_inotify, unixsock);
|
|
if (rv < 0) {
|
|
log_msg(LOG_INFO,
|
|
"Console [%s] unable to register device \"%s\" for inotify events",
|
|
@@ -177,6 +179,23 @@ int open_unixsock_obj(obj_t *unixsock)
|
|
}
|
|
|
|
|
|
+static int open_unixsock_obj_via_inotify(obj_t *unixsock)
|
|
+{
|
|
+/* Opens the specified 'unixsock' obj via an inotify callback.
|
|
+ * Returns 0 if the console is successfully opened; o/w, returns -1.
|
|
+ */
|
|
+ unixsock_obj_t *auxp;
|
|
+
|
|
+ assert(unixsock != NULL);
|
|
+ assert(is_unixsock_obj(unixsock));
|
|
+
|
|
+ auxp = &(unixsock->aux.unixsock);
|
|
+ auxp->isViaInotify = 1;
|
|
+
|
|
+ return(open_unixsock_obj(unixsock));
|
|
+}
|
|
+
|
|
+
|
|
static size_t max_unixsock_dev_strlen(void)
|
|
{
|
|
/* Returns the maximum string length allowed for a unix domain device.
|
|
@@ -199,6 +218,7 @@ static int connect_unixsock_obj(obj_t *unixsock)
|
|
* Returns 0 if the connection is successfully completed; o/w, returns -1.
|
|
*/
|
|
unixsock_obj_t *auxp;
|
|
+ int isViaInotify;
|
|
struct stat st;
|
|
struct sockaddr_un saddr;
|
|
size_t n;
|
|
@@ -210,6 +230,9 @@ static int connect_unixsock_obj(obj_t *unixsock)
|
|
|
|
auxp = &(unixsock->aux.unixsock);
|
|
|
|
+ isViaInotify = auxp->isViaInotify;
|
|
+ auxp->isViaInotify = 0;
|
|
+
|
|
if (auxp->timer >= 0) {
|
|
(void) tpoll_timeout_cancel(tp_global, auxp->timer);
|
|
auxp->timer = -1;
|
|
@@ -250,11 +273,20 @@ static int connect_unixsock_obj(obj_t *unixsock)
|
|
set_fd_nonblocking(unixsock->fd);
|
|
set_fd_closed_on_exec(unixsock->fd);
|
|
|
|
- /* FIXME: Check to see if connect() on a nonblocking unix domain socket
|
|
+ /* If a connect() triggered via an inotify event fails, reset the
|
|
+ * reconnect delay to its minimum to quickly re-attempt the connection.
|
|
+ * This handles the case where the remote has successfully called bind()
|
|
+ * (triggering the inotify event) but has not yet called listen().
|
|
+ * FIXME: Check to see if connect() on a nonblocking unix domain socket
|
|
* can return EINPROGRESS. I don't think it can.
|
|
*/
|
|
if (connect(unixsock->fd,
|
|
(struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
|
|
+ if (isViaInotify) {
|
|
+ auxp->delay = UNIXSOCK_MIN_TIMEOUT;
|
|
+ DPRINTF((15, "Reset [%s] reconnect delay due to inotify event\n",
|
|
+ unixsock->name));
|
|
+ }
|
|
log_msg(LOG_INFO, "Console [%s] cannot connect to device \"%s\": %s",
|
|
unixsock->name, auxp->dev, strerror(errno));
|
|
return(disconnect_unixsock_obj(unixsock));
|
|
diff --git a/server.h b/server.h
|
|
index 8ccbcf9..6cc7c1b 100644
|
|
--- a/server.h
|
|
+++ b/server.h
|
|
@@ -180,6 +180,7 @@ typedef struct unixsock_obj { /* UNIXSOCK AUX OBJ DATA: */
|
|
int timer; /* timer id for reconnects */
|
|
int delay; /* secs 'til next reconnect attempt */
|
|
unsigned state:1; /* unixsock_state_t conn state */
|
|
+ unsigned isViaInotify:1; /* true if triggered via inotify */
|
|
} unixsock_obj_t;
|
|
|
|
/* Refer to struct ipmiconsole_ipmi_config in <ipmiconsole.h>.
|