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--