Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/nfs fix a page locking deadlock problem for nfs.



details:   https://anonhg.NetBSD.org/src/rev/8a6d30e076cf
branches:  trunk
changeset: 538466:8a6d30e076cf
user:      yamt <yamt%NetBSD.org@localhost>
date:      Mon Oct 21 12:52:32 2002 +0000

description:
fix a page locking deadlock problem for nfs.

add a flag that specify if the file can be truncated safely or not
to nfsm_loadattr and friends.  when it isn't safe, just mark the nfsnode
as "should be truncated later".

ok'ed by Frank van der Linden and Chuck Silvers.
close kern/18036.

diffstat:

 sys/nfs/nfs_bio.c     |  12 +++++-
 sys/nfs/nfs_nqlease.c |   6 +-
 sys/nfs/nfs_subs.c    |  36 +++++++++++++++---
 sys/nfs/nfs_var.h     |  10 +++-
 sys/nfs/nfs_vfsops.c  |   8 ++--
 sys/nfs/nfs_vnops.c   |  99 +++++++++++++++++++++++++++++---------------------
 sys/nfs/nfsm_subs.h   |  17 ++++----
 sys/nfs/nfsnode.h     |   5 +-
 8 files changed, 124 insertions(+), 69 deletions(-)

diffs (truncated from 626 to 300 lines):

diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_bio.c
--- a/sys/nfs/nfs_bio.c Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_bio.c Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_bio.c,v 1.82 2002/09/01 10:39:38 bouyer Exp $      */
+/*     $NetBSD: nfs_bio.c,v 1.83 2002/10/21 12:52:32 yamt Exp $        */
 
 /*
  * Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.82 2002/09/01 10:39:38 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.83 2002/10/21 12:52:32 yamt Exp $");
 
 #include "opt_nfs.h"
 #include "opt_ddb.h"
@@ -1134,6 +1134,14 @@
        crhold(np->n_rcred);
 
        /*
+        * if we have delayed truncation and it's safe, do it now.
+        */
+       
+       if (ap->a_flags & PGO_SYNCIO) {
+               nfs_delayedtruncate(vp);
+       }
+
+       /*
         * call the genfs code to get the pages.  `pgs' may be NULL
         * when doing read-ahead.
         */
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_nqlease.c
--- a/sys/nfs/nfs_nqlease.c     Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_nqlease.c     Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_nqlease.c,v 1.40 2002/05/12 23:04:35 matt Exp $    */
+/*     $NetBSD: nfs_nqlease.c,v 1.41 2002/10/21 12:52:33 yamt Exp $    */
 
 /*
  * Copyright (c) 1992, 1993
@@ -53,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_nqlease.c,v 1.40 2002/05/12 23:04:35 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_nqlease.c,v 1.41 2002/10/21 12:52:33 yamt Exp $");
 
 #include "fs_nfs.h"
 #include "opt_nfs.h"
@@ -880,7 +880,7 @@
        if (reqtime > time.tv_sec) {
                frev = fxdr_hyper(tl);
                nqnfs_clientlease(nmp, np, rwflag, cachable, reqtime, frev);
-               nfsm_loadattr(vp, (struct vattr *)0);
+               nfsm_loadattr(vp, (struct vattr *)0, 0);
        } else
                error = NQNFS_EXPIRED;
        nfsm_reqdone;
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_subs.c
--- a/sys/nfs/nfs_subs.c        Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_subs.c        Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_subs.c,v 1.104 2002/08/23 05:38:51 enami Exp $     */
+/*     $NetBSD: nfs_subs.c,v 1.105 2002/10/21 12:52:33 yamt Exp $      */
 
 /*
  * Copyright (c) 1989, 1993
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.104 2002/08/23 05:38:51 enami Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.105 2002/10/21 12:52:33 yamt Exp $");
 
 #include "fs_nfs.h"
 #include "opt_nfs.h"
@@ -1527,11 +1527,12 @@
  *    copy the attributes to *vaper
  */
 int
-nfsm_loadattrcache(vpp, mdp, dposp, vaper)
+nfsm_loadattrcache(vpp, mdp, dposp, vaper, flags)
        struct vnode **vpp;
        struct mbuf **mdp;
        caddr_t *dposp;
        struct vattr *vaper;
+       int flags;
 {
        int32_t t1;
        caddr_t cp2;
@@ -1544,14 +1545,15 @@
        error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2);
        if (error)
                return (error);
-       return nfs_loadattrcache(vpp, (struct nfs_fattr *)cp2, vaper);
+       return nfs_loadattrcache(vpp, (struct nfs_fattr *)cp2, vaper, flags);
 }
 
 int
-nfs_loadattrcache(vpp, fp, vaper)
+nfs_loadattrcache(vpp, fp, vaper, flags)
        struct vnode **vpp;
        struct nfs_fattr *fp;
        struct vattr *vaper;
+       int flags;
 {
        struct vnode *vp = *vpp;
        struct vattr *vap;
@@ -1699,7 +1701,17 @@
                } else {
                        np->n_size = vap->va_size;
                        if (vap->va_type == VREG) {
-                               uvm_vnp_setsize(vp, np->n_size);
+                               if ((flags & NAC_NOTRUNC)
+                                   && np->n_size < vp->v_size) {
+                                       /*
+                                        * we can't free pages now because
+                                        * the pages can be owned by ourselves.
+                                        */
+                                       np->n_flag |= NTRUNCDELAYED;
+                               }
+                               else {
+                                       uvm_vnp_setsize(vp, np->n_size);
+                               }
                        }
                }
        }
@@ -1758,6 +1770,18 @@
        return (0);
 }
 
+void
+nfs_delayedtruncate(vp)
+       struct vnode *vp;
+{
+       struct nfsnode *np = VTONFS(vp);
+
+       if (np->n_flag & NTRUNCDELAYED) {
+               np->n_flag &= ~NTRUNCDELAYED;
+               uvm_vnp_setsize(vp, np->n_size);
+       }
+}
+
 /*
  * 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 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_var.h
--- a/sys/nfs/nfs_var.h Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_var.h Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_var.h,v 1.23 2002/03/17 22:22:40 christos Exp $    */
+/*     $NetBSD: nfs_var.h,v 1.24 2002/10/21 12:52:34 yamt Exp $        */
 
 /*-
  * Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -243,10 +243,11 @@
 void nfs_invaldircache __P((struct vnode *, int));
 void nfs_init __P((void));
 int nfsm_loadattrcache __P((struct vnode **, struct mbuf **, caddr_t *,
-                          struct vattr *));
+                          struct vattr *, int flags));
 int nfs_loadattrcache __P((struct vnode **, struct nfs_fattr *,
-                          struct vattr *));
+                          struct vattr *, int flags));
 int nfs_getattrcache __P((struct vnode *, struct vattr *));
+void nfs_delayedtruncate __P((struct vnode *));
 int nfs_namei __P((struct nameidata *, fhandle_t *, int, struct nfssvc_sock *,
                   struct mbuf *, struct mbuf **, caddr_t *, struct vnode **,
                   struct proc *, int, int));
@@ -264,6 +265,9 @@
 int nfs_ispublicfh __P((fhandle_t *));
 int netaddr_match __P((int, union nethostaddr *, struct mbuf *));
 
+/* flags for nfs_loadattrcache and friends */
+#define        NAC_NOTRUNC     1       /* don't truncate file size */
+
 void nfs_clearcommit __P((struct mount *));
 void nfs_merge_commit_ranges __P((struct vnode *));
 int nfs_in_committed_range __P((struct vnode *, off_t, off_t));
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_vfsops.c
--- a/sys/nfs/nfs_vfsops.c      Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_vfsops.c      Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_vfsops.c,v 1.118 2002/10/21 03:58:07 enami Exp $   */
+/*     $NetBSD: nfs_vfsops.c,v 1.119 2002/10/21 12:52:34 yamt Exp $    */
 
 /*
  * Copyright (c) 1989, 1993, 1995
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.118 2002/10/21 03:58:07 enami Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.119 2002/10/21 12:52:34 yamt Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -169,7 +169,7 @@
        nfsm_fhtom(vp, v3);
        nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
        if (v3)
-               nfsm_postop_attr(vp, retattr);
+               nfsm_postop_attr(vp, retattr, 0);
        if (error) {
                if (mrep != NULL)
                        m_free(mrep);
@@ -237,7 +237,7 @@
        nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
        nfsm_fhtom(vp, 1);
        nfsm_request(vp, NFSPROC_FSINFO, p, cred);
-       nfsm_postop_attr(vp, retattr);
+       nfsm_postop_attr(vp, retattr, 0);
        if (!error) {
                nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
                pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
diff -r 6c98ed59d707 -r 8a6d30e076cf sys/nfs/nfs_vnops.c
--- a/sys/nfs/nfs_vnops.c       Mon Oct 21 11:57:25 2002 +0000
+++ b/sys/nfs/nfs_vnops.c       Mon Oct 21 12:52:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_vnops.c,v 1.152 2002/10/18 19:08:15 thorpej Exp $  */
+/*     $NetBSD: nfs_vnops.c,v 1.153 2002/10/21 12:52:35 yamt Exp $     */
 
 /*
  * Copyright (c) 1989, 1993
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.152 2002/10/18 19:08:15 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.153 2002/10/21 12:52:35 yamt Exp $");
 
 #include "opt_nfs.h"
 #include "opt_uvmhist.h"
@@ -364,7 +364,7 @@
                }
                *tl = txdr_unsigned(mode);
                nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
-               nfsm_postop_attr(vp, attrflag);
+               nfsm_postop_attr(vp, attrflag, 0);
                if (!error) {
                        nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
                        rmode = fxdr_unsigned(u_int32_t, *tl);
@@ -628,7 +628,7 @@
        nfsm_fhtom(vp, v3);
        nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
        if (!error) {
-               nfsm_loadattr(vp, ap->a_vap);
+               nfsm_loadattr(vp, ap->a_vap, 0);
                if (vp->v_type == VDIR &&
                    ap->a_vap->va_blocksize < NFS_DIRFRAGSIZ)
                        ap->a_vap->va_blocksize = NFS_DIRFRAGSIZ;
@@ -769,9 +769,9 @@
        }
        nfsm_request(vp, NFSPROC_SETATTR, procp, cred);
        if (v3) {
-               nfsm_wcc_data(vp, wccflag);
+               nfsm_wcc_data(vp, wccflag, 0);
        } else
-               nfsm_loadattr(vp, (struct vattr *)0);
+               nfsm_loadattr(vp, (struct vattr *)0, 0);
        nfsm_reqdone;
        return (error);
 }
@@ -910,7 +910,7 @@
        nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
        nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
        if (error) {
-               nfsm_postop_attr(dvp, attrflag);
+               nfsm_postop_attr(dvp, attrflag, 0);
                m_freem(mrep);
                goto nfsmout;
        }
@@ -931,10 +931,10 @@
                }
                newvp = NFSTOV(np);
                if (v3) {
-                       nfsm_postop_attr(newvp, attrflag);
-                       nfsm_postop_attr(dvp, attrflag);
+                       nfsm_postop_attr(newvp, attrflag, 0);
+                       nfsm_postop_attr(dvp, attrflag, 0);
                } else
-                       nfsm_loadattr(newvp, (struct vattr *)0);
+                       nfsm_loadattr(newvp, (struct vattr *)0, 0);
                *vpp = newvp;
                m_freem(mrep);
                cnp->cn_flags |= SAVENAME;
@@ -958,10 +958,10 @@
                VREF(dvp);
                newvp = dvp;
                if (v3) {
-                       nfsm_postop_attr(newvp, attrflag);
-                       nfsm_postop_attr(dvp, attrflag);
+                       nfsm_postop_attr(newvp, attrflag, 0);
+                       nfsm_postop_attr(dvp, attrflag, 0);
                } else
-                       nfsm_loadattr(newvp, (struct vattr *)0);
+                       nfsm_loadattr(newvp, (struct vattr *)0, 0);
        } else if (flags & ISDOTDOT) {



Home | Main Index | Thread Index | Old Index