Page MenuHomeFreeBSD

D29475.diff
No OneTemporary

D29475.diff

diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -218,7 +218,7 @@
static int nfs_bigreply[NFSV42_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 1 };
+ 1, 0, 0, 1, 0 };
/* local functions */
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
@@ -301,6 +301,7 @@
{ NFSV4OP_SETXATTR, 2, "Setxattr", 8, },
{ NFSV4OP_REMOVEXATTR, 2, "Rmxattr", 7, },
{ NFSV4OP_LISTXATTRS, 2, "Listxattr", 9, },
+ { NFSV4OP_BINDCONNTOSESS, 1, "BindConSess", 11, },
};
/*
@@ -309,7 +310,7 @@
static int nfs_bigrequest[NFSV42_NPROCS] = {
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
};
/*
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -561,6 +561,7 @@
struct nfsvattr *, int *, struct ucred *, NFSPROC_T *);
int nfsrpc_rmextattr(vnode_t, const char *, struct nfsvattr *, int *,
struct ucred *, NFSPROC_T *);
+void nfsrpc_bindconnsess(CLIENT *, void *, struct ucred *);
/* nfs_clstate.c */
int nfscl_open(vnode_t, u_int8_t *, int, u_int32_t, int,
diff --git a/sys/fs/nfs/nfscl.h b/sys/fs/nfs/nfscl.h
--- a/sys/fs/nfs/nfscl.h
+++ b/sys/fs/nfs/nfscl.h
@@ -81,4 +81,9 @@
printf(__VA_ARGS__); \
} while (0)
+struct nfscl_reconarg {
+ int minorvers;
+ uint8_t sessionid[NFSX_V4SESSIONID];
+};
+
#endif /* _NFS_NFSCL_H */
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -412,10 +412,13 @@
#define NFSPROC_RMEXTATTR 63
#define NFSPROC_LISTEXTATTR 64
+/* BindConnectionToSession, done by the krpc for a new connection. */
+#define NFSPROC_BINDCONNTOSESS 65
+
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 65
+#define NFSV42_NPROCS 66
#endif /* NFS_V3NPROCS */
@@ -444,7 +447,7 @@
uint64_t readlink_bios;
uint64_t biocache_readdirs;
uint64_t readdir_bios;
- uint64_t rpccnt[NFSV42_NPROCS + 15];
+ uint64_t rpccnt[NFSV42_NPROCS + 14];
uint64_t rpcretries;
uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS + 15];
uint64_t reserved_0;
@@ -509,7 +512,7 @@
uint64_t readlink_bios;
uint64_t biocache_readdirs;
uint64_t readdir_bios;
- uint64_t rpccnt[NFSV42_NPROCS + 4];
+ uint64_t rpccnt[NFSV42_NPROCS + 3];
uint64_t rpcretries;
uint64_t srvrpccnt[NFSV42_PURENOPS + NFSV4OP_FAKENOPS];
uint64_t reserved_0;
diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h
--- a/sys/fs/nfs/nfsproto.h
+++ b/sys/fs/nfs/nfsproto.h
@@ -394,10 +394,13 @@
#define NFSPROC_RMEXTATTR 63
#define NFSPROC_LISTEXTATTR 64
+/* BindConnectionToSession, done by the krpc for a new connection. */
+#define NFSPROC_BINDCONNTOSESS 65
+
/*
* Must be defined as one higher than the last NFSv4.2 Proc# above.
*/
-#define NFSV42_NPROCS 65
+#define NFSV42_NPROCS 66
#endif /* NFS_V3NPROCS */
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -946,6 +946,8 @@
struct nfsclds *dsp, *odsp;
struct in6_addr a6;
struct nfsclsession *tsep;
+ struct rpc_reconupcall recon;
+ struct nfscl_reconarg *rcp;
if (nfsboottime.tv_sec == 0)
NFSSETBOOTTIME(nfsboottime);
@@ -1019,6 +1021,23 @@
NFSCL_DEBUG(1, "aft createsess=%d\n", error);
}
if (error == 0) {
+ /*
+ * If the session supports a backchannel, set up
+ * the BindConnectionToSession call in the krpc
+ * so that it is done on a reconnection.
+ */
+ if (nfscl_enablecallb != 0 && nfs_numnfscbd > 0) {
+ rcp = mem_alloc(sizeof(*rcp));
+ rcp->minorvers = nmp->nm_minorvers;
+ memcpy(rcp->sessionid,
+ dsp->nfsclds_sess.nfsess_sessionid,
+ NFSX_V4SESSIONID);
+ recon.call = nfsrpc_bindconnsess;
+ recon.arg = rcp;
+ CLNT_CONTROL(nmp->nm_client, CLSET_RECONUPCALL,
+ &recon);
+ }
+
NFSLOCKMNT(nmp);
/*
* The old sessions cannot be safely free'd
@@ -8709,3 +8728,74 @@
m->m_next = NULL;
return (m2);
}
+
+/*
+ * Do the NFSv4.1 Bind Connection to Session.
+ * Called from the reconnect layer of the krpc (sys/rpc/clnt_rc.c).
+ */
+void
+nfsrpc_bindconnsess(CLIENT *cl, void *arg, struct ucred *cr)
+{
+ struct nfscl_reconarg *rcp = (struct nfscl_reconarg *)arg;
+ uint32_t res, *tl;
+ struct nfsrv_descript nfsd;
+ struct nfsrv_descript *nd = &nfsd;
+ struct rpc_callextra ext;
+ struct timeval utimeout;
+ enum clnt_stat stat;
+ int error;
+
+ nfscl_reqstart(nd, NFSPROC_BINDCONNTOSESS, NULL, NULL, 0, NULL, NULL,
+ NFS_VER4, rcp->minorvers);
+ NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 2 * NFSX_UNSIGNED);
+ memcpy(tl, rcp->sessionid, NFSX_V4SESSIONID);
+ tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
+ *tl++ = txdr_unsigned(NFSCDFC4_FORE_OR_BOTH);
+ *tl = newnfs_false;
+
+ memset(&ext, 0, sizeof(ext));
+ utimeout.tv_sec = 30;
+ utimeout.tv_usec = 0;
+ ext.rc_auth = authunix_create(cr);
+ nd->nd_mrep = NULL;
+ stat = CLNT_CALL_MBUF(cl, &ext, NFSV4PROC_COMPOUND, nd->nd_mreq,
+ &nd->nd_mrep, utimeout);
+ AUTH_DESTROY(ext.rc_auth);
+ if (stat != RPC_SUCCESS) {
+ printf("nfsrpc_bindconnsess: call failed stat=%d\n", stat);
+ return;
+ }
+ if (nd->nd_mrep == NULL) {
+ printf("nfsrpc_bindconnsess: no reply args\n");
+ return;
+ }
+ error = 0;
+ newnfs_realign(&nd->nd_mrep, M_WAITOK);
+ nd->nd_md = nd->nd_mrep;
+ nd->nd_dpos = mtod(nd->nd_md, char *);
+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+ nd->nd_repstat = fxdr_unsigned(uint32_t, *tl++);
+ if (nd->nd_repstat == NFSERR_OK) {
+ res = fxdr_unsigned(uint32_t, *tl);
+ if (res > 0 && (error = nfsm_advance(nd, NFSM_RNDUP(res),
+ -1)) != 0)
+ goto nfsmout;
+ NFSM_DISSECT(tl, uint32_t *, NFSX_V4SESSIONID +
+ 4 * NFSX_UNSIGNED);
+ tl += 3;
+ if (!NFSBCMP(tl, rcp->sessionid, NFSX_V4SESSIONID)) {
+ tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
+ res = fxdr_unsigned(uint32_t, *tl);
+ if (res != NFSCDFS4_BOTH)
+ printf("nfsrpc_bindconnsess: did not "
+ "return FS4_BOTH\n");
+ } else
+ printf("nfsrpc_bindconnsess: not same "
+ "sessionid\n");
+ } else if (nd->nd_repstat != NFSERR_BADSESSION)
+ printf("nfsrpc_bindconnsess: returned %d\n", nd->nd_repstat);
+nfsmout:
+ if (error != 0)
+ printf("nfsrpc_bindconnsess: reply bad xdr\n");
+ m_freem(nd->nd_mrep);
+}
diff --git a/sys/rpc/clnt.h b/sys/rpc/clnt.h
--- a/sys/rpc/clnt.h
+++ b/sys/rpc/clnt.h
@@ -360,6 +360,12 @@
#define CLSET_TLS 30 /* set TLS for socket */
#define CLSET_BLOCKRCV 31 /* Temporarily block reception */
#define CLSET_TLSCERTNAME 32 /* TLS certificate file name */
+/* Structure used as the argument for CLSET_RECONUPCALL. */
+struct rpc_reconupcall {
+ void (*call)(CLIENT *, void *, struct ucred *);
+ void *arg;
+};
+#define CLSET_RECONUPCALL 33 /* Reconnect upcall */
#endif
diff --git a/sys/rpc/clnt_rc.c b/sys/rpc/clnt_rc.c
--- a/sys/rpc/clnt_rc.c
+++ b/sys/rpc/clnt_rc.c
@@ -111,6 +111,8 @@
rc->rc_client = NULL;
rc->rc_tls = false;
rc->rc_tlscertname = NULL;
+ rc->rc_reconcall = NULL;
+ rc->rc_reconarg = NULL;
cl->cl_refs = 1;
cl->cl_ops = &clnt_reconnect_ops;
@@ -213,6 +215,9 @@
goto out;
}
}
+ if (newclient != NULL && rc->rc_reconcall != NULL)
+ (*rc->rc_reconcall)(newclient, rc->rc_reconarg,
+ rc->rc_ucred);
}
td->td_ucred = oldcred;
@@ -408,6 +413,7 @@
struct rc_data *rc = (struct rc_data *)cl->cl_private;
SVCXPRT *xprt;
size_t slen;
+ struct rpc_reconupcall *upcp;
if (info == NULL) {
return (FALSE);
@@ -513,6 +519,12 @@
strlcpy(rc->rc_tlscertname, info, slen);
break;
+ case CLSET_RECONUPCALL:
+ upcp = (struct rpc_reconupcall *)info;
+ rc->rc_reconcall = upcp->call;
+ rc->rc_reconarg = upcp->arg;
+ break;
+
default:
return (FALSE);
}
@@ -555,12 +567,15 @@
CLNT_DESTROY(rc->rc_client);
if (rc->rc_backchannel) {
xprt = (SVCXPRT *)rc->rc_backchannel;
+ KASSERT(xprt->xp_socket == NULL,
+ ("clnt_reconnect_destroy: xp_socket not NULL"));
xprt_unregister(xprt);
SVC_RELEASE(xprt);
}
crfree(rc->rc_ucred);
mtx_destroy(&rc->rc_lock);
mem_free(rc->rc_tlscertname, 0); /* 0 ok, since arg. ignored. */
+ mem_free(rc->rc_reconarg, 0);
mem_free(rc, sizeof(*rc));
mem_free(cl, sizeof (CLIENT));
}
diff --git a/sys/rpc/krpc.h b/sys/rpc/krpc.h
--- a/sys/rpc/krpc.h
+++ b/sys/rpc/krpc.h
@@ -81,6 +81,9 @@
void *rc_backchannel;
bool rc_tls; /* Enable TLS on connection */
char *rc_tlscertname;
+ void (*rc_reconcall)(CLIENT *, void *,
+ struct ucred *); /* reconection upcall */
+ void *rc_reconarg; /* upcall arg */
};
/* Bits for ct_rcvstate. */

File Metadata

Mime Type
text/plain
Expires
Thu, Feb 6, 4:30 AM (21 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16486994
Default Alt Text
D29475.diff (8 KB)

Event Timeline