FreeBSD Bugzilla – Attachment 192666 Details for
Bug 226493
ESX NFSv4.1 client can't perform the BindConnectiontoSession operation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Add partial support for BindConnectiontoSession to the NFSv4.1 server
bindconn.patch (text/plain), 10.74 KB, created by
Rick Macklem
on 2018-04-19 20:14:58 UTC
(
hide
)
Description:
Add partial support for BindConnectiontoSession to the NFSv4.1 server
Filename:
MIME Type:
Creator:
Rick Macklem
Created:
2018-04-19 20:14:58 UTC
Size:
10.74 KB
patch
obsolete
>--- fs/nfs/nfsrvstate.h.orig 2018-04-18 20:21:06.867273000 -0400 >+++ fs/nfs/nfsrvstate.h 2018-04-18 20:24:04.195280000 -0400 >@@ -101,6 +101,7 @@ struct nfsclient { > u_char *lc_name; > struct nfssockreq lc_req; /* Callback info */ > u_int32_t lc_flags; /* LCL_ flag bits */ >+ u_int32_t lc_sesscnt; /* Count of sessions. */ > u_char lc_verf[NFSX_VERF]; /* client verifier */ > u_char lc_id[1]; /* Malloc'd correct size */ > }; >--- fs/nfs/nfs.h.orig 2018-04-18 20:18:53.516512000 -0400 >+++ fs/nfs/nfs.h 2018-04-18 20:24:04.197332000 -0400 >@@ -128,6 +128,9 @@ > #ifndef NFS_ACCESSCACHESIZE > #define NFS_ACCESSCACHESIZE 8 > #endif >+#ifndef NFSRV_MAXCLIENTSESS >+#define NFSRV_MAXCLIENTSESS 32 >+#endif > #define NFSV4_CBPORT 7745 /* Callback port for testing */ > > /* >@@ -299,6 +302,7 @@ struct nfsreferral { > #define LCL_ADMINREVOKED 0x00008000 > #define LCL_RECLAIMCOMPLETE 0x00010000 > #define LCL_NFSV41 0x00020000 >+#define LCL_DONEBINDCONN 0x00040000 > > #define LCL_GSS LCL_KERBV /* Or of all mechs */ > >--- fs/nfs/nfs_var.h.orig 2018-04-18 20:20:35.572475000 -0400 >+++ fs/nfs/nfs_var.h 2018-04-18 20:24:04.199185000 -0400 >@@ -95,6 +95,7 @@ int nfsrv_getclient(nfsquad_t, int, stru > nfsquad_t, uint32_t, struct nfsrv_descript *, NFSPROC_T *); > int nfsrv_destroyclient(nfsquad_t, NFSPROC_T *); > int nfsrv_destroysession(struct nfsrv_descript *, uint8_t *); >+int nfsrv_bindconnsess(struct nfsrv_descript *, uint8_t *, int *); > int nfsrv_freestateid(struct nfsrv_descript *, nfsv4stateid_t *, NFSPROC_T *); > int nfsrv_adminrevoke(struct nfsd_clid *, NFSPROC_T *); > void nfsrv_dumpclients(struct nfsd_dumpclients *, int); >@@ -230,6 +231,8 @@ int nfsrvd_reclaimcomplete(struct nfsrv_ > vnode_t, NFSPROC_T *, struct nfsexstuff *); > int nfsrvd_destroyclientid(struct nfsrv_descript *, int, > vnode_t, NFSPROC_T *, struct nfsexstuff *); >+int nfsrvd_bindconnsess(struct nfsrv_descript *, int, >+ vnode_t, NFSPROC_T *, struct nfsexstuff *); > int nfsrvd_destroysession(struct nfsrv_descript *, int, > vnode_t, NFSPROC_T *, struct nfsexstuff *); > int nfsrvd_freestateid(struct nfsrv_descript *, int, >--- fs/nfs/nfs_commonsubs.c.orig 2018-04-18 20:19:27.017290000 -0400 >+++ fs/nfs/nfs_commonsubs.c 2018-04-18 20:24:04.201895000 -0400 >@@ -136,7 +136,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV41_ > { 0, 2, 1, 1, LK_EXCLUSIVE, 1, 0 }, /* Write */ > { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 }, /* ReleaseLockOwner */ > { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Backchannel Ctrl */ >- { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 }, /* Bind Conn to Sess */ >+ { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Bind Conn to Sess */ > { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Exchange ID */ > { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Create Session */ > { 0, 0, 0, 0, LK_EXCLUSIVE, 0, 0 }, /* Destroy Session */ >--- fs/nfs/nfsproto.h.orig 2018-04-18 20:18:20.725787000 -0400 >+++ fs/nfs/nfsproto.h 2018-04-18 20:24:04.212443000 -0400 >@@ -650,6 +650,15 @@ > #define NFSFLAYUTIL_DENSE 0x1 > #define NFSFLAYUTIL_COMMIT_THRU_MDS 0x2 > >+/* Enum values for Bind Connection to Session. */ >+#define NFSCDFC4_FORE 0x1 >+#define NFSCDFC4_BACK 0x2 >+#define NFSCDFC4_FORE_OR_BOTH 0x3 >+#define NFSCDFC4_BACK_OR_BOTH 0x7 >+#define NFSCDFS4_FORE 0x1 >+#define NFSCDFS4_BACK 0x2 >+#define NFSCDFS4_BOTH 0x3 >+ > /* Conversion macros */ > #define vtonfsv2_mode(t,m) \ > txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \ >--- fs/nfsserver/nfs_nfsdstate.c.orig 2018-04-18 20:22:26.030375000 -0400 >+++ fs/nfsserver/nfs_nfsdstate.c 2018-04-18 21:17:51.642392000 -0400 >@@ -41,6 +41,7 @@ extern struct nfsstatsv1 nfsstatsv1; > extern int nfsrv_lease; > extern struct timeval nfsboottime; > extern u_int32_t newnfs_true, newnfs_false; >+extern int nfsd_debuglevel; > NFSV4ROOTLOCKMUTEX; > NFSSTATESPINLOCK; > >@@ -582,6 +583,11 @@ nfsrv_getclient(nfsquad_t clientid, int > error = NFSERR_STALECLIENTID; > else if (nfsrv_notsamecredname(nd, clp)) > error = NFSERR_CLIDINUSE; >+ else if ((nd->nd_flag & ND_NFSV41) != 0 && nsep != NULL && >+ clp->lc_sesscnt > NFSRV_MAXCLIENTSESS) { >+ NFSD_DEBUG(2, "nfsrv_getclient: too many sessions\n"); >+ error = NFSERR_RESOURCE; >+ } > > if (!error) { > if ((clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_DONTCLEAN)) == >@@ -614,10 +620,11 @@ nfsrv_getclient(nfsquad_t clientid, int > if (nsep != NULL) { > /* Hold a reference on the xprt for a backchannel. */ > if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) >- != 0 && clp->lc_req.nr_client == NULL) { >- clp->lc_req.nr_client = (struct __rpc_client *) >- clnt_bck_create(nd->nd_xprt->xp_socket, >- cbprogram, NFSV4_CBVERS); >+ != 0) { >+ if (clp->lc_req.nr_client == NULL) >+ clp->lc_req.nr_client = (struct __rpc_client *) >+ clnt_bck_create(nd->nd_xprt->xp_socket, >+ cbprogram, NFSV4_CBVERS); > if (clp->lc_req.nr_client != NULL) { > SVC_ACQUIRE(nd->nd_xprt); > nd->nd_xprt->xp_p2 = >@@ -638,6 +645,7 @@ nfsrv_getclient(nfsquad_t clientid, int > LIST_INSERT_HEAD(&shp->list, nsep, sess_hash); > LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list); > nsep->sess_clp = clp; >+ clp->lc_sesscnt++; > NFSUNLOCKSESSION(shp); > NFSUNLOCKSTATE(); > } >@@ -4213,9 +4221,10 @@ nfsrv_docallback(struct nfsclient *clp, > */ > (void) newnfs_sndlock(&clp->lc_req.nr_lock); > if (clp->lc_req.nr_client == NULL) { >- if ((clp->lc_flags & LCL_NFSV41) != 0) >+ if ((clp->lc_flags & LCL_NFSV41) != 0) { > error = ECONNREFUSED; >- else if (nd->nd_procnum == NFSV4PROC_CBNULL) >+ nfsrv_freesession(sep, NULL); >+ } else if (nd->nd_procnum == NFSV4PROC_CBNULL) > error = newnfs_connect(NULL, &clp->lc_req, cred, > NULL, 1); > else >@@ -5831,9 +5840,18 @@ nfsrv_checksequence(struct nfsrv_descrip > /* > * If this session handles the backchannel, save the nd_xprt for this > * RPC, since this is the one being used. >+ * RFC-5661 specifies that the fore channel will be implicitly >+ * bound by a Sequence operation. However, since some NFSv4.1 clients >+ * erroneously assumed that the back channel would be implicitly >+ * bound as well, do the implicit binding unless a >+ * BindConnectiontoSession has already been done on the session. > */ > if (sep->sess_clp->lc_req.nr_client != NULL && >- (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) { >+ sep->sess_cbsess.nfsess_xprt != nd->nd_xprt && >+ (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0 && >+ (sep->sess_clp->lc_flags & LCL_DONEBINDCONN) == 0) { >+ NFSD_DEBUG(2, >+ "nfsrv_checksequence: implicit back channel bind\n"); > savxprt = sep->sess_cbsess.nfsess_xprt; > SVC_ACQUIRE(nd->nd_xprt); > nd->nd_xprt->xp_p2 = >@@ -5950,6 +5968,80 @@ nfsrv_destroysession(struct nfsrv_descri > } > > /* >+ * Bind a connection to a session. >+ * For now, only certain variants are supported, since the current session >+ * structure can only handle a single backchannel entry, which will be >+ * applied to all connections if it is set. >+ */ >+int >+nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp) >+{ >+ struct nfssessionhash *shp; >+ struct nfsdsession *sep; >+ struct nfsclient *clp; >+ SVCXPRT *savxprt; >+ int error; >+ >+ error = 0; >+ shp = NFSSESSIONHASH(sessionid); >+ NFSLOCKSTATE(); >+ NFSLOCKSESSION(shp); >+ sep = nfsrv_findsession(sessionid); >+ if (sep != NULL) { >+ clp = sep->sess_clp; >+ if (*foreaftp == NFSCDFC4_BACK || >+ *foreaftp == NFSCDFC4_BACK_OR_BOTH || >+ *foreaftp == NFSCDFC4_FORE_OR_BOTH) { >+ /* Try to set up a backchannel. */ >+ if (clp->lc_req.nr_client == NULL) { >+ NFSD_DEBUG(2, "nfsrv_bindconnsess: acquire " >+ "backchannel\n"); >+ clp->lc_req.nr_client = (struct __rpc_client *) >+ clnt_bck_create(nd->nd_xprt->xp_socket, >+ sep->sess_cbprogram, NFSV4_CBVERS); >+ } >+ if (clp->lc_req.nr_client != NULL) { >+ NFSD_DEBUG(2, "nfsrv_bindconnsess: set up " >+ "backchannel\n"); >+ savxprt = sep->sess_cbsess.nfsess_xprt; >+ SVC_ACQUIRE(nd->nd_xprt); >+ nd->nd_xprt->xp_p2 = >+ clp->lc_req.nr_client->cl_private; >+ /* Disable idle timeout. */ >+ nd->nd_xprt->xp_idletimeout = 0; >+ sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; >+ if (savxprt != NULL) >+ SVC_RELEASE(savxprt); >+ sep->sess_crflags |= NFSV4CRSESS_CONNBACKCHAN; >+ clp->lc_flags |= LCL_DONEBINDCONN; >+ if (*foreaftp == NFSCDFS4_BACK) >+ *foreaftp = NFSCDFS4_BACK; >+ else >+ *foreaftp = NFSCDFS4_BOTH; >+ } else if (*foreaftp != NFSCDFC4_BACK) { >+ NFSD_DEBUG(2, "nfsrv_bindconnsess: can't set " >+ "up backchannel\n"); >+ sep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN; >+ clp->lc_flags |= LCL_DONEBINDCONN; >+ *foreaftp = NFSCDFS4_FORE; >+ } else { >+ error = NFSERR_NOTSUPP; >+ printf("nfsrv_bindconnsess: Can't add " >+ "backchannel\n"); >+ } >+ } else { >+ NFSD_DEBUG(2, "nfsrv_bindconnsess: Set forechannel\n"); >+ clp->lc_flags |= LCL_DONEBINDCONN; >+ *foreaftp = NFSCDFS4_FORE; >+ } >+ } else >+ error = NFSERR_BADSESSION; >+ NFSUNLOCKSESSION(shp); >+ NFSUNLOCKSTATE(); >+ return (error); >+} >+ >+/* > * Free up a session structure. > */ > static int >@@ -5976,6 +6068,7 @@ nfsrv_freesession(struct nfsdsession *se > } > LIST_REMOVE(sep, sess_hash); > LIST_REMOVE(sep, sess_list); >+ sep->sess_clp->lc_sesscnt--; > } > NFSUNLOCKSESSION(shp); > NFSUNLOCKSTATE(); >--- fs/nfsserver/nfs_nfsdserv.c.orig 2018-04-18 20:21:49.097492000 -0400 >+++ fs/nfsserver/nfs_nfsdserv.c 2018-04-18 20:24:04.208691000 -0400 >@@ -4041,6 +4041,45 @@ nfsmout: > } > > /* >+ * nfsv4 bind connection to session service >+ */ >+APPLESTATIC int >+nfsrvd_bindconnsess(struct nfsrv_descript *nd, __unused int isdgram, >+ __unused vnode_t vp, NFSPROC_T *p, __unused struct nfsexstuff *exp) >+{ >+ uint32_t *tl; >+ uint8_t sessid[NFSX_V4SESSIONID]; >+ int error = 0, foreaft; >+ >+ if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) { >+ nd->nd_repstat = NFSERR_WRONGSEC; >+ goto nfsmout; >+ } >+ NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED); >+ NFSBCOPY(tl, sessid, NFSX_V4SESSIONID); >+ tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED); >+ foreaft = fxdr_unsigned(int, *tl++); >+ if (*tl == newnfs_true) { >+ /* RDMA is not supported. */ >+ nd->nd_repstat = NFSERR_NOTSUPP; >+ goto nfsmout; >+ } >+ >+ nd->nd_repstat = nfsrv_bindconnsess(nd, sessid, &foreaft); >+ if (nd->nd_repstat == 0) { >+ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 2 * >+ NFSX_UNSIGNED); >+ NFSBCOPY(sessid, tl, NFSX_V4SESSIONID); >+ tl += (NFSX_V4SESSIONID / NFSX_UNSIGNED); >+ *tl++ = txdr_unsigned(foreaft); >+ *tl = newnfs_false; >+ } >+nfsmout: >+ NFSEXITCODE2(error, nd); >+ return (error); >+} >+ >+/* > * nfsv4 destroy session service > */ > APPLESTATIC int >--- fs/nfsserver/nfs_nfsdsocket.c.orig 2018-04-18 20:23:00.781713000 -0400 >+++ fs/nfsserver/nfs_nfsdsocket.c 2018-04-18 20:24:04.210613000 -0400 >@@ -176,7 +176,7 @@ int (*nfsrv4_ops0[NFSV41_NOPS])(struct n > nfsrvd_write, > nfsrvd_releaselckown, > nfsrvd_notsupp, >- nfsrvd_notsupp, >+ nfsrvd_bindconnsess, > nfsrvd_exchangeid, > nfsrvd_createsession, > nfsrvd_destroysession,
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 226493
:
191364
|
192534
| 192666