summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2002-07-08 01:50:14 +0000
committerjeff <jeff@FreeBSD.org>2002-07-08 01:50:14 +0000
commitce302369fbc64b2aa6f88338e81f3b1b823e19c9 (patch)
tree7decaf3e7f03a441cd6eea5eb2608db8dad3e7b6
parentc6f71d2a1d2a024e553871e2c8c17f8ab360ce66 (diff)
downloadFreeBSD-src-ce302369fbc64b2aa6f88338e81f3b1b823e19c9.zip
FreeBSD-src-ce302369fbc64b2aa6f88338e81f3b1b823e19c9.tar.gz
Lock down pseudofs:
- Initialize lock structure in vncache_alloc - Return locked vnodes from vncache_alloc - Setup vnode op vectors to use default lock, unlock, and islocked - Implement simple locking scheme required for lookup
-rw-r--r--sys/fs/pseudofs/pseudofs_vncache.c5
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c24
2 files changed, 29 insertions, 0 deletions
diff --git a/sys/fs/pseudofs/pseudofs_vncache.c b/sys/fs/pseudofs/pseudofs_vncache.c
index 5f21d67..498de38 100644
--- a/sys/fs/pseudofs/pseudofs_vncache.c
+++ b/sys/fs/pseudofs/pseudofs_vncache.c
@@ -120,6 +120,8 @@ pfs_vncache_alloc(struct mount *mp, struct vnode **vpp,
mtx_unlock(&pfs_vncache_mutex);
/* XXX see comment at top of pfs_lookup() */
cache_purge(*vpp);
+ vn_lock(*vpp, LK_RETRY | LK_EXCLUSIVE,
+ curthread);
return (0);
}
/* XXX if this can happen, we're in trouble */
@@ -171,6 +173,9 @@ pfs_vncache_alloc(struct mount *mp, struct vnode **vpp,
pvd->pvd_next->pvd_prev = pvd;
pfs_vncache = pvd;
mtx_unlock(&pfs_vncache_mutex);
+ (*vpp)->v_vnlock = &(*vpp)->v_lock;
+ lockinit((*vpp)->v_vnlock, PINOD, "pfsnod", VLKTIMEOUT, LK_CANRECURSE);
+ vn_lock(*vpp, LK_RETRY | LK_EXCLUSIVE, curthread);
return (0);
}
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index 1c3c847..0eed8ea 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -312,11 +312,15 @@ pfs_lookup(struct vop_lookup_args *va)
struct pfs_node *pd = pvd->pvd_pn;
struct pfs_node *pn, *pdn = NULL;
pid_t pid = pvd->pvd_pid;
+ int lockparent;
+ int wantparent;
char *pname;
int error, i, namelen;
PFS_TRACE(("%.*s", (int)cnp->cn_namelen, cnp->cn_nameptr));
+ cnp->cn_flags &= ~PDIRUNLOCK;
+
if (vn->v_type != VDIR)
PFS_RETURN (ENOTDIR);
@@ -336,6 +340,10 @@ pfs_lookup(struct vop_lookup_args *va)
if (!pfs_visible(curthread, pd, pvd->pvd_pid))
PFS_RETURN (ENOENT);
+ lockparent = cnp->cn_flags & LOCKPARENT;
+ wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
+
+
/* self */
namelen = cnp->cn_namelen;
pname = cnp->cn_nameptr;
@@ -350,6 +358,9 @@ pfs_lookup(struct vop_lookup_args *va)
if (cnp->cn_flags & ISDOTDOT) {
if (pd->pn_type == pfstype_root)
PFS_RETURN (EIO);
+ VOP_UNLOCK(vn, 0, cnp->cn_thread);
+ cnp->cn_flags |= PDIRUNLOCK;
+
KASSERT(pd->pn_parent, ("non-root directory has no parent"));
/*
* This one is tricky. Descendents of procdir nodes
@@ -390,9 +401,19 @@ pfs_lookup(struct vop_lookup_args *va)
pn->pn_parent = pd;
if (!pfs_visible(curthread, pn, pvd->pvd_pid))
PFS_RETURN (ENOENT);
+
error = pfs_vncache_alloc(vn->v_mount, vpp, pn, pid);
if (error)
PFS_RETURN (error);
+
+ if ((cnp->cn_flags & ISDOTDOT) && (cnp->cn_flags & ISLASTCN)
+ && lockparent) {
+ vn_lock(vn, LK_EXCLUSIVE|LK_RETRY, cnp->cn_thread);
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ }
+ if (!lockparent || !(cnp->cn_flags & ISLASTCN))
+ VOP_UNLOCK(vn, 0, cnp->cn_thread);
+
/*
* XXX See comment at top of the routine.
*/
@@ -806,6 +827,9 @@ static struct vnodeopv_entry_desc pfs_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)pfs_setattr },
{ &vop_symlink_desc, (vop_t *)vop_eopnotsupp },
{ &vop_write_desc, (vop_t *)pfs_write },
+ { &vop_lock_desc, (vop_t *)vop_stdlock },
+ { &vop_unlock_desc, (vop_t *)vop_stdunlock },
+ { &vop_islocked_desc, (vop_t *)vop_stdislocked},
/* XXX I've probably forgotten a few that need vop_eopnotsupp */
{ NULL, (vop_t *)NULL }
};
OpenPOWER on IntegriCloud