summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2004-07-12 06:22:42 +0000
committeralfred <alfred@FreeBSD.org>2004-07-12 06:22:42 +0000
commit031e087d2c3a8f23b40ec3cd62b741f935e1e2e6 (patch)
treebf496bf6af68cb9b9d21598b856b458f96bb8fab
parentdf5304b63cb13fff0de92961ba80dea84c5c552c (diff)
downloadFreeBSD-src-031e087d2c3a8f23b40ec3cd62b741f935e1e2e6.zip
FreeBSD-src-031e087d2c3a8f23b40ec3cd62b741f935e1e2e6.tar.gz
Use SO_REUSEADDR and SO_REUSEPORT when reconnecting NFS mounts.
Tune the timeout from 5 seconds to 12 seconds. Provide a sysctl to show how many reconnects the NFS client has done. Seems to fix IPv6 from: kuriyama
-rw-r--r--sys/kern/uipc_socket.c19
-rw-r--r--sys/nfsclient/nfs_socket.c12
-rw-r--r--sys/sys/socketvar.h2
3 files changed, 31 insertions, 2 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index f3a0108..6787573 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1541,6 +1541,25 @@ sooptcopyin(sopt, buf, len, minlen)
return 0;
}
+/*
+ * Kernel version of setsockopt(2)/
+ * XXX: optlen is size_t, not socklen_t
+ */
+int
+kern_setsockopt(struct socket *so, int level, int optname, void *optval,
+ size_t optlen)
+{
+ struct sockopt sopt;
+
+ sopt.sopt_level = level;
+ sopt.sopt_name = optname;
+ sopt.sopt_dir = SOPT_SET;
+ sopt.sopt_val = optval;
+ sopt.sopt_valsize = optlen;
+ sopt.sopt_td = NULL;
+ return (sosetopt(so, &sopt));
+}
+
int
sosetopt(so, sopt)
struct socket *so;
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index f602e42..191d5d2 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -111,12 +111,15 @@ static int proct[NFS_NPROCS] = {
static int nfs_realign_test;
static int nfs_realign_count;
static int nfs_bufpackets = 4;
+static int nfs_reconnects;
SYSCTL_DECL(_vfs_nfs);
SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 0, "");
SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 0, "");
SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0, "");
+SYSCTL_INT(_vfs_nfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0,
+ "number of times the nfs client has had to reconnect");
/*
@@ -157,7 +160,7 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
{
struct socket *so;
int error, rcvreserve, sndreserve;
- int pktscale;
+ int opt, pktscale;
struct sockaddr *saddr;
struct thread *td = &thread0; /* only used for socreate and sobind */
@@ -172,6 +175,10 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
so = nmp->nm_so;
nmp->nm_soflags = so->so_proto->pr_flags;
+ opt = 1;
+ (void)kern_setsockopt(so, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+ (void)kern_setsockopt(so, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
+
/*
* Some servers require that the client port be a reserved port number.
*/
@@ -261,7 +268,7 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
}
SOCK_UNLOCK(so);
}
- so->so_rcv.sb_timeo = 5 * hz;
+ so->so_rcv.sb_timeo = 12 * hz;
so->so_snd.sb_timeo = 5 * hz;
/*
@@ -357,6 +364,7 @@ nfs_reconnect(struct nfsreq *rep)
struct nfsmount *nmp = rep->r_nmp;
int error;
+ nfs_reconnects++;
nfs_disconnect(nmp);
while ((error = nfs_connect(nmp, rep)) != 0) {
if (error == ERESTART)
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index fb81792..cfe061b 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -438,6 +438,8 @@ struct uio;
/*
* From uipc_socket and friends
*/
+int kern_setsockopt(struct socket *so, int level, int optname,
+ void *optval, size_t optlen);
int sockargs(struct mbuf **mp, caddr_t buf, int buflen, int type);
int getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
void sbappend(struct sockbuf *sb, struct mbuf *m);
OpenPOWER on IntegriCloud