Subject: Re: EJUKEBOX
To: None <rick@snowhite.cis.uoguelph.ca>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-kern
Date: 07/23/2003 00:17:13
--NextPart-20030723000619-0312200
Content-Type: Text/Plain; charset=us-ascii

hi,

> I don't really think anyone uses NQNFS and it will be superceded by NFS V4
> completely. I recently became aware of the requirement for a different xid
> for V4 (never noticed that for V3). I also don't thing using a different xid
> will do any harm for NQNFS, if anyone cares. (My vague recollection is that
> NQNFS TRYLATER is just used for what NFS V4 calls NFSERR_GRACE, which means
> the server just restarted and is letting clients recover leases. If that is
> correct, the xid doesn't matter.)

i see.  thanks for clarification.

i made a patch. (attached, not yet tested)
i'll commit it after testing, hopefully tomorrow or so.

YAMAMOTO Takashi


--NextPart-20030723000619-0312200
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="nfs.jukebox.xid.diff"

Index: nfs_socket.c
===================================================================
--- nfs_socket.c	(revision 227)
+++ nfs_socket.c	(revision 228)
@@ -1138,6 +1138,12 @@ tryagain:
 				if (trylater_cnt + 1 <
 				   sizeof(nfs_backoff) / sizeof(nfs_backoff[0]))
 					trylater_cnt++;
+				/*
+				 * RFC1813:
+				 * The client should wait and then try
+				 * the request with a new RPC transaction ID.
+				 */
+				nfs_renewxid(rep);
 				goto tryagain;
 			}
 
Index: nfs_var.h
===================================================================
--- nfs_var.h	(revision 227)
+++ nfs_var.h	(revision 228)
@@ -301,6 +301,9 @@ void nfsrv_setcred __P((struct ucred *, 
 void nfs_cookieheuristic __P((struct vnode *, int *, struct proc *,
 			      struct ucred *));
 
+u_int32_t nfs_getxid __P((void));
+void nfs_renewxid __P((struct nfsreq *));
+
 /* nfs_syscalls.c */
 int sys_getfh __P((struct lwp *, void *, register_t *));
 int sys_nfssvc __P((struct lwp *, void *, register_t *));
Index: nfs_subs.c
===================================================================
--- nfs_subs.c	(revision 227)
+++ nfs_subs.c	(revision 228)
@@ -133,7 +133,6 @@ u_int32_t rpc_call, rpc_vers, rpc_reply,
 u_int32_t nfs_prog, nqnfs_prog, nfs_true, nfs_false;
 
 /* And other global data */
-static u_int32_t nfs_xid = 0;
 const nfstype nfsv2_type[9] =
 	{ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, NFCHR, NFNON };
 const nfstype nfsv3_type[9] =
@@ -665,8 +664,6 @@ nfsm_rpchead(cr, nmflag, procid, auth_ty
 	int i;
 	struct mbuf *mreq;
 	int siz, grpsiz, authsiz;
-	struct timeval tv;
-	static u_int32_t base;
 
 	authsiz = nfsm_rndup(auth_len);
 	mb = m_gethdr(M_WAIT, MT_DATA);
@@ -687,22 +684,7 @@ nfsm_rpchead(cr, nmflag, procid, auth_ty
 	 */
 	nfsm_build(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
 
-	/*
-	 * derive initial xid from system time
-	 * XXX time is invalid if root not yet mounted
-	 */
-	if (!base && (rootvp)) {
-		microtime(&tv);
-		base = tv.tv_sec << 12;
-		nfs_xid = base;
-	}
-	/*
-	 * Skip zero xid if it should ever happen.
-	 */
-	if (++nfs_xid == 0)
-		nfs_xid++;
-
-	*tl++ = *xidp = txdr_unsigned(nfs_xid);
+	*tl++ = *xidp = nfs_getxid();
 	*tl++ = rpc_call;
 	*tl++ = rpc_vers;
 	if (nmflag & NFSMNT_NQNFS) {
@@ -2785,4 +2767,56 @@ nfsrv_setcred(incred, outcred)
 	for (i = 0; i < incred->cr_ngroups; i++)
 		outcred->cr_groups[i] = incred->cr_groups[i];
 	nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
+}
+
+u_int32_t
+nfs_getxid()
+{
+	static u_int32_t base;
+	static u_int32_t nfs_xid = 0;
+	static struct simplelock nfs_xidlock = SIMPLELOCK_INITIALIZER;
+	u_int32_t newxid;
+
+	simple_lock(&nfs_xidlock);
+	/*
+	 * derive initial xid from system time
+	 * XXX time is invalid if root not yet mounted
+	 */
+	if (__predict_false(!base && (rootvp))) {
+		struct timeval tv;
+
+		microtime(&tv);
+		base = tv.tv_sec << 12;
+		nfs_xid = base;
+	}
+
+	/*
+	 * Skip zero xid if it should ever happen.
+	 */
+	if (__predict_false(++nfs_xid == 0))
+		nfs_xid++;
+	newxid = nfs_xid;
+	simple_unlock(&nfs_xidlock);
+
+	return txdr_unsigned(newxid);
+}
+
+/*
+ * assign a new xid for existing request.
+ * used for NFSERR_JUKEBOX handling.
+ */
+void
+nfs_renewxid(struct nfsreq *req)
+{
+	u_int32_t xid;
+	int off;
+
+	xid = nfs_getxid();
+	if (req->r_nmp->nm_sotype == SOCK_STREAM)
+		off = sizeof(u_int32_t); /* RPC record mark */
+	else
+		off = 0;
+
+	m_copyback(req->r_mreq, off, sizeof(xid), (void *)&xid);
+	req->r_xid = xid;
 }

--NextPart-20030723000619-0312200--