From owner-svn-src-projects@FreeBSD.ORG Wed Jan 18 03:07:35 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 35437106567F; Wed, 18 Jan 2012 03:07:35 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 200C48FC1A; Wed, 18 Jan 2012 03:07:35 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q0I37Yfv019553; Wed, 18 Jan 2012 03:07:34 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q0I37YGh019550; Wed, 18 Jan 2012 03:07:34 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <201201180307.q0I37YGh019550@svn.freebsd.org> From: Rick Macklem Date: Wed, 18 Jan 2012 03:07:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r230295 - in projects/nfsv4.1-client/sys/fs: nfs nfsclient X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 Jan 2012 03:07:35 -0000 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); +} +