9pmount-vsock: retry the mount if it fails

The client on the host may time-out the connection attempt after we have
accepted it. If the mount fails, sleep for 1s and try again.

Signed-off-by: David Scott <dave.scott@docker.com>
This commit is contained in:
David Scott 2016-05-21 12:09:54 +01:00
parent 1dfe82981a
commit a19630c1f4

View File

@ -13,6 +13,7 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <err.h> #include <err.h>
#include <sys/wait.h>
#include "hvsock.h" #include "hvsock.h"
@ -31,7 +32,7 @@ void fatal(const char *msg)
exit(1); exit(1);
} }
static void handle(int fd, char *tag, char *path) static int handle(int fd, char *tag, char *path)
{ {
char *options = NULL; char *options = NULL;
if (asprintf(&options, "trans=fd,dfltuid=1001,dfltgid=50,version=9p2000,rfdno=%d,wfdno=%d", fd, fd) < 0){ if (asprintf(&options, "trans=fd,dfltuid=1001,dfltgid=50,version=9p2000,rfdno=%d,wfdno=%d", fd, fd) < 0){
@ -43,8 +44,17 @@ static void handle(int fd, char *tag, char *path)
tag, path, tag, path,
NULL NULL
}; };
execv(mount, argv); pid_t pid = fork();
fatal("execv()"); if (pid == 0) {
execv(mount, argv);
fatal("execv()");
}
int status;
if (waitpid(pid, &status, 0) == -1) {
syslog(LOG_CRIT, "waitpid failed: %d. %s", errno, strerror(errno));
exit(1);
}
return WEXITSTATUS(status);
} }
static int create_listening_socket(GUID serviceid) { static int create_listening_socket(GUID serviceid) {
@ -195,17 +205,25 @@ int main(int argc, char **argv)
} }
openlog(argv[0], LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); openlog(argv[0], LOG_CONS | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);
int sock = -1; for (;;) {
if (mode == LISTEN) { int sock = -1;
syslog(LOG_INFO, "starting in listening mode with serviceid=%s", serviceid); if (mode == LISTEN) {
int lsocket = create_listening_socket(sid); syslog(LOG_INFO, "starting in listening mode with serviceid=%s, tag=%s, path=%s", serviceid, tag, path);
sock = accept_socket(lsocket); int lsocket = create_listening_socket(sid);
close(lsocket); sock = accept_socket(lsocket);
} else { close(lsocket);
syslog(LOG_INFO, "starting in connect mode with serviceid=%s", serviceid); } else {
sock = connect_socket(sid); syslog(LOG_INFO, "starting in connect mode with serviceid=%s, tag=%s, path=%s", serviceid, tag, path);
sock = connect_socket(sid);
}
int r = handle(sock, tag, path);
close(sock);
if (r == 0) {
syslog(LOG_INFO, "mount successful for serviceid=%s tag=%s path=%s", serviceid, tag, path);
exit(0);
}
/* This can happen if the client times out the connection after we accept it */
syslog(LOG_CRIT, "mount failed with %d for serviceid=%s tag=%s path=%s", r, serviceid, tag, path);
sleep(1); /* retry */
} }
handle(sock, tag, path);
exit(0);
} }