diff options
author | bp <bp@FreeBSD.org> | 2000-09-17 07:26:42 +0000 |
---|---|---|
committer | bp <bp@FreeBSD.org> | 2000-09-17 07:26:42 +0000 |
commit | 02544af7d4181c17b4280094d740b15516c89895 (patch) | |
tree | 6acabed362022c7dc8884295f86728d8a26966b5 /sys/ufs | |
parent | e785331769023a37dd8b665cd89d2937f9b417f6 (diff) | |
download | FreeBSD-src-02544af7d4181c17b4280094d740b15516c89895.zip FreeBSD-src-02544af7d4181c17b4280094d740b15516c89895.tar.gz |
Add new flag PDIRUNLOCK to the component.cn_flags which should be set by
filesystem lookup() routine if it unlocks parent directory. This flag should
be carefully tracked by filesystems if they want to work properly with nullfs
and other stacked filesystems.
VFS takes advantage of this flag to perform symantically correct usage
of vrele() instead of vput() if parent directory already unlocked.
If filesystem fails to track this flag then previous codepath in VFS left
unchanged.
Convert UFS code to set PDIRUNLOCK flag if necessary. Other filesystmes will
be changed after some period of testing.
Reviewed in general by: mckusick, dillon, adrian
Obtained from: NetBSD
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ufs/ufs_lookup.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index ee28d48..cddd025 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -154,6 +154,7 @@ ufs_lookup(ap) bp = NULL; slotoffset = -1; + cnp->cn_flags &= ~PDIRUNLOCK; /* * XXX there was a soft-update diff about this I couldn't merge. * I think this was the equiv. @@ -395,8 +396,10 @@ notfound: * information cannot be used. */ cnp->cn_flags |= SAVENAME; - if (!lockparent) + if (!lockparent) { VOP_UNLOCK(vdp, 0, p); + cnp->cn_flags |= PDIRUNLOCK; + } return (EJUSTRETURN); } /* @@ -460,8 +463,10 @@ found: if (flags & ISDOTDOT) VOP_UNLOCK(vdp, 0, p); /* race to get the inode */ error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); - if (flags & ISDOTDOT) - vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p); + if (flags & ISDOTDOT) { + if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p) != 0) + cnp->cn_flags |= PDIRUNLOCK; + } if (error) return (error); /* @@ -478,8 +483,10 @@ found: return (EPERM); } *vpp = tdp; - if (!lockparent) + if (!lockparent) { VOP_UNLOCK(vdp, 0, p); + cnp->cn_flags |= PDIRUNLOCK; + } return (0); } @@ -501,14 +508,18 @@ found: if (flags & ISDOTDOT) VOP_UNLOCK(vdp, 0, p); /* race to get the inode */ error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); - if (flags & ISDOTDOT) - vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p); + if (flags & ISDOTDOT) { + if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p) != 0) + cnp->cn_flags |= PDIRUNLOCK; + } if (error) return (error); *vpp = tdp; cnp->cn_flags |= SAVENAME; - if (!lockparent) + if (!lockparent) { VOP_UNLOCK(vdp, 0, p); + cnp->cn_flags |= PDIRUNLOCK; + } return (0); } @@ -534,14 +545,18 @@ found: pdp = vdp; if (flags & ISDOTDOT) { VOP_UNLOCK(pdp, 0, p); /* race to get the inode */ + cnp->cn_flags |= PDIRUNLOCK; if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) != 0) { - vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p); + if (vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p) == 0) + cnp->cn_flags &= ~PDIRUNLOCK; return (error); } - if (lockparent && (flags & ISLASTCN) && - (error = vn_lock(pdp, LK_EXCLUSIVE, p))) { - vput(tdp); - return (error); + if (lockparent && (flags & ISLASTCN)) { + if ((error = vn_lock(pdp, LK_EXCLUSIVE, p)) != 0) { + vput(tdp); + return (error); + } + cnp->cn_flags &= ~PDIRUNLOCK; } *vpp = tdp; } else if (dp->i_number == dp->i_ino) { @@ -551,8 +566,10 @@ found: error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp); if (error) return (error); - if (!lockparent || !(flags & ISLASTCN)) + if (!lockparent || !(flags & ISLASTCN)) { VOP_UNLOCK(pdp, 0, p); + cnp->cn_flags |= PDIRUNLOCK; + } *vpp = tdp; } |