aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeebs <seebs@seebs.net>2018-01-16 20:06:30 -0600
committerSeebs <seebs@seebs.net>2018-01-16 20:06:30 -0600
commit449c234d3030328fb997b309511bb54598848a05 (patch)
tree6e2d2db1800e0d4cf559e762771ab20e57b52ac6
parentd107418abf0296af1159d9ec0cd5af49a166ef4b (diff)
downloadpseudo-449c234d3030328fb997b309511bb54598848a05.tar.gz
pseudo-449c234d3030328fb997b309511bb54598848a05.tar.bz2
pseudo-449c234d3030328fb997b309511bb54598848a05.zip
Half-undo FASTOP
FASTOP is logically fine as long as there's no errors, but if there could be errors, we lose error detection. Responding instantly with a trivial ACK for FASTOP messages slightly reduces performance but improves reliability and seems to work better. Signed-off-by: Seebs <seebs@seebs.net>
-rw-r--r--ChangeLog.txt2
-rw-r--r--pseudo_client.c22
-rw-r--r--pseudo_server.c94
3 files changed, 63 insertions, 55 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 4f58922..d334dec 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -9,6 +9,8 @@
* (seebs) add wrapper for statvfs (based on patch from
<dan.dedrick@gmail.com>)
* (seebs) Call this 1.9.0.
+ * (seebs) Experimental-ish: Require a response even for FASTOP
+ just to confirm delivery of message/server availability.
2017-12-22:
* (seebs) handle the pathological case of LINKAT with
diff --git a/pseudo_client.c b/pseudo_client.c
index 2a4c106..ec07c07 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -1331,21 +1331,17 @@ pseudo_client_request(pseudo_msg_t *msg, size_t len, const char *path) {
* indicating a successful send.
*/
pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "sent!\n");
- if (msg->type != PSEUDO_MSG_FASTOP) {
- response = pseudo_msg_receive(connect_fd);
- if (!response) {
- pseudo_debug(PDBGF_CLIENT, "expected response did not occur; retrying\n");
+ response = pseudo_msg_receive(connect_fd);
+ if (!response) {
+ pseudo_debug(PDBGF_CLIENT, "expected response did not occur; retrying\n");
+ } else {
+ if (response->type != PSEUDO_MSG_ACK) {
+ pseudo_debug(PDBGF_CLIENT, "got non-ack response %d\n", response->type);
+ return 0;
} else {
- if (response->type != PSEUDO_MSG_ACK) {
- pseudo_debug(PDBGF_CLIENT, "got non-ack response %d\n", response->type);
- return 0;
- } else {
- pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "got response type %d\n", response->type);
- return response;
- }
+ pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "got response type %d\n", response->type);
+ return response;
}
- } else {
- return 0;
}
}
pseudo_diag("pseudo: server connection persistently failed, aborting.\n");
diff --git a/pseudo_server.c b/pseudo_server.c
index 8c6805b..dac3258 100644
--- a/pseudo_server.c
+++ b/pseudo_server.c
@@ -25,6 +25,7 @@
#include <unistd.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -472,7 +473,10 @@ static int
serve_client(int i) {
pseudo_msg_t *in;
int rc;
+ struct timeval tv1, tv2;
+ gettimeofday(&tv1, NULL);
+ ++messages;
pseudo_debug(PDBGF_SERVER, "message from client %d [%d:%s - %s] fd %d\n",
i, (int) clients[i].pid,
clients[i].program ? clients[i].program : "???",
@@ -509,6 +513,11 @@ serve_client(int i) {
}
pseudo_debug(PDBGF_SERVER, "\n");
}
+ if (in->type == PSEUDO_MSG_SHUTDOWN && !clients[i].pid) {
+ pseudo_debug(PDBGF_SERVER, "shutdown request from client %d [pid %d]\n",
+ i, in->client);
+ in->client = clients[i].pid;
+ }
/* sanity-check client ID */
if (in->client != clients[i].pid) {
pseudo_debug(PDBGF_SERVER, "uh-oh, expected pid %d for client %d, got %d\n",
@@ -518,8 +527,6 @@ serve_client(int i) {
* pseudo_server_response.
*/
if (in->type != PSEUDO_MSG_SHUTDOWN) {
- if (in->type == PSEUDO_MSG_FASTOP)
- send_response = 0;
/* most messages don't need these, but xattr may */
response_path = 0;
response_pathlen = -1;
@@ -536,6 +543,20 @@ serve_client(int i) {
} else {
in->pathlen = 0;
}
+ if (in->type == PSEUDO_MSG_FASTOP) {
+ /* respond instantly */
+ send_response = 0;
+ int t_type = in->type;
+ int t_pathlen = in->pathlen;
+ in->type = PSEUDO_MSG_ACK;
+ in->pathlen = 0;
+ if ((rc = pseudo_msg_send(clients[i].fd, in, in->pathlen, response_path)) != 0) {
+ pseudo_debug(PDBGF_SERVER, "failed to send response to client %d [%d]: %d (%s)\n",
+ i, (int) clients[i].pid, rc, strerror(errno));
+ }
+ in->type = t_type;
+ in->pathlen = t_pathlen;
+ }
} else {
/* the server's listen fd is "a client", and
* so is the program connecting to request a shutdown.
@@ -575,15 +596,28 @@ serve_client(int i) {
rc = 1;
}
free(response_path);
- return rc;
} else {
/* this should not be happening, but the exceptions aren't
* being detected in select() for some reason.
*/
pseudo_debug(PDBGF_SERVER, "client %d: no message\n", (int) clients[i].pid);
close_client(i);
- return 0;
+ rc = 0;
+ }
+
+ gettimeofday(&tv2, NULL);
+ if (rc == 0)
+ ++responses;
+ message_time.tv_sec += (tv2.tv_sec - tv1.tv_sec);
+ message_time.tv_usec += (tv2.tv_usec - tv1.tv_usec);
+ if (message_time.tv_usec < 0) {
+ message_time.tv_usec += 1000000;
+ --message_time.tv_sec;
+ } else while (message_time.tv_usec > 1000000) {
+ message_time.tv_usec -= 1000000;
+ ++message_time.tv_sec;
}
+ return rc;
}
#ifdef PSEUDO_EPOLL
@@ -698,22 +732,12 @@ static void pseudo_server_loop_epoll(void)
}
}
} else {
- struct timeval tv1, tv2;
- int rc;
- gettimeofday(&tv1, NULL);
- rc = serve_client(events[i].data.u64);
- gettimeofday(&tv2, NULL);
- ++messages;
- if (rc == 0)
- ++responses;
- message_time.tv_sec += (tv2.tv_sec - tv1.tv_sec);
- message_time.tv_usec += (tv2.tv_usec - tv1.tv_usec);
- if (message_time.tv_usec < 0) {
- message_time.tv_usec += 1000000;
- --message_time.tv_sec;
- } else while (message_time.tv_usec > 1000000) {
- message_time.tv_usec -= 1000000;
- ++message_time.tv_sec;
+ int n = 0;
+ ioctl(clients[i].fd, FIONREAD, &n);
+ if (n == 0) {
+ close_client(i);
+ } else {
+ serve_client(i);
}
}
if (die_forcefully)
@@ -805,8 +829,8 @@ pseudo_server_loop(void) {
pdb_log_msg(SEVERITY_INFO, NULL, NULL, NULL, "server started (pid %d)", getpid());
FD_ZERO(&reads);
- FD_ZERO(&writes);
FD_ZERO(&events);
+ FD_ZERO(&writes);
FD_SET(clients[0].fd, &reads);
FD_SET(clients[0].fd, &events);
max_fd = clients[0].fd;
@@ -844,28 +868,15 @@ pseudo_server_loop(void) {
} else if (rc > 0) {
loop_timeout = pseudo_server_timeout;
for (i = 1; i <= highest_client; ++i) {
- if (clients[i].fd == -1)
+ if (clients[i].fd == -1) {
continue;
- if (FD_ISSET(clients[i].fd, &events)) {
- /* this should happen but doesn't... */
- close_client(i);
} else if (FD_ISSET(clients[i].fd, &reads)) {
- struct timeval tv1, tv2;
- int rc;
- gettimeofday(&tv1, NULL);
- rc = serve_client(i);
- gettimeofday(&tv2, NULL);
- ++messages;
- if (rc == 0)
- ++responses;
- message_time.tv_sec += (tv2.tv_sec - tv1.tv_sec);
- message_time.tv_usec += (tv2.tv_usec - tv1.tv_usec);
- if (message_time.tv_usec < 0) {
- message_time.tv_usec += 1000000;
- --message_time.tv_sec;
- } else while (message_time.tv_usec > 1000000) {
- message_time.tv_usec -= 1000000;
- ++message_time.tv_sec;
+ int n = 0;
+ ioctl(clients[i].fd, FIONREAD, &n);
+ if (n == 0) {
+ close_client(i);
+ } else {
+ serve_client(i);
}
}
if (die_forcefully)
@@ -943,7 +954,6 @@ pseudo_server_loop(void) {
if (clients[i].fd != -1) {
++current_clients;
FD_SET(clients[i].fd, &reads);
- FD_SET(clients[i].fd, &events);
if (clients[i].fd > max_fd)
max_fd = clients[i].fd;
}