svn commit: r230295 - in projects/nfsv4.1-client/sys/fs: nfs
nfsclient
Rick Macklem
rmacklem at FreeBSD.org
Wed Jan 18 03:07:35 UTC 2012
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);
+}
+
More information about the svn-src-projects
mailing list