socket: keep fd the same across reconnects
There is no guarantee that we get the same fd again when reestablishing a session. But if the fd changes during a reconnect we might up with a client application busy polling on the old fd. Qemu registers a read handler on the current fd, but is not realizing fd changes. So we busy poll on the old fd for good. Things are working (except for the busy polling) until a drain all is issued. At this point Qemu deadlocks. Signed-off-by: Peter Lieven <pl@kamp.de>libnfs-4.0.0-vitalif
parent
7b7aef6b6d
commit
ddd9e2f7e9
|
@ -79,6 +79,7 @@ struct rpc_queue {
|
|||
struct rpc_context {
|
||||
uint32_t magic;
|
||||
int fd;
|
||||
int old_fd;
|
||||
int is_connected;
|
||||
|
||||
char *error_string;
|
||||
|
|
15
lib/socket.c
15
lib/socket.c
|
@ -132,6 +132,10 @@ int rpc_get_fd(struct rpc_context *rpc)
|
|||
{
|
||||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (rpc->old_fd) {
|
||||
return rpc->old_fd;
|
||||
}
|
||||
|
||||
return rpc->fd;
|
||||
}
|
||||
|
||||
|
@ -418,6 +422,14 @@ static int rpc_connect_sockaddr_async(struct rpc_context *rpc, struct sockaddr_s
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (rpc->old_fd) {
|
||||
if (dup2(rpc->fd, rpc->old_fd) == -1) {
|
||||
return -1;
|
||||
}
|
||||
close(rpc->fd);
|
||||
rpc->fd = rpc->old_fd;
|
||||
}
|
||||
|
||||
/* Some systems allow you to set capabilities on an executable
|
||||
* to allow the file to be executed with privilege to bind to
|
||||
* privileged system ports, even if the user is not root.
|
||||
|
@ -579,6 +591,7 @@ static void reconnect_cb(struct rpc_context *rpc, int status, void *data _U_, vo
|
|||
|
||||
rpc->is_connected = 1;
|
||||
rpc->connect_cb = NULL;
|
||||
rpc->old_fd = 0;
|
||||
}
|
||||
|
||||
/* disconnect but do not error all PDUs, just move pdus in-flight back to the outqueue and reconnect */
|
||||
|
@ -590,7 +603,7 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc)
|
|||
assert(rpc->magic == RPC_CONTEXT_MAGIC);
|
||||
|
||||
if (rpc->fd != -1) {
|
||||
close(rpc->fd);
|
||||
rpc->old_fd = rpc->fd;
|
||||
}
|
||||
rpc->fd = -1;
|
||||
rpc->is_connected = 0;
|
||||
|
|
Loading…
Reference in New Issue