Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106132147
D30970.id91639.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D30970.id91639.diff
View Options
diff --git a/sys/fs/nfs/nfs_commonkrpc.c.nconn b/sys/fs/nfs/nfs_commonkrpc.c
--- a/sys/fs/nfs/nfs_commonkrpc.c.nconn
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -167,7 +167,8 @@
*/
int
newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
- struct ucred *cred, NFSPROC_T *p, int callback_retry_mult, bool dotls)
+ struct ucred *cred, NFSPROC_T *p, int callback_retry_mult, bool dotls,
+ struct __rpc_client **clipp)
{
int rcvreserve, sndreserve;
int pktscale, pktscalesav;
@@ -420,15 +421,22 @@
CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, &timo);
}
+ /*
+ * *clipp is &nrp->nr_client or &nm_aconn[nmp->nm_nextconn].
+ * The latter case is for additional connections specified by the
+ * "nconnect" mount option. nr_mtx etc is used for these additional
+ * connections, as well as nr_client in the nfssockreq
+ * structure for the mount.
+ */
mtx_lock(&nrp->nr_mtx);
- if (nrp->nr_client != NULL) {
+ if (*clipp != NULL) {
mtx_unlock(&nrp->nr_mtx);
/*
* Someone else already connected.
*/
CLNT_RELEASE(client);
} else {
- nrp->nr_client = client;
+ *clipp = client;
/*
* Protocols that do not require connections may be optionally
* left unconnected for servers that reply from a port other
@@ -453,18 +461,34 @@
* NFS disconnect. Clean up and unlink.
*/
void
-newnfs_disconnect(struct nfssockreq *nrp)
+newnfs_disconnect(struct nfsmount *nmp, struct nfssockreq *nrp)
{
- CLIENT *client;
+ CLIENT *client, *aconn[NFS_MAXNCONN - 1];
+ int i;
mtx_lock(&nrp->nr_mtx);
if (nrp->nr_client != NULL) {
client = nrp->nr_client;
nrp->nr_client = NULL;
+ if (nmp != NULL && nmp->nm_nconnect > 0) {
+ for (i = 0; i < nmp->nm_nconnect - 1; i++) {
+ aconn[i] = nmp->nm_aconn[i];
+ nmp->nm_aconn[i] = NULL;
+ }
+ }
mtx_unlock(&nrp->nr_mtx);
rpc_gss_secpurge_call(client);
CLNT_CLOSE(client);
CLNT_RELEASE(client);
+ if (nmp != NULL && nmp->nm_nconnect > 0) {
+ for (i = 0; i < nmp->nm_nconnect - 1; i++) {
+ if (aconn[i] != NULL) {
+ rpc_gss_secpurge_call(aconn[i]);
+ CLNT_CLOSE(aconn[i]);
+ CLNT_RELEASE(aconn[i]);
+ }
+ }
+ }
} else {
mtx_unlock(&nrp->nr_mtx);
}
@@ -602,13 +626,16 @@
}
/*
- * XXX if not already connected call nfs_connect now. Longer
- * term, change nfs_mount to call nfs_connect unconditionally
- * and let clnt_reconnect_create handle reconnects.
+ * If not already connected call newnfs_connect now.
*/
if (nrp->nr_client == NULL)
- newnfs_connect(nmp, nrp, cred, td, 0, false);
+ newnfs_connect(nmp, nrp, cred, td, 0, false, &nrp->nr_client);
+ if (nmp != NULL && nmp->nm_nconnect > 0 &&
+ nmp->nm_aconn[nmp->nm_nextnconn] == NULL)
+ newnfs_connect(nmp, nrp, cred, td, 0, false,
+ &nmp->nm_aconn[nmp->nm_nextnconn]);
+
/*
* For a client side mount, nmp is != NULL and clp == NULL. For
* server calls (callbacks or upcalls), nmp == NULL.
@@ -830,7 +857,25 @@
if (clp != NULL && sep != NULL)
stat = clnt_bck_call(nrp->nr_client, &ext, procnum,
nd->nd_mreq, &nd->nd_mrep, timo, sep->nfsess_xprt);
- else
+ else if (nmp != NULL && nmp->nm_nconnect > 0 &&
+ (nd->nd_procnum == NFSPROC_READ ||
+ nd->nd_procnum == NFSPROC_READDIR ||
+ nd->nd_procnum == NFSPROC_WRITE)) {
+ /*
+ * When there are multiple TCP connections, send the
+ * RPCs with large messages on the alternate TCP
+ * connection(s) in a round robin fashion.
+ * The small RPC messages are sent on the default
+ * TCP connection because they do not require much
+ * network bandwidth and separating them from the
+ * large RPC messages avoids them getting "log jammed"
+ * behind several large RPC messages.
+ */
+ stat = CLNT_CALL_MBUF(nmp->nm_aconn[nmp->nm_nextnconn],
+ &ext, procnum, nd->nd_mreq, &nd->nd_mrep, timo);
+ nmp->nm_nextnconn = (nmp->nm_nextnconn + 1) %
+ (nmp->nm_nconnect - 1);
+ } else
stat = CLNT_CALL_MBUF(nrp->nr_client, &ext, procnum,
nd->nd_mreq, &nd->nd_mrep, timo);
NFSCL_DEBUG(2, "clnt call=%d\n", stat);
diff --git a/sys/fs/nfs/nfs_commonsubs.c.nconn b/sys/fs/nfs/nfs_commonsubs.c
--- a/sys/fs/nfs/nfs_commonsubs.c.nconn
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -3625,7 +3625,8 @@
}
rp->nr_vers = RPCNFSUSERD_VERS;
if (error == 0)
- error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0, false);
+ error = newnfs_connect(NULL, rp, NFSPROCCRED(p), p, 0, false,
+ &rp->nr_client);
if (error == 0) {
NFSLOCKNAMEID();
nfsrv_nfsuserd = RUNNING;
@@ -3659,7 +3660,7 @@
msleep(&nfsrv_userdupcalls, NFSNAMEIDMUTEXPTR, PVFS,
"nfsupcalls", 0);
NFSUNLOCKNAMEID();
- newnfs_disconnect(&nfsrv_nfsuserdsock);
+ newnfs_disconnect(NULL, &nfsrv_nfsuserdsock);
free(nfsrv_nfsuserdsock.nr_nam, M_SONAME);
NFSLOCKNAMEID();
nfsrv_nfsuserd = NOTRUNNING;
diff --git a/sys/fs/nfs/nfs_var.h.nconn b/sys/fs/nfs/nfs_var.h
--- a/sys/fs/nfs/nfs_var.h.nconn
+++ b/sys/fs/nfs/nfs_var.h
@@ -772,8 +772,8 @@
struct ucred *, u_int32_t, u_int32_t, u_char *, int, u_int64_t *,
struct nfsclsession *);
int newnfs_connect(struct nfsmount *, struct nfssockreq *,
- struct ucred *, NFSPROC_T *, int, bool);
-void newnfs_disconnect(struct nfssockreq *);
+ struct ucred *, NFSPROC_T *, int, bool, struct __rpc_client **);
+void newnfs_disconnect(struct nfsmount *, struct nfssockreq *);
int newnfs_sigintr(struct nfsmount *, NFSPROC_T *);
/* nfs_nfsdkrpc.c */
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c.nconn b/sys/fs/nfsclient/nfs_clrpcops.c
--- a/sys/fs/nfsclient/nfs_clrpcops.c.nconn
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -5610,7 +5610,7 @@
* unmount, but I did it anyhow.
*/
nrp->nr_cred = crhold(nmp->nm_sockreq.nr_cred);
- error = newnfs_connect(nmp, nrp, NULL, p, 0, false);
+ error = newnfs_connect(nmp, nrp, NULL, p, 0, false, &nrp->nr_client);
NFSCL_DEBUG(3, "DS connect=%d\n", error);
dsp = NULL;
@@ -5628,7 +5628,7 @@
} while (error == NFSERR_MINORVERMISMATCH &&
firsttry++ == 0);
if (error != 0)
- newnfs_disconnect(nrp);
+ newnfs_disconnect(NULL, nrp);
} else {
dsp = malloc(sizeof(struct nfsclds), M_NFSCLDS,
M_WAITOK | M_ZERO);
@@ -5656,7 +5656,7 @@
* If there is already a session for this
* server, use it.
*/
- (void)newnfs_disconnect(nrp);
+ newnfs_disconnect(NULL, nrp);
nfscl_freenfsclds(dsp);
*dspp = tdsp;
return (0);
@@ -5688,7 +5688,7 @@
NFSUNLOCKMNT(nmp);
*dspp = dsp;
} else if (dsp != NULL) {
- newnfs_disconnect(nrp);
+ newnfs_disconnect(NULL, nrp);
nfscl_freenfsclds(dsp);
}
return (error);
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c.nconn b/sys/fs/nfsclient/nfs_clvfsops.c
--- a/sys/fs/nfsclient/nfs_clvfsops.c.nconn
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -118,7 +118,7 @@
static int mountnfs(struct nfs_args *, struct mount *,
struct sockaddr *, char *, u_char *, int, u_char *, int,
u_char *, int, struct vnode **, struct ucred *,
- struct thread *, int, int, int, uint32_t, char *);
+ struct thread *, int, int, int, uint32_t, char *, int);
static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
struct sockaddr_storage *, int *, off_t *,
struct timeval *);
@@ -548,7 +548,7 @@
nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
- NFS_DEFAULT_NEGNAMETIMEO, 0, 0, NULL)) != 0) {
+ NFS_DEFAULT_NEGNAMETIMEO, 0, 0, NULL, 0)) != 0) {
printf("nfs_mountroot: mount %s on /: %d\n", path, error);
return (error);
}
@@ -715,14 +715,14 @@
haslock = 1;
}
if (!error) {
- newnfs_disconnect(&nmp->nm_sockreq);
+ newnfs_disconnect(nmp, &nmp->nm_sockreq);
if (haslock)
newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
nmp->nm_sotype = argp->sotype;
nmp->nm_soproto = argp->proto;
if (nmp->nm_sotype == SOCK_DGRAM)
while (newnfs_connect(nmp, &nmp->nm_sockreq,
- cred, td, 0, false)) {
+ cred, td, 0, false, &nmp->nm_sockreq.nr_client)) {
printf("newnfs_args: retrying connect\n");
(void) nfs_catnap(PSOCK, 0, "nfscon");
}
@@ -750,7 +750,7 @@
"resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
"nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
"minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
- "pnfs", "wcommitsize", "oneopenown", "tls", "tlscertname",
+ "pnfs", "wcommitsize", "oneopenown", "tls", "tlscertname", "nconnect",
NULL };
/*
@@ -902,6 +902,7 @@
krbnamelen, srvkrbnamelen;
size_t hstlen;
uint32_t newflag;
+ int nconn = 0;
has_nfs_args_opt = 0;
has_nfs_from_opt = 0;
@@ -1192,6 +1193,15 @@
goto out;
}
}
+ if (vfs_getopt(mp->mnt_optnew, "nconnect", (void **)&opt, NULL) ==
+ 0) {
+ ret = sscanf(opt, "%d", &nconn);
+ if (ret != 1 || nconn < 2 || nconn > NFS_MAXNCONN) {
+ vfs_mount_error(mp, "illegal nconnect: %s", opt);
+ error = EINVAL;
+ goto out;
+ }
+ }
if (vfs_getopt(mp->mnt_optnew, "sec",
(void **) &secname, NULL) == 0)
nfs_sec_name(secname, &args.flags);
@@ -1362,7 +1372,7 @@
args.fh = nfh;
error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
- nametimeo, negnametimeo, minvers, newflag, tlscertname);
+ nametimeo, negnametimeo, minvers, newflag, tlscertname, nconn);
out:
if (!error) {
MNT_ILOCK(mp);
@@ -1410,7 +1420,7 @@
char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
- int minvers, uint32_t newflag, char *tlscertname)
+ int minvers, uint32_t newflag, char *tlscertname, int nconn)
{
struct nfsmount *nmp;
struct nfsnode *np;
@@ -1577,7 +1587,8 @@
else
nmp->nm_sockreq.nr_vers = NFS_VER2;
- if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0, false)))
+ if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0, false,
+ &nmp->nm_sockreq.nr_client)))
goto bad;
/* For NFSv4, get the clientid now. */
if ((argp->flags & NFSMNT_NFSV4) != 0) {
@@ -1680,6 +1691,10 @@
MNT_IUNLOCK(mp);
}
+ /* Can now allow additional connections. */
+ if (nconn > 0 && argp->sotype == SOCK_STREAM)
+ nmp->nm_nconnect = nconn;
+
/*
* Lose the lock but keep the ref.
*/
@@ -1692,7 +1707,7 @@
bad:
if (clp != NULL)
nfscl_clientrelease(clp);
- newnfs_disconnect(&nmp->nm_sockreq);
+ newnfs_disconnect(NULL, &nmp->nm_sockreq);
crfree(nmp->nm_sockreq.nr_cred);
if (nmp->nm_sockreq.nr_auth != NULL)
AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
@@ -1707,7 +1722,7 @@
TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
dsp->nfsclds_sockp != NULL)
- newnfs_disconnect(dsp->nfsclds_sockp);
+ newnfs_disconnect(NULL, dsp->nfsclds_sockp);
nfscl_freenfsclds(dsp);
}
free(nmp->nm_tlscertname, M_NEWNFSMNT);
@@ -1793,7 +1808,7 @@
msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
mtx_unlock(&nmp->nm_mtx);
- newnfs_disconnect(&nmp->nm_sockreq);
+ newnfs_disconnect(nmp, &nmp->nm_sockreq);
crfree(nmp->nm_sockreq.nr_cred);
free(nmp->nm_nam, M_SONAME);
if (nmp->nm_sockreq.nr_auth != NULL)
@@ -1803,7 +1818,7 @@
TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
dsp->nfsclds_sockp != NULL)
- newnfs_disconnect(dsp->nfsclds_sockp);
+ newnfs_disconnect(NULL, dsp->nfsclds_sockp);
nfscl_freenfsclds(dsp);
}
free(nmp->nm_tlscertname, M_NEWNFSMNT);
@@ -2067,6 +2082,7 @@
&blen);
nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
&buf, &blen);
+ nfscl_printoptval(nmp, nmp->nm_nconnect, ",nconnect", &buf, &blen);
nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
&blen);
nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
diff --git a/sys/fs/nfsclient/nfsmount.h.nconn b/sys/fs/nfsclient/nfsmount.h
--- a/sys/fs/nfsclient/nfsmount.h.nconn
+++ b/sys/fs/nfsclient/nfsmount.h
@@ -39,6 +39,9 @@
#include <nfs/nfs_mountcommon.h>
+/* Maximum value for nm_nconnect. */
+#define NFS_MAXNCONN 16
+
/*
* Mount structure.
* One allocated on every NFS mount.
@@ -81,6 +84,9 @@
u_int64_t nm_clval; /* identifies which clientid */
u_int64_t nm_fsid[2]; /* NFSv4 fsid */
int nm_minorvers; /* Minor version # for NFSv4 */
+ u_int nm_nconnect; /* nconnect value */
+ u_int nm_nextnconn; /* Next nconnect to use */
+ struct __rpc_client *nm_aconn[NFS_MAXNCONN - 1]; /* Additional nconn */
u_int16_t nm_krbnamelen; /* Krb5 host principal, if any */
u_int16_t nm_dirpathlen; /* and mount dirpath, for V4 */
u_int16_t nm_srvkrbnamelen; /* and the server's target name */
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c.nconn b/sys/fs/nfsserver/nfs_nfsdstate.c
--- a/sys/fs/nfsserver/nfs_nfsdstate.c.nconn
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -1369,7 +1369,7 @@
NULL, 0, NULL, NULL, NULL, 0, p);
}
#endif
- newnfs_disconnect(&clp->lc_req);
+ newnfs_disconnect(NULL, &clp->lc_req);
free(clp->lc_req.nr_nam, M_SONAME);
NFSFREEMUTEX(&clp->lc_req.nr_mtx);
free(clp->lc_stateid, M_NFSDCLIENT);
@@ -4578,10 +4578,10 @@
nfsrv_freesession(sep, NULL);
} else if (nd->nd_procnum == NFSV4PROC_CBNULL)
error = newnfs_connect(NULL, &clp->lc_req, cred,
- NULL, 1, dotls);
+ NULL, 1, dotls, &clp->lc_req.nr_client);
else
error = newnfs_connect(NULL, &clp->lc_req, cred,
- NULL, 3, dotls);
+ NULL, 3, dotls, &clp->lc_req.nr_client);
}
newnfs_sndunlock(&clp->lc_req.nr_lock);
NFSD_DEBUG(4, "aft sndunlock=%d\n", error);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 26, 10:38 PM (11 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15608488
Default Alt Text
D30970.id91639.diff (13 KB)
Attached To
Mode
D30970: add a "nconnect" mount option to the NFS client
Attached
Detach File
Event Timeline
Log In to Comment