summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient/nfs_vnops.c
diff options
context:
space:
mode:
authorbp <bp@FreeBSD.org>2000-10-15 08:06:32 +0000
committerbp <bp@FreeBSD.org>2000-10-15 08:06:32 +0000
commit9c029c0ce5709535e3b6879728a23184ca809eab (patch)
treea974bd4de9f5c187730b1003219422f8b58caea2 /sys/nfsclient/nfs_vnops.c
parent86d96862d160882bab7ab6f56af018d8796870b2 (diff)
downloadFreeBSD-src-9c029c0ce5709535e3b6879728a23184ca809eab.zip
FreeBSD-src-9c029c0ce5709535e3b6879728a23184ca809eab.tar.gz
Make nfs PDIRUNLOCK aware. Now it is possible to use nullfs mounts on top
of nfs mounts, but there can be side effects because nfs uses shared locks for vnodes.
Diffstat (limited to 'sys/nfsclient/nfs_vnops.c')
-rw-r--r--sys/nfsclient/nfs_vnops.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 6d2ec66..3d9f797 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -825,6 +825,7 @@ nfs_lookup(ap)
struct proc *p = cnp->cn_proc;
*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);
@@ -854,13 +855,19 @@ nfs_lookup(ap)
error = 0;
} else if (flags & ISDOTDOT) {
VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
error = vget(newvp, LK_EXCLUSIVE, p);
- if (!error && lockparent && (flags & ISLASTCN))
+ if (!error && lockparent && (flags & ISLASTCN)) {
error = vn_lock(dvp, LK_EXCLUSIVE, p);
+ if (error == 0)
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ }
} else {
error = vget(newvp, LK_EXCLUSIVE, p);
- if (!lockparent || error || !(flags & ISLASTCN))
+ if (!lockparent || error || !(flags & ISLASTCN)) {
VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
}
if (!error) {
if (vpid == newvp->v_id) {
@@ -880,8 +887,11 @@ nfs_lookup(ap)
}
error = vn_lock(dvp, LK_EXCLUSIVE, p);
*vpp = NULLVP;
- if (error)
+ if (error) {
+ cnp->cn_flags |= PDIRUNLOCK;
return (error);
+ }
+ cnp->cn_flags &= ~PDIRUNLOCK;
}
error = 0;
newvp = NULLVP;
@@ -922,8 +932,10 @@ nfs_lookup(ap)
*vpp = newvp;
m_freem(mrep);
cnp->cn_flags |= SAVENAME;
- if (!lockparent)
+ if (!lockparent) {
VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
return (0);
}
@@ -935,11 +947,15 @@ nfs_lookup(ap)
return (error);
}
newvp = NFSTOV(np);
- if (lockparent && (flags & ISLASTCN) &&
- (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
- vput(newvp);
- return (error);
- }
+ if (lockparent && (flags & ISLASTCN)) {
+ error = vn_lock(dvp, LK_EXCLUSIVE, p);
+ 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;
@@ -949,8 +965,10 @@ nfs_lookup(ap)
m_freem(mrep);
return (error);
}
- if (!lockparent || !(flags & ISLASTCN))
+ if (!lockparent || !(flags & ISLASTCN)) {
+ cnp->cn_flags |= PDIRUNLOCK;
VOP_UNLOCK(dvp, 0, p);
+ }
newvp = NFSTOV(np);
}
if (v3) {
@@ -974,8 +992,10 @@ nfs_lookup(ap)
}
if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
(flags & ISLASTCN) && error == ENOENT) {
- if (!lockparent)
+ if (!lockparent) {
VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
if (dvp->v_mount->mnt_flag & MNT_RDONLY)
error = EROFS;
else
OpenPOWER on IntegriCloud