Source-Changes-HG archive

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

[src/trunk]: src/sys/nfs Do actual vnode locking for NFS.



details:   https://anonhg.NetBSD.org/src/rev/daa9f39e7d5d
branches:  trunk
changeset: 503445:daa9f39e7d5d
user:      fvdl <fvdl%NetBSD.org@localhost>
date:      Tue Feb 06 11:40:02 2001 +0000

description:
Do actual vnode locking for NFS.

diffstat:

 sys/nfs/nfs_node.c    |    8 +-
 sys/nfs/nfs_nqlease.c |    8 +-
 sys/nfs/nfs_vfsops.c  |   28 ++++---
 sys/nfs/nfs_vnops.c   |  188 +++++++++++++++++++++++++++++++++++++------------
 sys/nfs/nfsnode.h     |    8 +-
 5 files changed, 171 insertions(+), 69 deletions(-)

diffs (truncated from 592 to 300 lines):

diff -r 63345a474613 -r daa9f39e7d5d sys/nfs/nfs_node.c
--- a/sys/nfs/nfs_node.c        Tue Feb 06 10:58:55 2001 +0000
+++ b/sys/nfs/nfs_node.c        Tue Feb 06 11:40:02 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_node.c,v 1.38 2000/11/27 08:39:48 chs Exp $        */
+/*     $NetBSD: nfs_node.c,v 1.39 2001/02/06 11:40:02 fvdl Exp $       */
 
 /*
  * Copyright (c) 1989, 1993
@@ -156,7 +156,6 @@
                lockmgr(&nfs_hashlock, LK_RELEASE, 0);
                return (error);
        }
-       nvp->v_vnlock = 0;      /* XXX At least untill we do locking */
        vp = nvp;
        np = pool_get(&nfs_node_pool, PR_WAITOK);
        memset(np, 0, sizeof *np);
@@ -177,6 +176,8 @@
        np->n_accstamp = -1;
        np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK);
 
+       lockmgr(&vp->v_lock, LK_EXCLUSIVE, (struct simplelock *)0);
+
        /*
         * XXXUBC doing this while holding the nfs_hashlock is bad,
         * but there's no alternative at the moment.
@@ -235,9 +236,10 @@
                /*
                 * Remove the silly file that was rename'd earlier
                 */
+               vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_RETRY);
                nfs_removeit(sp);
                crfree(sp->s_cred);
-               vrele(sp->s_dvp);
+               vput(sp->s_dvp);
                FREE(sp, M_NFSREQ);
        }
        np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
diff -r 63345a474613 -r daa9f39e7d5d sys/nfs/nfs_nqlease.c
--- a/sys/nfs/nfs_nqlease.c     Tue Feb 06 10:58:55 2001 +0000
+++ b/sys/nfs/nfs_nqlease.c     Tue Feb 06 11:40:02 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_nqlease.c,v 1.35 2000/11/24 23:30:02 chs Exp $     */
+/*     $NetBSD: nfs_nqlease.c,v 1.36 2001/02/06 11:40:02 fvdl Exp $    */
 
 /*
  * Copyright (c) 1992, 1993
@@ -981,7 +981,7 @@
                        CIRCLEQ_INSERT_HEAD(&nmp->nm_timerhead, np, n_timer);
                }
        }
-       vrele(vp);
+       vput(vp);
        nfsm_srvdone;
 }
 #endif /* NFS && !NFS_V2_ONLY */
@@ -1101,7 +1101,7 @@
                                        }
                                }
                              }
-                             vrele(vp);
+                             vput(vp);
                              nmp->nm_inprog = NULLVP;
                            }
                        } else if ((np->n_expiry - NQ_RENEWAL) < time.tv_sec) {
@@ -1112,7 +1112,7 @@
                                 if (vpid == vp->v_id &&
                                     nqnfs_getlease(vp, ND_WRITE, cred, p)==0)
                                        np->n_brev = np->n_lrev;
-                                vrele(vp);
+                                vput(vp);
                                 nmp->nm_inprog = NULLVP;
                            }
                        } else
diff -r 63345a474613 -r daa9f39e7d5d sys/nfs/nfs_vfsops.c
--- a/sys/nfs/nfs_vfsops.c      Tue Feb 06 10:58:55 2001 +0000
+++ b/sys/nfs/nfs_vfsops.c      Tue Feb 06 11:40:02 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_vfsops.c,v 1.99 2001/01/22 12:17:41 jdolecek Exp $ */
+/*     $NetBSD: nfs_vfsops.c,v 1.100 2001/02/06 11:40:02 fvdl Exp $    */
 
 /*
  * Copyright (c) 1989, 1993, 1995
@@ -207,7 +207,7 @@
        }
        strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN);
        nfsm_reqdone;
-       vrele(vp);
+       vput(vp);
        crfree(cred);
        return (error);
 }
@@ -718,14 +718,6 @@
         * point.
         */
        mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
-       /*
-        * A reference count is needed on the nfsnode representing the
-        * remote root.  If this object is not persistent, then backward
-        * traversals of the mount point (i.e. "..") will not work if
-        * the nfsnode gets flushed out of the cache. Ufs does not have
-        * this problem, because one can identify root inodes by their
-        * number == ROOTINO (2).
-        */
        error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
        if (error)
                goto bad;
@@ -740,6 +732,17 @@
                crfree(cr);
        }
 
+       /*
+        * A reference count is needed on the nfsnode representing the
+        * remote root.  If this object is not persistent, then backward
+        * traversals of the mount point (i.e. "..") will not work if
+        * the nfsnode gets flushed out of the cache. Ufs does not have
+        * this problem, because one can identify root inodes by their
+        * number == ROOTINO (2). So, just unlock, but no rele.
+        */
+
+       VOP_UNLOCK(*vpp, 0);
+
        return (0);
 bad:
        nfs_disconnect(nmp);
@@ -809,10 +812,11 @@
        nmp->nm_iflag |= NFSMNT_DISMNT;
 
        /*
-        * There are two reference counts to get rid of here.
+        * There are two reference counts to get rid of here
+        * (see comment in mountnfs()).
         */
        vrele(vp);
-       vrele(vp);
+       vput(vp);
        vgone(vp);
        nfs_disconnect(nmp);
        m_freem(nmp->nm_nam);
diff -r 63345a474613 -r daa9f39e7d5d sys/nfs/nfs_vnops.c
--- a/sys/nfs/nfs_vnops.c       Tue Feb 06 10:58:55 2001 +0000
+++ b/sys/nfs/nfs_vnops.c       Tue Feb 06 11:40:02 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_vnops.c,v 1.127 2001/01/22 12:17:42 jdolecek Exp $ */
+/*     $NetBSD: nfs_vnops.c,v 1.128 2001/02/06 11:40:02 fvdl Exp $     */
 
 /*
  * Copyright (c) 1989, 1993
@@ -771,6 +771,12 @@
  * nfs lookup call, one step at a time...
  * First look in cache
  * If not found, unlock the directory nfsnode and do the rpc
+ *
+ * This code is full of lock/unlock statements and checks, because
+ * we continue after cache_lookup has finished (we need to check
+ * with the attr cache and do an rpc if it has timed out). This means
+ * that the locking effects of cache_lookup have to be taken into
+ * account.
  */
 int
 nfs_lookup(v)
@@ -798,10 +804,12 @@
        struct nfsnode *np;
        int lockparent, wantparent, error = 0, attrflag, fhsize;
        const int v3 = NFS_ISV3(dvp);
+
        cnp->cn_flags &= ~PDIRUNLOCK;
        flags = cnp->cn_flags;
 
        *vpp = NULLVP;
+       newvp = NULLVP;
        if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
            (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
                return (EROFS);
@@ -828,20 +836,29 @@
 
                if (error && error != ENOENT) {
                        *vpp = NULLVP;
-                       return (error);
+                       return error;
+               }
+
+               if (cnp->cn_flags & PDIRUNLOCK) {
+                       error = vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+                       if (error) {
+                               *vpp = NULLVP;
+                               return error;
+                       }
+                       cnp->cn_flags &= ~PDIRUNLOCK;
                }
 
                err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
                if (err2) {
                        *vpp = NULLVP;
-                       return (err2);
+                       return err2;
                }
 
                if (error == ENOENT) {
                        if (!VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
                            cnp->cn_proc) && vattr.va_mtime.tv_sec ==
                            VTONFS(dvp)->n_nctime)
-                               return (ENOENT);
+                               return ENOENT;
                        cache_purge(dvp);
                        np->n_nctime = 0;
                        goto dorpc;
@@ -857,15 +874,16 @@
                        nfsstats.lookupcache_hits++;
                        if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
                                cnp->cn_flags |= SAVENAME;
+                       if ((!lockparent || !(flags & ISLASTCN)) &&     
+                            newvp != dvp)
+                               VOP_UNLOCK(dvp, 0);
                        return (0);
                }
-               /* XXX cache_lookup() returns the vnode locked; if nfs
-                * would have real vnode locking, we should call VOP_UNLOCK()
-                * here; as it has no real locking, don't bother to do
-                * anything */
-               /* VOP_UNLOCK(newvp, 0); */
                cache_purge(newvp);
-               vrele(newvp);
+               if (newvp != dvp)
+                       vput(newvp);
+               else
+                       vrele(newvp);
                *vpp = NULLVP;
        }
 dorpc:
@@ -897,7 +915,7 @@
                error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
                if (error) {
                        m_freem(mrep);
-                       return (error);
+                       return error;
                }
                newvp = NFSTOV(np);
                if (v3) {
@@ -908,27 +926,80 @@
                *vpp = newvp;
                m_freem(mrep);
                cnp->cn_flags |= SAVENAME;
-               if (!lockparent || !(flags & ISLASTCN))
+               if (!lockparent) {
+                       VOP_UNLOCK(dvp, 0);
                        cnp->cn_flags |= PDIRUNLOCK;
+               }
                return (0);
        }
 
+       /*
+        * The postop attr handling is duplicated for each if case,
+        * because it should be done while dvp is locked (unlocking
+        * dvp is different for each case).
+        */
+
        if (NFS_CMPFH(np, fhp, fhsize)) {
+               /*
+                * "." lookup
+                */
                VREF(dvp);
                newvp = dvp;
+               if (v3) {
+                       nfsm_postop_attr(newvp, attrflag);
+                       nfsm_postop_attr(dvp, attrflag);
+               } else
+                       nfsm_loadattr(newvp, (struct vattr *)0);
+       } else if (flags & ISDOTDOT) {
+               /*
+                * ".." lookup
+                */
+               VOP_UNLOCK(dvp, 0);
+               cnp->cn_flags |= PDIRUNLOCK;
+
+               error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
+               if (error) {
+                       if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY) == 0)
+                               cnp->cn_flags &= ~PDIRUNLOCK;
+                       m_freem(mrep);
+                       return error;
+               }
+               newvp = NFSTOV(np);
+
+               if (v3) {
+                       nfsm_postop_attr(newvp, attrflag);
+                       nfsm_postop_attr(dvp, attrflag);
+               } else
+                       nfsm_loadattr(newvp, (struct vattr *)0);
+
+               if (lockparent && (flags & ISLASTCN)) {
+                       if ((error = vn_lock(dvp, LK_EXCLUSIVE))) {
+                               m_freem(mrep);
+                               vput(newvp);
+                               return error;
+                       }
+                       cnp->cn_flags &= ~PDIRUNLOCK;
+               }
        } else {
+               /*



Home | Main Index | Thread Index | Old Index