Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/nfs implement inaccurate mtime/ctime detection.
details: https://anonhg.NetBSD.org/src/rev/e3afe4f05e65
branches: trunk
changeset: 573099:e3afe4f05e65
user: yamt <yamt%NetBSD.org@localhost>
date: Wed Jan 19 16:22:19 2005 +0000
description:
implement inaccurate mtime/ctime detection.
namely, if mtime or ctime are same between pre_op_attr and post_op_attr
when we expected them to be changed, don't trust the server.
diffstat:
sys/nfs/nfs_subs.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++-
sys/nfs/nfs_var.h | 4 +-
sys/nfs/nfs_vnops.c | 28 ++++++++--------
sys/nfs/nfsm_subs.h | 35 +++++++++++++--------
sys/nfs/nfsmount.h | 4 +-
5 files changed, 124 insertions(+), 32 deletions(-)
diffs (truncated from 336 to 300 lines):
diff -r 119fa699606e -r e3afe4f05e65 sys/nfs/nfs_subs.c
--- a/sys/nfs/nfs_subs.c Wed Jan 19 16:13:57 2005 +0000
+++ b/sys/nfs/nfs_subs.c Wed Jan 19 16:22:19 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_subs.c,v 1.140 2005/01/09 01:32:32 yamt Exp $ */
+/* $NetBSD: nfs_subs.c,v 1.141 2005/01/19 16:22:19 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.140 2005/01/09 01:32:32 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.141 2005/01/19 16:22:19 yamt Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@@ -1903,6 +1903,87 @@
}
}
+#define NFS_WCCKLUDGE_TIMEOUT (24 * 60 * 60) /* 1 day */
+#define NFS_WCCKLUDGE(nmp, now) \
+ (((nmp)->nm_iflag & NFSMNT_WCCKLUDGE) && \
+ ((now) - (nmp)->nm_wcckludgetime - NFS_WCCKLUDGE_TIMEOUT) < 0)
+
+/*
+ * nfs_check_wccdata: check inaccurate wcc_data
+ *
+ * => return non-zero if we shouldn't trust the wcc_data.
+ * => NFS_WCCKLUDGE_TIMEOUT is for the case that the server is "fixed".
+ */
+
+int
+nfs_check_wccdata(struct nfsnode *np, const struct timespec *ctime,
+ struct timespec *mtime, boolean_t docheck)
+{
+ int error = 0;
+
+#if !defined(NFS_V2_ONLY)
+
+ if (docheck) {
+ struct vnode *vp = NFSTOV(np);
+ struct nfsmount *nmp;
+ long now = mono_time.tv_sec;
+#if defined(DEBUG)
+ const char *reason = NULL; /* XXX: gcc */
+#endif
+
+ if (timespeccmp(&np->n_vattr->va_mtime, mtime, <=)) {
+#if defined(DEBUG)
+ reason = "mtime";
+#endif
+ error = EINVAL;
+ }
+
+ if (vp->v_type == VDIR &&
+ timespeccmp(&np->n_vattr->va_ctime, ctime, <=)) {
+#if defined(DEBUG)
+ reason = "ctime";
+#endif
+ error = EINVAL;
+ }
+
+ /*
+ *
+ */
+
+ nmp = VFSTONFS(vp->v_mount);
+ if (error) {
+ simple_lock(&nmp->nm_slock);
+#if defined(DEBUG)
+ if (!NFS_WCCKLUDGE(nmp, now)) {
+ printf("%s: inaccurate wcc data (%s) detected,"
+ " disabling wcc\n",
+ vp->v_mount->mnt_stat.f_mntfromname,
+ reason);
+ }
+#endif
+ nmp->nm_iflag |= NFSMNT_WCCKLUDGE;
+ nmp->nm_wcckludgetime = now;
+ simple_unlock(&nmp->nm_slock);
+ } else if (NFS_WCCKLUDGE(nmp, now)) {
+ error = EPERM; /* XXX */
+ } else if (nmp->nm_iflag & NFSMNT_WCCKLUDGE) {
+ simple_lock(&nmp->nm_slock);
+ if (nmp->nm_iflag & NFSMNT_WCCKLUDGE) {
+#if defined(DEBUG)
+ printf("%s: re-enabling wcc\n",
+ vp->v_mount->mnt_stat.f_mntfromname);
+#endif
+ nmp->nm_iflag &= ~NFSMNT_WCCKLUDGE;
+ }
+ simple_unlock(&nmp->nm_slock);
+ }
+ }
+
+#endif /* !defined(NFS_V2_ONLY) */
+
+ return error;
+}
+
/*
* Heuristic to see if the server XDR encodes directory cookies or not.
* it is not supposed to, but a lot of servers may do this. Also, since
diff -r 119fa699606e -r e3afe4f05e65 sys/nfs/nfs_var.h
--- a/sys/nfs/nfs_var.h Wed Jan 19 16:13:57 2005 +0000
+++ b/sys/nfs/nfs_var.h Wed Jan 19 16:22:19 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_var.h,v 1.47 2004/12/14 09:13:13 yamt Exp $ */
+/* $NetBSD: nfs_var.h,v 1.48 2005/01/19 16:22:19 yamt Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -272,6 +272,8 @@
struct vattr *, int flags));
int nfs_getattrcache __P((struct vnode *, struct vattr *));
void nfs_delayedtruncate __P((struct vnode *));
+int nfs_check_wccdata __P((struct nfsnode *, const struct timespec *,
+ struct timespec *, boolean_t));
int nfs_namei __P((struct nameidata *, fhandle_t *, uint32_t,
struct nfssvc_sock *, struct mbuf *, struct mbuf **,
caddr_t *, struct vnode **, struct proc *, int, int));
diff -r 119fa699606e -r e3afe4f05e65 sys/nfs/nfs_vnops.c
--- a/sys/nfs/nfs_vnops.c Wed Jan 19 16:13:57 2005 +0000
+++ b/sys/nfs/nfs_vnops.c Wed Jan 19 16:22:19 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_vnops.c,v 1.215 2005/01/08 03:12:30 yamt Exp $ */
+/* $NetBSD: nfs_vnops.c,v 1.216 2005/01/19 16:22:19 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.215 2005/01/08 03:12:30 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.216 2005/01/19 16:22:19 yamt Exp $");
#include "opt_inet.h"
#include "opt_nfs.h"
@@ -777,7 +777,7 @@
nfsm_request(np, NFSPROC_SETATTR, procp, cred);
#ifndef NFS_V2_ONLY
if (v3) {
- nfsm_wcc_data(vp, wccflag, 0);
+ nfsm_wcc_data(vp, wccflag, 0, FALSE);
} else
#endif
nfsm_loadattr(vp, (struct vattr *)0, 0);
@@ -1452,7 +1452,7 @@
#ifndef NFS_V2_ONLY
if (v3) {
wccflag = NFSV3_WCCCHK;
- nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC);
+ nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, !error);
if (!error) {
nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
+ NFSX_V3WRITEVERF);
@@ -1634,7 +1634,7 @@
}
#ifndef NFS_V2_ONLY
if (v3)
- nfsm_wcc_data(dvp, wccflag, 0);
+ nfsm_wcc_data(dvp, wccflag, 0, !error);
#endif
nfsm_reqdone;
if (error) {
@@ -1772,7 +1772,7 @@
}
#ifndef NFS_V2_ONLY
if (v3)
- nfsm_wcc_data(dvp, wccflag, 0);
+ nfsm_wcc_data(dvp, wccflag, 0, !error);
#endif
nfsm_reqdone;
if (error) {
@@ -1942,7 +1942,7 @@
nfsm_request1(dnp, NFSPROC_REMOVE, proc, cred, &rexmit);
#ifndef NFS_V2_ONLY
if (v3)
- nfsm_wcc_data(dvp, wccflag, 0);
+ nfsm_wcc_data(dvp, wccflag, 0, !error);
#endif
nfsm_reqdone;
VTONFS(dvp)->n_flag |= NMODIFIED;
@@ -2085,8 +2085,8 @@
nfsm_request1(fdnp, NFSPROC_RENAME, proc, cred, &rexmit);
#ifndef NFS_V2_ONLY
if (v3) {
- nfsm_wcc_data(fdvp, fwccflag, 0);
- nfsm_wcc_data(tdvp, twccflag, 0);
+ nfsm_wcc_data(fdvp, fwccflag, 0, !error);
+ nfsm_wcc_data(tdvp, twccflag, 0, !error);
}
#endif
nfsm_reqdone;
@@ -2167,7 +2167,7 @@
#ifndef NFS_V2_ONLY
if (v3) {
nfsm_postop_attr(vp, attrflag, 0);
- nfsm_wcc_data(dvp, wccflag, 0);
+ nfsm_wcc_data(dvp, wccflag, 0, !error);
}
#endif
nfsm_reqdone;
@@ -2250,7 +2250,7 @@
if (v3) {
if (!error)
nfsm_mtofh(dvp, newvp, v3, gotvp);
- nfsm_wcc_data(dvp, wccflag, 0);
+ nfsm_wcc_data(dvp, wccflag, 0, !error);
}
#endif
nfsm_reqdone;
@@ -2338,7 +2338,7 @@
if (!error)
nfsm_mtofh(dvp, newvp, v3, gotvp);
if (v3)
- nfsm_wcc_data(dvp, wccflag, 0);
+ nfsm_wcc_data(dvp, wccflag, 0, !error);
nfsm_reqdone;
VTONFS(dvp)->n_flag |= NMODIFIED;
if (!wccflag)
@@ -2422,7 +2422,7 @@
nfsm_request1(dnp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred, &rexmit);
#ifndef NFS_V2_ONLY
if (v3)
- nfsm_wcc_data(dvp, wccflag, 0);
+ nfsm_wcc_data(dvp, wccflag, 0, !error);
#endif
nfsm_reqdone;
PNBUF_PUT(cnp->cn_pnbuf);
@@ -3188,7 +3188,7 @@
tl += 2;
*tl = txdr_unsigned(cnt);
nfsm_request(np, NFSPROC_COMMIT, procp, np->n_wcred);
- nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC);
+ nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, FALSE);
if (!error) {
nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
simple_lock(&nmp->nm_slock);
diff -r 119fa699606e -r e3afe4f05e65 sys/nfs/nfsm_subs.h
--- a/sys/nfs/nfsm_subs.h Wed Jan 19 16:13:57 2005 +0000
+++ b/sys/nfs/nfsm_subs.h Wed Jan 19 16:22:19 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nfsm_subs.h,v 1.38 2004/09/29 11:24:28 yamt Exp $ */
+/* $NetBSD: nfsm_subs.h,v 1.39 2005/01/19 16:22:19 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -247,38 +247,45 @@
* NFSV3_WCCCHK return true if pre_op_attr's mtime is the same
* as our n_mtime. (ie. our cache isn't stale.)
* flags: (IN) flags for nfsm_loadattrcache
+ * docheck: (IN) TRUE if timestamp change is expected
*/
/* Used as (f) for nfsm_wcc_data() */
#define NFSV3_WCCRATTR 0
#define NFSV3_WCCCHK 1
-#define nfsm_wcc_data(v, f, flags) \
+#define nfsm_wcc_data(v, f, flags, docheck) \
{ int ttattrf, ttretf = 0, renewctime = 0, renewnctime = 0; \
+ struct timespec ctime, mtime; \
+ struct nfsnode *np = VTONFS(v); \
+ boolean_t haspreopattr = FALSE; \
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
- struct timespec ctime; \
+ haspreopattr = TRUE; \
nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); \
+ fxdr_nfsv3time(tl + 2, &mtime); \
fxdr_nfsv3time(tl + 4, &ctime); \
- if (VTONFS(v)->n_ctime == ctime.tv_sec) \
+ if (np->n_ctime == ctime.tv_sec) \
renewctime = 1; \
if ((v)->v_type == VDIR) { \
- if (timespeccmp(&VTONFS(v)->n_nctime, \
- &ctime, ==)) \
+ if (timespeccmp(&np->n_nctime, &ctime, ==)) \
renewnctime = 1; \
} \
if (f) { \
- struct timespec mtime; \
- fxdr_nfsv3time(tl + 2, &mtime); \
- ttretf = timespeccmp(&VTONFS(v)->n_mtime, \
- &mtime, ==); \
+ ttretf = timespeccmp(&np->n_mtime, &mtime, ==);\
} \
} \
nfsm_postop_attr((v), ttattrf, (flags)); \
- if (renewctime && ttattrf) \
- VTONFS(v)->n_ctime = VTONFS(v)->n_vattr->va_ctime.tv_sec; \
- if (renewnctime && ttattrf) \
- VTONFS(v)->n_nctime = VTONFS(v)->n_vattr->va_ctime; \
+ np = VTONFS(v); \
+ if (ttattrf) { \
Home |
Main Index |
Thread Index |
Old Index