svn commit: r324090 - in head/sys/fs: nfs nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Thu Sep 28 22:33:03 UTC 2017
Author: rmacklem
Date: Thu Sep 28 22:33:01 2017
New Revision: 324090
URL: https://svnweb.freebsd.org/changeset/base/324090
Log:
Change nfsv4_getipaddr() and nfsrpc_fillsa() to not use sockaddr_storage.
This patch changes nfsv4_getipaddr() and nfsrpc_fillsa() to use
a sockaddr_in * and sockaddr_in6 * instead of sockaddr_storage, to
avoid allocating the latter on the stack. It also moves the nfsrpc_fillsa()
call to after the completion of parsing of the DeviceInfo reply from
the server. This patch is in preparation for addition of Flex File
Layout support in a future commit.
It only affects the "pnfs" NFSv4.1 client mount option and should not
have changed its semantics.
Modified:
head/sys/fs/nfs/nfs_commonsubs.c
head/sys/fs/nfs/nfs_var.h
head/sys/fs/nfsclient/nfs_clrpcops.c
Modified: head/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- head/sys/fs/nfs/nfs_commonsubs.c Thu Sep 28 19:57:46 2017 (r324089)
+++ head/sys/fs/nfs/nfs_commonsubs.c Thu Sep 28 22:33:01 2017 (r324090)
@@ -3938,14 +3938,13 @@ newnfs_sndunlock(int *flagp)
}
APPLESTATIC int
-nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_storage *sa,
- int *isudp)
+nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_in *sin,
+ struct sockaddr_in6 *sin6, sa_family_t *saf, int *isudp)
{
- struct sockaddr_in *sad;
- struct sockaddr_in6 *sad6;
struct in_addr saddr;
uint32_t portnum, *tl;
- int af = 0, i, j, k;
+ int i, j, k;
+ sa_family_t af = AF_UNSPEC;
char addr[64], protocol[5], *cp;
int cantparse = 0, error = 0;
uint16_t portv;
@@ -4023,20 +4022,20 @@ nfsv4_getipaddr(struct nfsrv_descript *nd, struct sock
cantparse = 1;
if (cantparse == 0) {
if (af == AF_INET) {
- sad = (struct sockaddr_in *)sa;
- if (inet_pton(af, addr, &sad->sin_addr) == 1) {
- sad->sin_len = sizeof(*sad);
- sad->sin_family = AF_INET;
- sad->sin_port = htons(portv);
+ if (inet_pton(af, addr, &sin->sin_addr) == 1) {
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(portv);
+ *saf = af;
return (0);
}
} else {
- sad6 = (struct sockaddr_in6 *)sa;
- if (inet_pton(af, addr, &sad6->sin6_addr)
+ if (inet_pton(af, addr, &sin6->sin6_addr)
== 1) {
- sad6->sin6_len = sizeof(*sad6);
- sad6->sin6_family = AF_INET6;
- sad6->sin6_port = htons(portv);
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = htons(portv);
+ *saf = af;
return (0);
}
}
Modified: head/sys/fs/nfs/nfs_var.h
==============================================================================
--- head/sys/fs/nfs/nfs_var.h Thu Sep 28 19:57:46 2017 (r324089)
+++ head/sys/fs/nfs/nfs_var.h Thu Sep 28 22:33:01 2017 (r324090)
@@ -287,8 +287,8 @@ void nfsrv_cleanusergroup(void);
int nfsrv_checkutf8(u_int8_t *, int);
int newnfs_sndlock(int *);
void newnfs_sndunlock(int *);
-int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_storage *,
- int *);
+int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_in *,
+ struct sockaddr_in6 *, sa_family_t *, int *);
int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,
struct mbuf **, uint16_t);
void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, int, struct mbuf **);
Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c Thu Sep 28 19:57:46 2017 (r324089)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c Thu Sep 28 22:33:01 2017 (r324090)
@@ -109,8 +109,8 @@ static int nfsrpc_setaclrpc(vnode_t, struct ucred *, N
static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int,
uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
struct ucred *, NFSPROC_T *);
-static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_storage *,
- struct nfsclds **, NFSPROC_T *);
+static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *,
+ struct sockaddr_in6 *, sa_family_t, int, struct nfsclds **, NFSPROC_T *);
static void nfscl_initsessionslots(struct nfsclsession *);
static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *,
nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
@@ -4885,14 +4885,17 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de
uint32_t cnt, *tl;
struct nfsrv_descript nfsd;
struct nfsrv_descript *nd = &nfsd;
- struct sockaddr_storage ss;
- struct nfsclds *dsp = NULL, **dspp;
+ struct sockaddr_in sin, ssin;
+ struct sockaddr_in6 sin6, ssin6;
+ struct nfsclds *dsp = NULL, **dspp, **gotdspp;
struct nfscldevinfo *ndi;
- int addrcnt, bitcnt, error, i, isudp, j, pos, safilled, stripecnt;
+ int addrcnt = 0, bitcnt, error, gotvers, i, isudp, j, stripecnt;
uint8_t stripeindex;
+ sa_family_t af, safilled;
*ndip = NULL;
ndi = NULL;
+ gotdspp = NULL;
nfscl_reqstart(nd, NFSPROC_GETDEVICEINFO, nmp, NULL, 0, NULL, NULL, 0,
0);
NFSM_BUILD(tl, uint32_t *, NFSX_V4DEVICEID + 3 * NFSX_UNSIGNED);
@@ -4960,7 +4963,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de
}
/* Now, dissect the server address(es). */
- safilled = 0;
+ safilled = AF_UNSPEC;
for (i = 0; i < addrcnt; i++) {
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
cnt = fxdr_unsigned(uint32_t, *tl);
@@ -4970,61 +4973,65 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de
goto nfsmout;
}
dspp = nfsfldi_addr(ndi, i);
- pos = arc4random() % cnt; /* Choose one. */
- safilled = 0;
+ safilled = AF_UNSPEC;
for (j = 0; j < cnt; j++) {
- error = nfsv4_getipaddr(nd, &ss, &isudp);
+ error = nfsv4_getipaddr(nd, &sin, &sin6, &af,
+ &isudp);
if (error != 0 && error != EPERM) {
error = NFSERR_BADXDR;
goto nfsmout;
}
if (error == 0 && isudp == 0) {
/*
- * The algorithm is:
- * - use "pos" entry if it is of the
- * same af_family or none of them
- * is of the same af_family
- * else
- * - use the first one of the same
- * af_family.
+ * The priority is:
+ * - Same address family.
+ * Save the address and dspp, so that
+ * the connection can be done after
+ * parsing is complete.
*/
- if ((safilled == 0 && ss.ss_family ==
- nmp->nm_nam->sa_family) ||
- (j == pos &&
- (safilled == 0 || ss.ss_family ==
- nmp->nm_nam->sa_family)) ||
- (safilled == 1 && ss.ss_family ==
- nmp->nm_nam->sa_family)) {
- error = nfsrpc_fillsa(nmp, &ss,
- &dsp, p);
- if (error == 0) {
- *dspp = dsp;
- if (ss.ss_family ==
- nmp->nm_nam->sa_family)
- safilled = 2;
- else
- safilled = 1;
- }
+ if (safilled == AF_UNSPEC ||
+ (af == nmp->nm_nam->sa_family &&
+ safilled != nmp->nm_nam->sa_family)
+ ) {
+ if (af == AF_INET)
+ ssin = sin;
+ else
+ ssin6 = sin6;
+ safilled = af;
+ gotdspp = dspp;
}
}
}
- if (safilled == 0)
- break;
}
+ gotvers = NFS_VER4; /* Always NFSv4 for File Layout. */
+
/* And the notify bits. */
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
- if (safilled != 0) {
- bitcnt = fxdr_unsigned(int, *tl);
- if (bitcnt > 0) {
- NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
- if (notifybitsp != NULL)
- *notifybitsp =
- fxdr_unsigned(uint32_t, *tl);
- }
+ bitcnt = fxdr_unsigned(int, *tl);
+ if (bitcnt > 0) {
+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+ if (notifybitsp != NULL)
+ *notifybitsp =
+ fxdr_unsigned(uint32_t, *tl);
+ }
+ if (safilled != AF_UNSPEC) {
+ KASSERT(ndi != NULL, ("ndi is NULL"));
*ndip = ndi;
} else
error = EPERM;
+ if (error == 0) {
+ /*
+ * Now we can do a TCP connection for the correct
+ * NFS version and IP address.
+ */
+ error = nfsrpc_fillsa(nmp, &ssin, &ssin6, safilled,
+ gotvers, &dsp, p);
+ }
+ if (error == 0) {
+ KASSERT(gotdspp != NULL, ("gotdspp is NULL"));
+ *gotdspp = dsp;
+ }
}
if (nd->nd_repstat != 0)
error = nd->nd_repstat;
@@ -5213,11 +5220,12 @@ nfsrpc_getlayout(struct nfsmount *nmp, vnode_t vp, str
* mount point and a pointer to it is returned.
*/
static int
-nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
- struct nfsclds **dspp, NFSPROC_T *p)
+nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in *sin,
+ struct sockaddr_in6 *sin6, sa_family_t af, int vers, struct nfsclds **dspp,
+ NFSPROC_T *p)
{
- struct sockaddr_in *msad, *sad, *ssd;
- struct sockaddr_in6 *msad6, *sad6, *ssd6;
+ struct sockaddr_in *msad, *sad;
+ struct sockaddr_in6 *msad6, *sad6;
struct nfsclclient *clp;
struct nfssockreq *nrp;
struct nfsclds *dsp, *tdsp;
@@ -5232,10 +5240,8 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_st
NFSUNLOCKCLSTATE();
if (clp == NULL)
return (EPERM);
- if (ssp->ss_family == AF_INET) {
- ssd = (struct sockaddr_in *)ssp;
+ if (af == AF_INET) {
NFSLOCKMNT(nmp);
-
/*
* Check to see if we already have a session for this
* address that is usable for a DS.
@@ -5246,8 +5252,8 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_st
tdsp = TAILQ_FIRST(&nmp->nm_sess);
while (tdsp != NULL) {
if (msad != NULL && msad->sin_family == AF_INET &&
- ssd->sin_addr.s_addr == msad->sin_addr.s_addr &&
- ssd->sin_port == msad->sin_port &&
+ sin->sin_addr.s_addr == msad->sin_addr.s_addr &&
+ sin->sin_port == msad->sin_port &&
(tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
tdsp->nfsclds_sess.nfsess_defunct == 0) {
*dspp = tdsp;
@@ -5268,14 +5274,12 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_st
sad = malloc(sizeof(*sad), M_SONAME, M_WAITOK | M_ZERO);
sad->sin_len = sizeof(*sad);
sad->sin_family = AF_INET;
- sad->sin_port = ssd->sin_port;
- sad->sin_addr.s_addr = ssd->sin_addr.s_addr;
+ sad->sin_port = sin->sin_port;
+ sad->sin_addr.s_addr = sin->sin_addr.s_addr;
nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
nrp->nr_nam = (struct sockaddr *)sad;
- } else if (ssp->ss_family == AF_INET6) {
- ssd6 = (struct sockaddr_in6 *)ssp;
+ } else if (af == AF_INET6) {
NFSLOCKMNT(nmp);
-
/*
* Check to see if we already have a session for this
* address that is usable for a DS.
@@ -5286,9 +5290,9 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_st
tdsp = TAILQ_FIRST(&nmp->nm_sess);
while (tdsp != NULL) {
if (msad6 != NULL && msad6->sin6_family == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(&ssd6->sin6_addr,
+ IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
&msad6->sin6_addr) &&
- ssd6->sin6_port == msad6->sin6_port &&
+ sin6->sin6_port == msad6->sin6_port &&
(tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
tdsp->nfsclds_sess.nfsess_defunct == 0) {
*dspp = tdsp;
@@ -5308,8 +5312,8 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_st
sad6 = malloc(sizeof(*sad6), M_SONAME, M_WAITOK | M_ZERO);
sad6->sin6_len = sizeof(*sad6);
sad6->sin6_family = AF_INET6;
- sad6->sin6_port = ssd6->sin6_port;
- NFSBCOPY(&ssd6->sin6_addr, &sad6->sin6_addr,
+ sad6->sin6_port = sin6->sin6_port;
+ NFSBCOPY(&sin6->sin6_addr, &sad6->sin6_addr,
sizeof(struct in6_addr));
nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
nrp->nr_nam = (struct sockaddr *)sad6;
@@ -5319,7 +5323,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_st
nrp->nr_sotype = SOCK_STREAM;
mtx_init(&nrp->nr_mtx, "nfssock", NULL, MTX_DEF);
nrp->nr_prog = NFS_PROG;
- nrp->nr_vers = NFS_VER4;
+ nrp->nr_vers = vers;
/*
* Use the credentials that were used for the mount, which are
More information about the svn-src-head
mailing list