Change how auto-reconnect works

For NFS sessions, change the autoreconnect options to be :
-1:  (default) retry connectiong back to the server forever. Just like
normal NFS clients do.
0: Do not attempt reconnecting at all. Immediately fail and return an
error back to the application on session loss.
>=1: Retry connecting to the server this many times before giving up.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2017-05-29 17:21:13 -07:00
parent eee1b4f7f2
commit 173ad2b1f3
5 changed files with 48 additions and 46 deletions

14
README
View File

@ -56,11 +56,15 @@ Arguments supported by libnfs are :
: Should libnfs try to traverse across nested mounts
automatically or not. Default is 1 == enabled.
dircache=<0|1> : Disable/enable directory caching. Enabled by default.
autoreconnect=<0|1>
: Disable/enable reconnection when connections close.
When disabled, closed connections will cause an
immediate error return, with loss of commands and
data that are still inflight. Default is 1 == enabled.
autoreconnect=<-1|0|>=1>
: Control the auto-reconnect behaviour to the NFS session.
-1 : Try to reconnect forever on session failures.
Just like normal NFS clients do.
0 : Disable auto-reconnect completely and immediately
return a failure to the application.
>=1 : Retry to connect back to the server this many
times before failing and returing an error back
to the application.
if=<interface> : Interface name (e.g., eth1) to bind; requires `root`
Auto_traverse_mounts

View File

@ -133,7 +133,7 @@ struct rpc_context {
/* track the address we connect to so we can auto-reconnect on session failure */
struct sockaddr_storage s;
int auto_reconnect;
int auto_reconnect_retries;
int num_retries;
/* fragment reassembly */
struct rpc_fragment *fragments;
@ -218,8 +218,7 @@ int rpc_set_udp_destination(struct rpc_context *rpc, char *addr, int port, int i
struct rpc_context *rpc_init_udp_context(void);
struct sockaddr *rpc_get_recv_sockaddr(struct rpc_context *rpc);
void rpc_set_autoreconnect(struct rpc_context *rpc);
void rpc_unset_autoreconnect(struct rpc_context *rpc);
void rpc_set_autoreconnect(struct rpc_context *rpc, int num_retries);
void rpc_set_interface(struct rpc_context *rpc, const char *ifname);

View File

@ -183,11 +183,15 @@ EXTERN void nfs_destroy_context(struct nfs_context *nfs);
* : Should libnfs try to traverse across nested mounts
* automatically or not. Default is 1 == enabled.
* dircache=<0|1> : Disable/enable directory caching. Enabled by default.
* autoreconnect=<0|1>
* : Disable/enable reconnection when connections close.
* When disabled, closed connections will cause an
* immediate error return, with loss of commands and
* data that are still inflight. Default is 1 == enabled.
* autoreconnect=<-1|0|>=1>
* : Control the auto-reconnect behaviour to the NFS session.
* -1 : Try to reconnect forever on session failures.
* Just like normal NFS clients do.
* 0 : Disable auto-reconnect completely and immediately
* return a failure to the application.
* >=1 : Retry to connect back to the server this many
* times before failing and returing an error back
* to the application.
*/
/*
* Parse a complete NFS URL including, server, path and
@ -238,7 +242,7 @@ EXTERN void nfs_set_pagecache_ttl(struct nfs_context *nfs, uint32_t v);
EXTERN void nfs_set_readahead(struct nfs_context *nfs, uint32_t v);
EXTERN void nfs_set_debug(struct nfs_context *nfs, int level);
EXTERN void nfs_set_dircache(struct nfs_context *nfs, int enabled);
EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int enabled);
EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries);
/*
* Invalidate the pagecache

View File

@ -148,7 +148,7 @@ struct nfs_context {
uint64_t writemax;
char *cwd;
int dircache_enabled;
int auto_reconnect_enabled;
int auto_reconnect;
struct nfsdir *dircache;
uint16_t mask;
@ -532,7 +532,8 @@ struct nfs_context *nfs_init_context(void)
nfs->mask = 022;
nfs->auto_traverse_mounts = 1;
nfs->dircache_enabled = 1;
nfs->auto_reconnect_enabled = 1;
/* Default is never give up, never surrender */
nfs->auto_reconnect = -1;
return nfs;
}
@ -1023,11 +1024,10 @@ static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_da
return;
}
/* NFS TCP connections should be autoreconnected after sessions have
* been torn down (due to inactivity or error)
/* NFS TCP: As we are connected now we can pass on the auto-reconnect
* settings to the RPC layer.
*/
if (nfs->auto_reconnect_enabled)
rpc_set_autoreconnect(rpc);
rpc_set_autoreconnect(rpc, nfs->auto_reconnect);
args.fsroot = nfs->rootfh;
if (rpc_nfs3_fsinfo_async(rpc, nfs_mount_10_cb, &args, data) != 0) {
@ -5607,8 +5607,8 @@ void nfs_set_dircache(struct nfs_context *nfs, int enabled) {
nfs->dircache_enabled = enabled;
}
void nfs_set_autoreconnect(struct nfs_context *nfs, int enabled) {
nfs->auto_reconnect_enabled = enabled;
void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries) {
nfs->auto_reconnect = num_retries;
}
void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)

View File

@ -85,8 +85,6 @@
#include "win32_errnowrapper.h"
#endif
#define NR_RECONNECT_RETRIES 10
static int rpc_reconnect_requeue(struct rpc_context *rpc);
static int create_socket(int domain, int type, int protocol)
@ -476,7 +474,7 @@ int rpc_service(struct rpc_context *rpc, int revents)
return 0;
}
void rpc_set_autoreconnect(struct rpc_context *rpc)
void rpc_set_autoreconnect(struct rpc_context *rpc, int num_retries)
{
assert(rpc->magic == RPC_CONTEXT_MAGIC);
@ -485,18 +483,7 @@ void rpc_set_autoreconnect(struct rpc_context *rpc)
return;
}
rpc->auto_reconnect = 1;
}
void rpc_unset_autoreconnect(struct rpc_context *rpc)
{
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (rpc->is_server_context) {
return;
}
rpc->auto_reconnect = 0;
rpc->auto_reconnect = num_retries;
}
void rpc_set_tcp_syncnt(struct rpc_context *rpc, int v)
@ -717,7 +704,8 @@ int rpc_disconnect(struct rpc_context *rpc, const char *error)
if (!rpc->is_connected) {
return 0;
}
rpc_unset_autoreconnect(rpc);
/* Disable autoreconnect */
rpc_set_autoreconnect(rpc, 0);
if (rpc->fd != -1) {
close(rpc->fd);
@ -756,8 +744,15 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc)
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (rpc->is_connected)
rpc->auto_reconnect_retries = NR_RECONNECT_RETRIES;
if (rpc->auto_reconnect == 0) {
RPC_LOG(rpc, 1, "reconnect is disabled");
rpc_error_all_pdus(rpc, "RPC ERROR: Failed to reconnect async");
return -1;
}
if (rpc->is_connected) {
rpc->num_retries = rpc->auto_reconnect;
}
if (rpc->fd != -1) {
rpc->old_fd = rpc->fd;
@ -784,20 +779,20 @@ static int rpc_reconnect_requeue(struct rpc_context *rpc)
}
rpc->waitpdu_len = 0;
if (rpc->auto_reconnect != 0 && rpc->auto_reconnect_retries > 0) {
rpc->auto_reconnect_retries--;
if (rpc->auto_reconnect < 0 || rpc->num_retries > 0) {
rpc->num_retries--;
rpc->connect_cb = reconnect_cb;
RPC_LOG(rpc, 1, "reconnect initiated");
if (rpc_connect_sockaddr_async(rpc) != 0) {
rpc_error_all_pdus(rpc, "RPC ERROR: Failed to reconnect async");
return -1;
}
} else {
RPC_LOG(rpc, 1, "reconnect NOT initiated, auto-reconnect is disabled");
return -1;
return 0;
}
return 0;
RPC_LOG(rpc, 1, "reconnect: all attempts failed.");
rpc_error_all_pdus(rpc, "RPC ERROR: All attempts to reconnect failed.");
return -1;
}