File: [local] / src / sys / kern / vfs_default.c (download)
Revision 1.3, Thu Aug 6 19:34:24 1998 UTC (25 years, 10 months ago) by csapuntz
Branch: MAIN
CVS Tags: kame_19991208, SMP_BASE, OPENBSD_2_8_BASE, OPENBSD_2_8, OPENBSD_2_7_BASE, OPENBSD_2_7, OPENBSD_2_6_BASE, OPENBSD_2_6, OPENBSD_2_5_BASE, OPENBSD_2_5, OPENBSD_2_4_BASE, OPENBSD_2_4 Branch point for: SMP
Changes since 1.2: +26 -10 lines
Rename vop_revoke, vn_bwrite, vop_noislocked, vop_nolock, vop_nounlock
to be vop_generic_revoke, vop_generic_bwrite, vop_generic_islocked,
vop_generic_lock and vop_generic_unlock.
Create vop_generic_abortop and propogate change to all file systems.
Fix PR/371.
Get rid of locking in NULLFS (should be mostly unnecessary now except for
forced unmounts).
|
/* $OpenBSD: vfs_default.c,v 1.3 1998/08/06 19:34:24 csapuntz Exp $ */
/*
* Portions of this code are:
*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <miscfs/specfs/specdev.h>
extern struct simplelock spechash_slock;
/*
* Eliminate all activity associated with the requested vnode
* and with all vnodes aliased to the requested vnode.
*/
int
vop_generic_revoke(v)
void *v;
{
struct vop_revoke_args /* {
struct vnode *a_vp;
int a_flags;
} */ *ap = v;
struct vnode *vp, *vq;
struct proc *p = curproc;
#ifdef DIAGNOSTIC
if ((ap->a_flags & REVOKEALL) == 0)
panic("vop_generic_revoke");
#endif
vp = ap->a_vp;
simple_lock(&vp->v_interlock);
if (vp->v_flag & VALIASED) {
/*
* If a vgone (or vclean) is already in progress,
* wait until it is done and return.
*/
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
simple_unlock(&vp->v_interlock);
tsleep((caddr_t)vp, PINOD, "vop_generic_revokeall", 0);
return(0);
}
/*
* Ensure that vp will not be vgone'd while we
* are eliminating its aliases.
*/
vp->v_flag |= VXLOCK;
simple_unlock(&vp->v_interlock);
while (vp->v_flag & VALIASED) {
simple_lock(&spechash_slock);
for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
if (vq->v_rdev != vp->v_rdev ||
vq->v_type != vp->v_type || vp == vq)
continue;
simple_unlock(&spechash_slock);
vgone(vq);
break;
}
}
/*
* Remove the lock so that vgone below will
* really eliminate the vnode after which time
* vgone will awaken any sleepers.
*/
simple_lock(&vp->v_interlock);
vp->v_flag &= ~VXLOCK;
}
vgonel(vp, p);
return (0);
}
int
vop_generic_bwrite(v)
void *v;
{
struct vop_bwrite_args *ap = v;
return (bwrite(ap->a_bp));
}
int
vop_generic_abortop(v)
void *v;
{
struct vop_abortop_args /* {
struct vnode *a_dvp;
struct componentname *a_cnp;
} */ *ap = v;
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
return (0);
}
/*
* Stubs to use when there is no locking to be done on the underlying object.
* A minimal shared lock is necessary to ensure that the underlying object
* is not revoked while an operation is in progress. So, an active shared
* count is maintained in an auxillary vnode lock structure.
*/
int
vop_generic_lock(v)
void *v;
{
struct vop_lock_args /* {
struct vnode *a_vp;
int a_flags;
struct proc *a_p;
} */ *ap = v;
#ifdef notyet
/*
* This code cannot be used until all the non-locking filesystems
* (notably NFS) are converted to properly lock and release nodes.
* Also, certain vnode operations change the locking state within
* the operation (create, mknod, remove, link, rename, mkdir, rmdir,
* and symlink). Ideally these operations should not change the
* lock state, but should be changed to let the caller of the
* function unlock them. Otherwise all intermediate vnode layers
* (such as union, umapfs, etc) must catch these functions to do
* the necessary locking at their layer. Note that the inactive
* and lookup operations also change their lock state, but this
* cannot be avoided, so these two operations will always need
* to be handled in intermediate layers.
*/
struct vnode *vp = ap->a_vp;
int vnflags, flags = ap->a_flags;
if (vp->v_vnlock == NULL) {
if ((flags & LK_TYPE_MASK) == LK_DRAIN)
return (0);
MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
M_VNODE, M_WAITOK);
lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
}
switch (flags & LK_TYPE_MASK) {
case LK_DRAIN:
vnflags = LK_DRAIN;
break;
case LK_EXCLUSIVE:
case LK_SHARED:
vnflags = LK_SHARED;
break;
case LK_UPGRADE:
case LK_EXCLUPGRADE:
case LK_DOWNGRADE:
return (0);
case LK_RELEASE:
default:
panic("vop_generic_lock: bad operation %d", flags & LK_TYPE_MASK);
}
if (flags & LK_INTERLOCK)
vnflags |= LK_INTERLOCK;
return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
#else /* for now */
/*
* Since we are not using the lock manager, we must clear
* the interlock here.
*/
if (ap->a_flags & LK_INTERLOCK)
simple_unlock(&ap->a_vp->v_interlock);
return (0);
#endif
}
/*
* Decrement the active use count.
*/
int
vop_generic_unlock(v)
void *v;
{
struct vop_unlock_args /* {
struct vnode *a_vp;
int a_flags;
struct proc *a_p;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
if (vp->v_vnlock == NULL)
return (0);
return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p));
}
/*
* Return whether or not the node is in use.
*/
int
vop_generic_islocked(v)
void *v;
{
struct vop_islocked_args /* {
struct vnode *a_vp;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
if (vp->v_vnlock == NULL)
return (0);
return (lockstatus(vp->v_vnlock));
}