aboutsummaryrefslogtreecommitdiff
path: root/sys/fs
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2012-03-05 11:38:02 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2012-03-05 11:38:02 +0000
commit31452ff75ea91680132d10d4f03bfc06f8e0c01b (patch)
treefcf9755f8c999877e34c28f310135c48a7b5b031 /sys/fs
parente8052eb4ea9ab647937e1fd0ce534fad0e7a1638 (diff)
downloadsrc-31452ff75ea91680132d10d4f03bfc06f8e0c01b.tar.gz
src-31452ff75ea91680132d10d4f03bfc06f8e0c01b.zip
Apply inlined vn_vget_ino() algorithm for ".." lookup in pseudofs.
Reported and tested by: pho MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=232541
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index 8a9ca6424429..9f97cd3b64ce 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -432,6 +432,7 @@ pfs_lookup(struct vop_cachedlookup_args *va)
struct pfs_vdata *pvd = vn->v_data;
struct pfs_node *pd = pvd->pvd_pn;
struct pfs_node *pn, *pdn = NULL;
+ struct mount *mp;
pid_t pid = pvd->pvd_pid;
char *pname;
int error, i, namelen, visible;
@@ -474,10 +475,26 @@ pfs_lookup(struct vop_cachedlookup_args *va)
PFS_RETURN (0);
}
+ mp = vn->v_mount;
+
/* parent */
if (cnp->cn_flags & ISDOTDOT) {
if (pd->pn_type == pfstype_root)
PFS_RETURN (EIO);
+ error = vfs_busy(mp, MBF_NOWAIT);
+ if (error != 0) {
+ vfs_ref(mp);
+ VOP_UNLOCK(vn, 0);
+ error = vfs_busy(mp, 0);
+ vn_lock(vn, LK_EXCLUSIVE | LK_RETRY);
+ vfs_rel(mp);
+ if (error != 0)
+ PFS_RETURN(ENOENT);
+ if (vn->v_iflag & VI_DOOMED) {
+ vfs_unbusy(mp);
+ PFS_RETURN(ENOENT);
+ }
+ }
VOP_UNLOCK(vn, 0);
KASSERT(pd->pn_parent != NULL,
("%s(): non-root directory has no parent", __func__));
@@ -535,18 +552,28 @@ pfs_lookup(struct vop_cachedlookup_args *va)
goto failed;
}
- error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid);
+ error = pfs_vncache_alloc(mp, vpp, pn, pid);
if (error)
goto failed;
- if (cnp->cn_flags & ISDOTDOT)
- vn_lock(vn, LK_EXCLUSIVE|LK_RETRY);
+ if (cnp->cn_flags & ISDOTDOT) {
+ vfs_unbusy(mp);
+ vn_lock(vn, LK_EXCLUSIVE | LK_RETRY);
+ if (vn->v_iflag & VI_DOOMED) {
+ vput(*vpp);
+ *vpp = NULL;
+ PFS_RETURN(ENOENT);
+ }
+ }
if (cnp->cn_flags & MAKEENTRY && !(vn->v_iflag & VI_DOOMED))
cache_enter(vn, *vpp, cnp);
PFS_RETURN (0);
failed:
- if (cnp->cn_flags & ISDOTDOT)
- vn_lock(vn, LK_EXCLUSIVE|LK_RETRY);
+ if (cnp->cn_flags & ISDOTDOT) {
+ vfs_unbusy(mp);
+ vn_lock(vn, LK_EXCLUSIVE | LK_RETRY);
+ *vpp = NULL;
+ }
PFS_RETURN(error);
}