Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Jan 2012 03:07:34 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r230295 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient
Message-ID:  <201201180307.q0I37YGh019550@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Wed Jan 18 03:07:34 2012
New Revision: 230295
URL: http://svn.freebsd.org/changeset/base/230295

Log:
  Modify the nfsclfldevinfo structure so that it stores the list of TCP
  connections and their NFSv4.1 sessions instead of the socket address.
  Add a function that fills in the TCP connection, clientid and session.
  These connection(s) should be usable for communication to the DS(s).
  This code is currently untested.

Modified:
  projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h
  projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c

Modified: projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Wed Jan 18 03:03:21 2012	(r230294)
+++ projects/nfsv4.1-client/sys/fs/nfs/nfsclstate.h	Wed Jan 18 03:07:34 2012	(r230295)
@@ -69,6 +69,14 @@ struct nfsclsession {
 	uint8_t		nfsess_sessionid[NFSX_V4SESSIONID];
 };
 
+/*
+ * This structure holds the information used to access a Data Server (DS).
+ */
+struct nfsclds {
+	struct nfssockreq	nfsclds_sock;
+	struct nfsclsession	nfsclds_sess;
+};
+
 struct nfsclclient {
 	LIST_ENTRY(nfsclclient) nfsc_list;
 	struct nfsclownerhead	nfsc_owner;
@@ -249,9 +257,9 @@ struct nfsclflayout {
 
 /*
  * Stores the NFSv4.1 Device Info. Malloc'd to the correct length to
- * store the list of network addresses and list of indices.
+ * store the list of network connections and list of indices.
  * nfsdi_data[] is allocated the following way:
- * - nfsdi_addrcnt * struct sockaddr_storage
+ * - nfsdi_addrcnt * struct nfsclds
  * - stripe indices, each stored as one byte, since there can be many
  *   of them. (This implies a limit of 256 on nfsdi_addrcnt, since the
  *   indices select which address.)
@@ -264,14 +272,14 @@ struct nfscldevinfo {
 	uint32_t			nfsdi_refcnt;
 	uint16_t			nfsdi_stripecnt;
 	uint16_t			nfsdi_addrcnt;
-	struct sockaddr_storage		nfsdi_data[1];
+	struct nfsclds			nfsdi_data[1];
 };
 
 /* These inline functions return values from nfsdi_data[]. */
 /*
  * Return a pointer to the address at "pos".
  */
-static __inline struct sockaddr_storage *
+static __inline struct nfsclds *
 nfsfldi_addr(struct nfscldevinfo *ndi, int pos)
 {
 

Modified: projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Wed Jan 18 03:03:21 2012	(r230294)
+++ projects/nfsv4.1-client/sys/fs/nfsclient/nfs_clrpcops.c	Wed Jan 18 03:07:34 2012	(r230295)
@@ -87,6 +87,8 @@ static int nfsrpc_setaclrpc(vnode_t, str
     struct acl *, nfsv4stateid_t *, void *);
 static int nfsrpc_getlayout(struct nfsmount *, struct nfsfh *, int, uint32_t *,
     nfsv4stateid_t *, struct ucred *, NFSPROC_T *);
+static int nfsrpc_fillsa(struct nfsmount *, struct nfsclds *,
+    struct sockaddr_storage *, NFSPROC_T *);
 
 /*
  * nfs null call from vfs.
@@ -4626,8 +4628,9 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 {
 	uint32_t cnt, *tl;
 	struct nfsrv_descript nfsd;
-	struct sockaddr_storage ss, *sa;
 	struct nfsrv_descript *nd = &nfsd;
+	struct sockaddr_storage ss;
+	struct nfsclds *sa;
 	struct nfscldevinfo *ndi;
 	int addrcnt, bitcnt, error, i, isudp, j, pos, safilled, stripecnt;
 	uint8_t stripeindex;
@@ -4664,7 +4667,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		}
 		NFSM_DISSECT(tl, uint32_t *, (stripecnt + 1) * NFSX_UNSIGNED);
 		addrcnt = fxdr_unsigned(int, *(tl + stripecnt));
-		if (addrcnt < 0 || addrcnt > 128) {
+		if (addrcnt < 1 || addrcnt > 128) {
 			printf("NFS devinfo addrcnt %d: out of range\n",
 			    addrcnt);
 			error = NFSERR_BADXDR;
@@ -4675,10 +4678,9 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		 * Now we know how many stripe indices and addresses, so
 		 * we can allocate the structure the correct size.
 		 */
-		i = stripecnt / sizeof(struct sockaddr_storage) + 1;
+		i = stripecnt / sizeof(struct nfsclds) + 1;
 		ndi = malloc(sizeof(*ndi) + (addrcnt + i - 1) *
-		    sizeof(struct sockaddr_storage),
-		    M_NFSDEVINFO, M_WAITOK);
+		    sizeof(struct nfsclds), M_NFSDEVINFO, M_WAITOK | M_ZERO);
 		NFSBCOPY(deviceid, ndi->nfsdi_deviceid, NFSX_V4DEVICEID);
 		ndi->nfsdi_refcnt = 0;
 		ndi->nfsdi_stripecnt = stripecnt;
@@ -4696,6 +4698,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 		}
 
 		/* Now, dissect the server address(es). */
+		safilled = 0;
 		for (i = 0; i < addrcnt; i++) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 			cnt = fxdr_unsigned(uint32_t, *tl);
@@ -4730,31 +4733,48 @@ nfsrpc_getdeviceinfo(struct nfsmount *nm
 					      nmp->nm_nam->sa_family)) ||
 					    (safilled == 1 && ss.ss_family ==
 					     nmp->nm_nam->sa_family)) {
-						NFSBCOPY(&ss, sa, sizeof(ss));
-						if (ss.ss_family ==
-						    nmp->nm_nam->sa_family)
-							safilled = 2;
-						else
-							safilled = 1;
+						error = nfsrpc_fillsa(nmp, sa,
+						    &ss, p);
+						if (error == 0) {
+							if (ss.ss_family ==
+							 nmp->nm_nam->sa_family)
+								safilled = 2;
+							else
+								safilled = 1;
+						}
 					}
 				}
 			}
+			if (safilled == 0)
+				break;
 		}
 
 		/* And the notify bits. */
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
-		bitcnt = fxdr_unsigned(int, *tl);
-		if (bitcnt > 0) {
-			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
-			*notifybitsp = fxdr_unsigned(uint32_t, *tl);
-		}
-		*ndip = ndi;
+		if (safilled != 0) {
+			bitcnt = fxdr_unsigned(int, *tl);
+			if (bitcnt > 0) {
+				NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+				*notifybitsp = fxdr_unsigned(uint32_t, *tl);
+			}
+			*ndip = ndi;
+		} else
+			error = EPERM;
 	}
 	if (nd->nd_repstat != 0)
 		error = nd->nd_repstat;
 nfsmout:
-	if (error != 0 && ndi != NULL)
+	if (error != 0 && ndi != NULL) {
+		for (i = 0; i < ndi->nfsdi_addrcnt; i++) {
+			sa = nfsfldi_addr(ndi, i);
+			if (sa->nfsclds_sock.nr_nam != NULL) {
+				/* Both are set or both are NULL. */
+				NFSFREECRED(sa->nfsclds_sock.nr_cred);
+				free(sa->nfsclds_sock.nr_nam, M_SONAME);
+			}
+		}
 		free(ndi, M_NFSDEVINFO);
+	}
 	mbuf_freem(nd->nd_mrep);
 	return (error);
 }
@@ -4939,3 +4959,72 @@ nfsrpc_getlayout(struct nfsmount *nmp, s
 	return (error);
 }
 
+/*
+ * Fill in nfsclds, doing the TCP connect plus exchangeid and create session.
+ * The nfsclds structure pointed to by dsp is all zero'd out.
+ */
+static int
+nfsrpc_fillsa(struct nfsmount *nmp, struct nfsclds *dsp,
+    struct sockaddr_storage *ssp, NFSPROC_T *p)
+{
+	struct sockaddr_in *sad, *ssd;
+	struct sockaddr_in6 *sad6, *ssd6;
+	struct nfsclclient *clp;
+	int error;
+
+	KASSERT(nmp->nm_sockreq.nr_cred != NULL,
+	    ("nfsrpc_fillsa: NULL nr_cred"));
+	NFSLOCKCLSTATE();
+	clp = nmp->nm_clp;
+	NFSUNLOCKCLSTATE();
+	if (clp == NULL)
+		return (EPERM);
+	if (ssp->ss_family == AF_INET) {
+		ssd = (struct sockaddr_in *)ssp;
+		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;
+		dsp->nfsclds_sock.nr_nam = (struct sockaddr *)sad;
+	} else if (ssp->ss_family == AF_INET6) {
+		ssd6 = (struct sockaddr_in6 *)ssp;
+		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,
+		    sizeof(struct in6_addr));
+		dsp->nfsclds_sock.nr_nam = (struct sockaddr *)sad6;
+	} else
+		return (EPERM);
+	dsp->nfsclds_sock.nr_sotype = SOCK_STREAM;
+	mtx_init(&dsp->nfsclds_sock.nr_mtx, "nfssock", NULL, MTX_DEF);
+	dsp->nfsclds_sock.nr_prog = NFS_PROG;
+	dsp->nfsclds_sock.nr_vers = NFS_VER4;
+
+	/*
+	 * Use the credentials that were used for the mount, which are
+	 * in nmp->nm_sockreq.nr_cred for newnfs_connect() etc.
+	 * Ref. counting the credentials with crhold() is probably not
+	 * necessary, since nm_sockreq.nr_cred won't be crfree()'d until
+	 * unmount, but I did it anyhow.
+	 */
+	dsp->nfsclds_sock.nr_cred = crhold(nmp->nm_sockreq.nr_cred);
+	error = newnfs_connect(nmp, &dsp->nfsclds_sock, NULL, p, 0);
+
+	/* Now, do the exchangeid and create session. */
+	if (error == 0)
+		error = nfsrpc_exchangeid(nmp, clp, &dsp->nfsclds_sess,
+		    NFSV4EXCH_USEPNFSDS, dsp->nfsclds_sock.nr_cred, p);
+	if (error == 0)
+		error = nfsrpc_createsession(nmp, &dsp->nfsclds_sess,
+		    dsp->nfsclds_sock.nr_cred, p);
+	if (error != 0) {
+		NFSFREECRED(dsp->nfsclds_sock.nr_cred);
+		free(dsp->nfsclds_sock.nr_nam, M_SONAME);
+		NFSBZERO(dsp, sizeof(*dsp));
+	}
+	return (error);
+}
+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201180307.q0I37YGh019550>