summaryrefslogtreecommitdiffstats
path: root/sys/nfs
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/nfs
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/nfs')
-rw-r--r--sys/nfs/nfs_vnops.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
index 6d2ec66..3d9f797 100644
--- a/sys/nfs/nfs_vnops.c
+++ b/sys/nfs/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