diff options
author | jeff <jeff@FreeBSD.org> | 2005-03-28 09:29:58 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2005-03-28 09:29:58 +0000 |
commit | 5f8bc80203c1f09224b3147185dc75b9836efa82 (patch) | |
tree | 55f8f7863119a8b25b0a65b6af969ad7dfbfb683 /sys/nfsclient/nfs_vnops.c | |
parent | eb142209f00eb33da0b100cb34139de01a18a9a8 (diff) | |
download | FreeBSD-src-5f8bc80203c1f09224b3147185dc75b9836efa82.zip FreeBSD-src-5f8bc80203c1f09224b3147185dc75b9836efa82.tar.gz |
- We no longer have to bother with PDIRUNLOCK, lookup() handles it for us.
- Network filesystems are written with a special idiom that checks the
cache first, and may even unlock dvp before discovering that a network
round-trip is required to resolve the name. I believe dvp is prevented
from being recycled even in the forced unmount case by the shared lock
on the mount point. If not, this code should grow checks for VI_DOOMED
after it relocks dvp or it will access NULL v_data fields.
Sponsored by: Isilon Systems, Inc.
Diffstat (limited to 'sys/nfsclient/nfs_vnops.c')
-rw-r--r-- | sys/nfsclient/nfs_vnops.c | 55 |
1 files changed, 10 insertions, 45 deletions
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index d3059a26..2dfb345 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -776,18 +776,16 @@ nfs_lookup(struct vop_lookup_args *ap) long len; nfsfh_t *fhp; struct nfsnode *np; - int lockparent, wantparent, error = 0, attrflag, fhsize; + int wantparent, error = 0, attrflag, fhsize; int v3 = NFS_ISV3(dvp); struct thread *td = cnp->cn_thread; *vpp = NULLVP; - cnp->cn_flags &= ~PDIRUNLOCK; if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) return (EROFS); if (dvp->v_type != VDIR) return (ENOTDIR); - lockparent = flags & LOCKPARENT; wantparent = flags & (LOCKPARENT|WANTPARENT); nmp = VFSTONFS(dvp->v_mount); np = VTONFS(dvp); @@ -810,20 +808,11 @@ nfs_lookup(struct vop_lookup_args *ap) error = 0; } else if (flags & ISDOTDOT) { VOP_UNLOCK(dvp, 0, td); - cnp->cn_flags |= PDIRUNLOCK; error = vget(newvp, LK_EXCLUSIVE, td); - if (!error && lockparent && (flags & ISLASTCN)) { - error = vn_lock(dvp, LK_EXCLUSIVE, td); - if (error == 0) - cnp->cn_flags &= ~PDIRUNLOCK; - } - } else { + if (error) + vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY, td); + } else error = vget(newvp, LK_EXCLUSIVE, td); - if (!lockparent || error || !(flags & ISLASTCN)) { - VOP_UNLOCK(dvp, 0, td); - cnp->cn_flags |= PDIRUNLOCK; - } - } if (!error) { if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td) && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { @@ -835,18 +824,15 @@ nfs_lookup(struct vop_lookup_args *ap) return (0); } cache_purge(newvp); - vput(newvp); - if (lockparent && dvp != newvp && (flags & ISLASTCN)) - VOP_UNLOCK(dvp, 0, td); + if (dvp != newvp) + vput(newvp); + else + vrele(newvp); + if (flags & ISDOTDOT) + vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY, td); } vdrop(newvp); - error = vn_lock(dvp, LK_EXCLUSIVE, td); *vpp = NULLVP; - if (error) { - cnp->cn_flags |= PDIRUNLOCK; - return (error); - } - cnp->cn_flags &= ~PDIRUNLOCK; } error = 0; newvp = NULLVP; @@ -889,10 +875,6 @@ nfs_lookup(struct vop_lookup_args *ap) *vpp = newvp; m_freem(mrep); cnp->cn_flags |= SAVENAME; - if (!lockparent) { - VOP_UNLOCK(dvp, 0, td); - cnp->cn_flags |= PDIRUNLOCK; - } return (0); } @@ -904,15 +886,6 @@ nfs_lookup(struct vop_lookup_args *ap) return (error); } newvp = NFSTOV(np); - if (lockparent && (flags & ISLASTCN)) { - error = vn_lock(dvp, LK_EXCLUSIVE, td); - if (error) { - cnp->cn_flags |= PDIRUNLOCK; - vput(newvp); - return (error); - } - } else - cnp->cn_flags |= PDIRUNLOCK; } else if (NFS_CMPFH(np, fhp, fhsize)) { VREF(dvp); newvp = dvp; @@ -922,10 +895,6 @@ nfs_lookup(struct vop_lookup_args *ap) m_freem(mrep); return (error); } - if (!lockparent || !(flags & ISLASTCN)) { - cnp->cn_flags |= PDIRUNLOCK; - VOP_UNLOCK(dvp, 0, td); - } newvp = NFSTOV(np); } if (v3) { @@ -950,10 +919,6 @@ nfsmout: } if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && (flags & ISLASTCN) && error == ENOENT) { - if (!lockparent) { - VOP_UNLOCK(dvp, 0, td); - cnp->cn_flags |= PDIRUNLOCK; - } if (dvp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else |