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