diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/exec_script.c | 4 | ||||
-rw-r--r-- | sys/kern/init_main.c | 9 | ||||
-rw-r--r-- | sys/kern/kern_acct.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_ktrace.c | 10 | ||||
-rw-r--r-- | sys/kern/kern_lkm.c | 47 | ||||
-rw-r--r-- | sys/kern/kern_lock.c | 537 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 9 | ||||
-rw-r--r-- | sys/kern/spec_vnops.c | 159 | ||||
-rw-r--r-- | sys/kern/subr_xxx.c | 6 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 22 | ||||
-rw-r--r-- | sys/kern/sys_pipe.c | 4 | ||||
-rw-r--r-- | sys/kern/tty.c | 6 | ||||
-rw-r--r-- | sys/kern/tty_tty.c | 16 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 294 | ||||
-rw-r--r-- | sys/kern/vfs_cluster.c | 19 | ||||
-rw-r--r-- | sys/kern/vfs_conf.c | 172 | ||||
-rw-r--r-- | sys/kern/vfs_init.c | 21 | ||||
-rw-r--r-- | sys/kern/vfs_lookup.c | 36 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 1230 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 406 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 58 | ||||
-rw-r--r-- | sys/kern/vnode_if.c | 76 | ||||
-rw-r--r-- | sys/kern/vnode_if.src | 241 |
28 files changed, 882 insertions, 2526 deletions
diff --git a/sys/kern/exec_script.c b/sys/kern/exec_script.c index 91f6d638397..3b826d994ab 100644 --- a/sys/kern/exec_script.c +++ b/sys/kern/exec_script.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_script.c,v 1.5 1997/10/06 15:12:10 csapuntz Exp $ */ +/* $OpenBSD: exec_script.c,v 1.6 1997/10/06 20:19:48 deraadt Exp $ */ /* $NetBSD: exec_script.c,v 1.13 1996/02/04 02:15:06 christos Exp $ */ /* @@ -228,7 +228,7 @@ check_shell: scriptvp = epp->ep_vp; oldpnbuf = epp->ep_ndp->ni_cnd.cn_pnbuf; - VOP_UNLOCK(scriptvp, 0, p); + VOP_UNLOCK(scriptvp); if ((error = check_exec(p, epp)) == 0) { /* note that we've clobbered the header */ diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index ae47944d74e..5753d2fb76a 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.25 1997/10/06 15:12:12 csapuntz Exp $ */ +/* $OpenBSD: init_main.c,v 1.26 1997/10/06 20:19:49 deraadt Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -335,16 +335,17 @@ main(framep) schedcpu(NULL); /* Mount the root file system. */ - if (vfs_mountroot()) + if ((*mountroot)()) panic("cannot mount root"); mountlist.cqh_first->mnt_flag |= MNT_ROOTFS; + mountlist.cqh_first->mnt_op->vfs_refcount++; /* Get the vnode for '/'. Set filedesc0.fd_fd.fd_cdir to reference it. */ if (VFS_ROOT(mountlist.cqh_first, &rootvnode)) panic("cannot find root vnode"); filedesc0.fd_fd.fd_cdir = rootvnode; VREF(filedesc0.fd_fd.fd_cdir); - VOP_UNLOCK(rootvnode, 0, p); + VOP_UNLOCK(rootvnode); filedesc0.fd_fd.fd_rdir = NULL; swapinit(); @@ -583,6 +584,6 @@ start_update(p) */ p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ bcopy("update", curproc->p_comm, sizeof ("update")); - sched_sync(p); + vn_update(); /* NOTREACHED */ } diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c index ccf5d0a79db..98341253604 100644 --- a/sys/kern/kern_acct.c +++ b/sys/kern/kern_acct.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_acct.c,v 1.3 1997/10/06 15:12:14 csapuntz Exp $ */ +/* $OpenBSD: kern_acct.c,v 1.4 1997/10/06 20:19:50 deraadt Exp $ */ /* $NetBSD: kern_acct.c,v 1.42 1996/02/04 02:15:12 christos Exp $ */ /*- @@ -120,7 +120,7 @@ sys_acct(p, v, retval) p); if ((error = vn_open(&nd, FWRITE, 0)) != 0) return (error); - VOP_UNLOCK(nd.ni_vp, 0, p); + VOP_UNLOCK(nd.ni_vp); if (nd.ni_vp->v_type != VREG) { vn_close(nd.ni_vp, FWRITE, p->p_ucred, p); return (EACCES); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index b70c6bd3cd2..e05d7236b9d 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exec.c,v 1.13 1997/10/06 15:12:16 csapuntz Exp $ */ +/* $OpenBSD: kern_exec.c,v 1.14 1997/10/06 20:19:51 deraadt Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- @@ -188,10 +188,10 @@ check_exec(p, epp) bad2: /* - * unlock and close the vnode, free the + * unlock and close the vnode, restore the old one, free the * pathname buf, and punt. */ - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); vn_close(vp, FREAD, p->p_ucred, p); FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); return error; diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index bab12bfe770..17f5d829dee 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.10 1997/10/06 15:12:17 csapuntz Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.11 1997/10/06 20:19:52 deraadt Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -179,7 +179,7 @@ exit1(p, rv) * if we blocked. */ if (sp->s_ttyvp) - VOP_REVOKE(sp->s_ttyvp, REVOKEALL); + vgoneall(sp->s_ttyvp); } if (sp->s_ttyvp) vrele(sp->s_ttyvp); diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 973ba8e5827..13440997cfe 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_ktrace.c,v 1.4 1997/10/06 15:12:18 csapuntz Exp $ */ +/* $OpenBSD: kern_ktrace.c,v 1.5 1997/10/06 20:19:53 deraadt Exp $ */ /* $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $ */ /* @@ -293,9 +293,7 @@ sys_ktrace(curp, v, retval) return (error); } vp = nd.ni_vp; - - /* FIXME: Should be curp?? */ - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); if (vp->v_type != VREG) { (void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp); curp->p_traceflag &= ~KTRFAC_ACTIVE; @@ -470,9 +468,9 @@ ktrwrite(vp, kth) aiov[1].iov_len = kth->ktr_len; auio.uio_resid += kth->ktr_len; } - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred); - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); if (!error) return; /* diff --git a/sys/kern/kern_lkm.c b/sys/kern/kern_lkm.c index 524b3671468..663bf0ca395 100644 --- a/sys/kern/kern_lkm.c +++ b/sys/kern/kern_lkm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_lkm.c,v 1.19 1997/10/06 15:12:19 csapuntz Exp $ */ +/* $OpenBSD: kern_lkm.c,v 1.20 1997/10/06 20:19:54 deraadt Exp $ */ /* $NetBSD: kern_lkm.c,v 1.31 1996/03/31 21:40:27 christos Exp $ */ /* @@ -689,52 +689,57 @@ _lkm_vfs(lkmtp, cmd) struct lkm_table *lkmtp; int cmd; { - int error = 0; -#if 0 struct lkm_vfs *args = lkmtp->private.lkm_vfs; - struct vfsconf *vfsp, **vfspp; -#endif + int i; + int error = 0; + switch(cmd) { case LKM_E_LOAD: /* don't load twice! */ if (lkmexists(lkmtp)) return (EEXIST); - return (EEXIST); -#if 0 /* make sure there's no VFS in the table with this name */ - for (vfspp = &vfsconf, vfsp = vfsconf; - vfsp; - vfspp = &vfsp->vfc_next, vfsp = vfsp->vfc_next) - if (strncmp(vfsp->vfc_name, + for (i = 0; i < nvfssw; i++) + if (vfssw[i] != (struct vfsops *)0 && + strncmp(vfssw[i]->vfs_name, args->lkm_vfsops->vfs_name, MFSNAMELEN) == 0) return (EEXIST); - /* pick the last available empty slot */ - MALLOC (vfsp, struct vfsconf *, sizeof (struct vfsconf), - M_VFS, M_WAITOK); - - /* Add tot he end of the list */ - *vfspp = vfsp; + for (i = nvfssw - 1; i >= 0; i--) + if (vfssw[i] == (struct vfsops *)0) + break; + if (i == -1) { /* or if none, punt */ + error = EINVAL; + break; + } /* * Set up file system */ - /* FIXME (CPS): Setup new vfsconf structure */ + vfssw[i] = args->lkm_vfsops; + vfssw[i]->vfs_refcount = 0; /* * Call init function for this VFS... */ - (*(vfsp->vfc_vfsops->vfs_init))(vfsp); + (*(vfssw[i]->vfs_init))(); /* done! */ - /* Nope - can't return this */ + args->lkm_offset = i; /* slot in vfssw[] */ break; -#endif case LKM_E_UNLOAD: + /* current slot... */ + i = args->lkm_offset; + + if (vfssw[i]->vfs_refcount != 0) + return (EBUSY); + + /* replace current slot contents with old contents */ + vfssw[i] = (struct vfsops *)0; break; case LKM_E_STAT: /* no special handling... */ diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c deleted file mode 100644 index c6793d24f58..00000000000 --- a/sys/kern/kern_lock.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (c) 1995 - * The Regents of the University of California. All rights reserved. - * - * This code contains ideas from software contributed to Berkeley by - * Avadis Tevanian, Jr., Michael Wayne Young, and the Mach Operating - * System project at Carnegie-Mellon University. - * - * 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. - * - * @(#)kern_lock.c 8.18 (Berkeley) 5/21/95 - */ - -#include <sys/param.h> -#include <sys/proc.h> -#include <sys/lock.h> -#include <sys/systm.h> - -#include <machine/cpu.h> - -void record_stacktrace __P((int *, int)); -void playback_stacktrace __P((int *, int)); - -/* - * Locking primitives implementation. - * Locks provide shared/exclusive sychronization. - */ - -#ifdef DEBUG -#define COUNT(p, x) if (p) (p)->p_locks += (x) -#else -#define COUNT(p, x) -#endif - -#if NCPUS > 1 - -/* - * For multiprocessor system, try spin lock first. - * - * This should be inline expanded below, but we cannot have #if - * inside a multiline define. - */ -int lock_wait_time = 100; -#define PAUSE(lkp, wanted) \ - if (lock_wait_time > 0) { \ - int i; \ - \ - simple_unlock(&lkp->lk_interlock); \ - for (i = lock_wait_time; i > 0; i--) \ - if (!(wanted)) \ - break; \ - simple_lock(&lkp->lk_interlock); \ - } \ - if (!(wanted)) \ - break; - -#else /* NCPUS == 1 */ - -/* - * It is an error to spin on a uniprocessor as nothing will ever cause - * the simple lock to clear while we are executing. - */ -#define PAUSE(lkp, wanted) - -#endif /* NCPUS == 1 */ - -/* - * Acquire a resource. - */ -#define ACQUIRE(lkp, error, extflags, wanted) \ - PAUSE(lkp, wanted); \ - for (error = 0; wanted; ) { \ - (lkp)->lk_waitcount++; \ - simple_unlock(&(lkp)->lk_interlock); \ - error = tsleep((void *)lkp, (lkp)->lk_prio, \ - (lkp)->lk_wmesg, (lkp)->lk_timo); \ - simple_lock(&(lkp)->lk_interlock); \ - (lkp)->lk_waitcount--; \ - if (error) \ - break; \ - if ((extflags) & LK_SLEEPFAIL) { \ - error = ENOLCK; \ - break; \ - } \ - } - -/* - * Initialize a lock; required before use. - */ -void -lockinit(lkp, prio, wmesg, timo, flags) - struct lock *lkp; - int prio; - char *wmesg; - int timo; - int flags; -{ - - bzero(lkp, sizeof(struct lock)); - simple_lock_init(&lkp->lk_interlock); - lkp->lk_flags = flags & LK_EXTFLG_MASK; - lkp->lk_prio = prio; - lkp->lk_timo = timo; - lkp->lk_wmesg = wmesg; - lkp->lk_lockholder = LK_NOPROC; -} - -/* - * Determine the status of a lock. - */ -int -lockstatus(lkp) - struct lock *lkp; -{ - int lock_type = 0; - - simple_lock(&lkp->lk_interlock); - if (lkp->lk_exclusivecount != 0) - lock_type = LK_EXCLUSIVE; - else if (lkp->lk_sharecount != 0) - lock_type = LK_SHARED; - simple_unlock(&lkp->lk_interlock); - return (lock_type); -} - -/* - * Set, change, or release a lock. - * - * Shared requests increment the shared count. Exclusive requests set the - * LK_WANT_EXCL flag (preventing further shared locks), and wait for already - * accepted shared locks and shared-to-exclusive upgrades to go away. - */ -int -lockmgr(lkp, flags, interlkp, p) - __volatile struct lock *lkp; - u_int flags; - struct simplelock *interlkp; - struct proc *p; -{ - int error; - pid_t pid; - int extflags; - - error = 0; - if (p) - pid = p->p_pid; - else - pid = LK_KERNPROC; - simple_lock(&lkp->lk_interlock); - if (flags & LK_INTERLOCK) - simple_unlock(interlkp); - extflags = (flags | lkp->lk_flags) & LK_EXTFLG_MASK; -#ifdef DIAGNOSTIC - /* - * Once a lock has drained, the LK_DRAINING flag is set and an - * exclusive lock is returned. The only valid operation thereafter - * is a single release of that exclusive lock. This final release - * clears the LK_DRAINING flag and sets the LK_DRAINED flag. Any - * further requests of any sort will result in a panic. The bits - * selected for these two flags are chosen so that they will be set - * in memory that is freed (freed memory is filled with 0xdeadbeef). - * The final release is permitted to give a new lease on life to - * the lock by specifying LK_REENABLE. - */ - if (lkp->lk_flags & (LK_DRAINING|LK_DRAINED)) { - if (lkp->lk_flags & LK_DRAINED) - panic("lockmgr: using decommissioned lock"); - if ((flags & LK_TYPE_MASK) != LK_RELEASE || - lkp->lk_lockholder != pid) - panic("lockmgr: non-release on draining lock: %d\n", - flags & LK_TYPE_MASK); - lkp->lk_flags &= ~LK_DRAINING; - if ((flags & LK_REENABLE) == 0) - lkp->lk_flags |= LK_DRAINED; - } -#endif DIAGNOSTIC - - switch (flags & LK_TYPE_MASK) { - - case LK_SHARED: - if (lkp->lk_lockholder != pid) { - /* - * If just polling, check to see if we will block. - */ - if ((extflags & LK_NOWAIT) && (lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE))) { - error = EBUSY; - break; - } - /* - * Wait for exclusive locks and upgrades to clear. - */ - ACQUIRE(lkp, error, extflags, lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)); - if (error) - break; - lkp->lk_sharecount++; - COUNT(p, 1); - break; - } - /* - * We hold an exclusive lock, so downgrade it to shared. - * An alternative would be to fail with EDEADLK. - */ - lkp->lk_sharecount++; - COUNT(p, 1); - /* fall into downgrade */ - - case LK_DOWNGRADE: - if (lkp->lk_lockholder != pid || lkp->lk_exclusivecount == 0) - panic("lockmgr: not holding exclusive lock"); - lkp->lk_sharecount += lkp->lk_exclusivecount; - lkp->lk_exclusivecount = 0; - lkp->lk_flags &= ~LK_HAVE_EXCL; - lkp->lk_lockholder = LK_NOPROC; - if (lkp->lk_waitcount) - wakeup((void *)lkp); - break; - - case LK_EXCLUPGRADE: - /* - * If another process is ahead of us to get an upgrade, - * then we want to fail rather than have an intervening - * exclusive access. - */ - if (lkp->lk_flags & LK_WANT_UPGRADE) { - lkp->lk_sharecount--; - COUNT(p, -1); - error = EBUSY; - break; - } - /* fall into normal upgrade */ - - case LK_UPGRADE: - /* - * Upgrade a shared lock to an exclusive one. If another - * shared lock has already requested an upgrade to an - * exclusive lock, our shared lock is released and an - * exclusive lock is requested (which will be granted - * after the upgrade). If we return an error, the file - * will always be unlocked. - */ - if (lkp->lk_lockholder == pid || lkp->lk_sharecount <= 0) - panic("lockmgr: upgrade exclusive lock"); - lkp->lk_sharecount--; - COUNT(p, -1); - /* - * If we are just polling, check to see if we will block. - */ - if ((extflags & LK_NOWAIT) && - ((lkp->lk_flags & LK_WANT_UPGRADE) || - lkp->lk_sharecount > 1)) { - error = EBUSY; - break; - } - if ((lkp->lk_flags & LK_WANT_UPGRADE) == 0) { - /* - * We are first shared lock to request an upgrade, so - * request upgrade and wait for the shared count to - * drop to zero, then take exclusive lock. - */ - lkp->lk_flags |= LK_WANT_UPGRADE; - ACQUIRE(lkp, error, extflags, lkp->lk_sharecount); - lkp->lk_flags &= ~LK_WANT_UPGRADE; - if (error) - break; - lkp->lk_flags |= LK_HAVE_EXCL; - lkp->lk_lockholder = pid; - if (lkp->lk_exclusivecount != 0) - panic("lockmgr: non-zero exclusive count"); - lkp->lk_exclusivecount = 1; - COUNT(p, 1); - break; - } - /* - * Someone else has requested upgrade. Release our shared - * lock, awaken upgrade requestor if we are the last shared - * lock, then request an exclusive lock. - */ - if (lkp->lk_sharecount == 0 && lkp->lk_waitcount) - wakeup((void *)lkp); - /* fall into exclusive request */ - - case LK_EXCLUSIVE: - if (lkp->lk_lockholder == pid && pid != LK_KERNPROC) { - /* - * Recursive lock. - */ - if ((extflags & LK_CANRECURSE) == 0) - panic("lockmgr: locking against myself"); - lkp->lk_exclusivecount++; - COUNT(p, 1); - break; - } - /* - * If we are just polling, check to see if we will sleep. - */ - if ((extflags & LK_NOWAIT) && ((lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) || - lkp->lk_sharecount != 0)) { - error = EBUSY; - break; - } - /* - * Try to acquire the want_exclusive flag. - */ - ACQUIRE(lkp, error, extflags, lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL)); - if (error) - break; - lkp->lk_flags |= LK_WANT_EXCL; - /* - * Wait for shared locks and upgrades to finish. - */ - ACQUIRE(lkp, error, extflags, lkp->lk_sharecount != 0 || - (lkp->lk_flags & LK_WANT_UPGRADE)); - lkp->lk_flags &= ~LK_WANT_EXCL; - if (error) - break; - lkp->lk_flags |= LK_HAVE_EXCL; - lkp->lk_lockholder = pid; - if (lkp->lk_exclusivecount != 0) - panic("lockmgr: non-zero exclusive count"); - lkp->lk_exclusivecount = 1; - COUNT(p, 1); - break; - - case LK_RELEASE: - if (lkp->lk_exclusivecount != 0) { - if (pid != lkp->lk_lockholder) - panic("lockmgr: pid %d, not %s %d unlocking", - pid, "exclusive lock holder", - lkp->lk_lockholder); - lkp->lk_exclusivecount--; - COUNT(p, -1); - if (lkp->lk_exclusivecount == 0) { - lkp->lk_flags &= ~LK_HAVE_EXCL; - lkp->lk_lockholder = LK_NOPROC; - } - } else if (lkp->lk_sharecount != 0) { - lkp->lk_sharecount--; - COUNT(p, -1); - } - if (lkp->lk_waitcount) - wakeup((void *)lkp); - break; - - case LK_DRAIN: - /* - * Check that we do not already hold the lock, as it can - * never drain if we do. Unfortunately, we have no way to - * check for holding a shared lock, but at least we can - * check for an exclusive one. - */ - if (lkp->lk_lockholder == pid) - panic("lockmgr: draining against myself"); - /* - * If we are just polling, check to see if we will sleep. - */ - if ((extflags & LK_NOWAIT) && ((lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) || - lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0)) { - error = EBUSY; - break; - } - PAUSE(lkp, ((lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) || - lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0)); - for (error = 0; ((lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) || - lkp->lk_sharecount != 0 || lkp->lk_waitcount != 0); ) { - lkp->lk_flags |= LK_WAITDRAIN; - simple_unlock(&lkp->lk_interlock); - if ((error = tsleep((void *)&lkp->lk_flags, lkp->lk_prio, - lkp->lk_wmesg, lkp->lk_timo)) != 0) - return (error); - if ((extflags) & LK_SLEEPFAIL) - return (ENOLCK); - simple_lock(&lkp->lk_interlock); - } - lkp->lk_flags |= LK_DRAINING | LK_HAVE_EXCL; - lkp->lk_lockholder = pid; - lkp->lk_exclusivecount = 1; - COUNT(p, 1); - break; - - default: - simple_unlock(&lkp->lk_interlock); - panic("lockmgr: unknown locktype request %d", - flags & LK_TYPE_MASK); - /* NOTREACHED */ - } - if ((lkp->lk_flags & LK_WAITDRAIN) && ((lkp->lk_flags & - (LK_HAVE_EXCL | LK_WANT_EXCL | LK_WANT_UPGRADE)) == 0 && - lkp->lk_sharecount == 0 && lkp->lk_waitcount == 0)) { - lkp->lk_flags &= ~LK_WAITDRAIN; - wakeup((void *)&lkp->lk_flags); - } - simple_unlock(&lkp->lk_interlock); - return (error); -} - -/* - * Print out information about state of a lock. Used by VOP_PRINT - * routines to display ststus about contained locks. - */ -void -lockmgr_printinfo(lkp) - struct lock *lkp; -{ - - if (lkp->lk_sharecount) - printf(" lock type %s: SHARED (count %d)", lkp->lk_wmesg, - lkp->lk_sharecount); - else if (lkp->lk_flags & LK_HAVE_EXCL) - printf(" lock type %s: EXCL (count %d) by pid %d", - lkp->lk_wmesg, lkp->lk_exclusivecount, lkp->lk_lockholder); - if (lkp->lk_waitcount > 0) - printf(" with %d pending", lkp->lk_waitcount); -} - -#if defined(DEBUG) && NCPUS == 1 -#include <sys/kernel.h> -#include <vm/vm.h> -#include <sys/sysctl.h> -int lockpausetime = 0; -struct ctldebug debug2 = { "lockpausetime", &lockpausetime }; -int simplelockrecurse; -/* - * Simple lock functions so that the debugger can see from whence - * they are being called. - */ -void -simple_lock_init(alp) - struct simplelock *alp; -{ - - alp->lock_data = 0; -} - -void -_simple_lock(alp, id, l) - __volatile struct simplelock *alp; - const char *id; - int l; -{ - - if (simplelockrecurse) - return; - if (alp->lock_data == 1) { - if (lockpausetime == -1) - panic("%s:%d: simple_lock: lock held", id, l); - printf("%s:%d: simple_lock: lock held\n", id, l); - if (lockpausetime == 1) { - BACKTRACE(curproc); - } else if (lockpausetime > 1) { - printf("%s:%d: simple_lock: lock held...", id, l); - tsleep(&lockpausetime, PCATCH | PPAUSE, "slock", - lockpausetime * hz); - printf(" continuing\n"); - } - } - alp->lock_data = 1; - if (curproc) - curproc->p_simple_locks++; -} - -int -_simple_lock_try(alp, id, l) - __volatile struct simplelock *alp; - const char *id; - int l; -{ - - if (alp->lock_data) - return (0); - if (simplelockrecurse) - return (1); - alp->lock_data = 1; - if (curproc) - curproc->p_simple_locks++; - return (1); -} - -void -_simple_unlock(alp, id, l) - __volatile struct simplelock *alp; - const char *id; - int l; -{ - - if (simplelockrecurse) - return; - if (alp->lock_data == 0) { - if (lockpausetime == -1) - panic("%s:%d: simple_unlock: lock not held", id, l); - printf("%s:%d: simple_unlock: lock not held\n", id, l); - if (lockpausetime == 1) { - BACKTRACE(curproc); - } else if (lockpausetime > 1) { - printf("%s:%d: simple_unlock: lock not held...", id, l); - tsleep(&lockpausetime, PCATCH | PPAUSE, "sunlock", - lockpausetime * hz); - printf(" continuing\n"); - } - } - alp->lock_data = 0; - if (curproc) - curproc->p_simple_locks--; -} -#endif /* DEBUG && NCPUS == 1 */ diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 2e29983bea4..878dd36c04c 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.20 1997/10/06 15:12:21 csapuntz Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.21 1997/10/06 20:19:56 deraadt Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -1213,7 +1213,7 @@ coredump(p) UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p); } out: - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); error1 = vn_close(vp, FWRITE, cred, p); crfree(cred); if (error == 0) diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 93d2459035d..9a1f674b9bd 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_synch.c,v 1.8 1997/10/06 15:12:23 csapuntz Exp $ */ +/* $OpenBSD: kern_synch.c,v 1.9 1997/10/06 20:19:57 deraadt Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /*- @@ -174,6 +174,7 @@ schedcpu(arg) register int s; register unsigned int newcpu; + wakeup((caddr_t)&lbolt); for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { /* * Increment time in/out of memory and sleep time @@ -222,7 +223,6 @@ schedcpu(arg) splx(s); } vmmeter(); - wakeup((caddr_t)&lbolt); timeout(schedcpu, (void *)0, hz); } diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 923a4bd9077..1b7d09d11e0 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.20 1997/10/06 15:12:25 csapuntz Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.21 1997/10/06 20:19:58 deraadt Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -110,7 +110,7 @@ sys___sysctl(p, v, retval) switch (name[0]) { case CTL_KERN: fn = kern_sysctl; - if (name[2] == KERN_VNODE) /* XXX */ + if (name[2] != KERN_VNODE) /* XXX */ dolock = 0; break; case CTL_HW: @@ -125,9 +125,6 @@ sys___sysctl(p, v, retval) case CTL_FS: fn = fs_sysctl; break; - case CTL_VFS: - fn = vfs_sysctl; - break; case CTL_MACHDEP: fn = cpu_sysctl; break; @@ -267,7 +264,7 @@ kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, sizeof(struct timeval))); case KERN_VNODE: - return (sysctl_vnode(oldp, oldlenp, p)); + return (sysctl_vnode(oldp, oldlenp)); case KERN_PROC: return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp)); case KERN_FILE: diff --git a/sys/kern/spec_vnops.c b/sys/kern/spec_vnops.c index c9d59179f98..995870d11d0 100644 --- a/sys/kern/spec_vnops.c +++ b/sys/kern/spec_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: spec_vnops.c,v 1.10 1997/10/06 15:19:12 csapuntz Exp $ */ +/* $OpenBSD: spec_vnops.c,v 1.11 1997/10/06 20:20:37 deraadt Exp $ */ /* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */ /* @@ -79,7 +79,6 @@ struct vnodeopv_entry_desc spec_vnodeop_entries[] = { { &vop_lease_desc, spec_lease_check }, /* lease */ { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ { &vop_select_desc, spec_select }, /* select */ - { &vop_revoke_desc, spec_revoke }, /* revoke */ { &vop_mmap_desc, spec_mmap }, /* mmap */ { &vop_fsync_desc, spec_fsync }, /* fsync */ { &vop_seek_desc, spec_seek }, /* seek */ @@ -144,13 +143,8 @@ spec_open(v) struct ucred *a_cred; struct proc *a_p; } */ *ap = v; - struct proc *p = ap->a_p; - struct vnode *vp = ap->a_vp; -#if 0 - struct vnode *bvp; - dev_t bdev; -#endif - dev_t dev = (dev_t)vp->v_rdev; + struct vnode *bvp, *vp = ap->a_vp; + dev_t bdev, dev = (dev_t)vp->v_rdev; register int maj = major(dev); int error; @@ -178,7 +172,6 @@ spec_open(v) * devices whose corresponding block devices are * currently mounted. */ -#if 0 if (securelevel >= 1) { if ((bdev = chrtoblk(dev)) != NODEV && vfinddev(bdev, VBLK, &bvp) && @@ -188,13 +181,12 @@ spec_open(v) if (iskmemdev(dev)) return (EPERM); } -#endif } if (cdevsw[maj].d_type == D_TTY) vp->v_flag |= VISTTY; - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); return (error); case VBLK: @@ -263,10 +255,10 @@ spec_read(v) switch (vp->v_type) { case VCHR: - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); error = (*cdevsw[major(vp->v_rdev)].d_read) (vp->v_rdev, uio, ap->a_ioflag); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); return (error); case VBLK: @@ -314,19 +306,6 @@ spec_read(v) /* NOTREACHED */ } -int -spec_inactive(v) - void *v; -{ - struct vop_inactive_args /* { - struct vnode *a_vp; - struct proc *a_p; - } */ *ap = v; - - VOP_UNLOCK(ap->a_vp, 0, ap->a_p); - return (0); -} - /* * Vnode op for write */ @@ -362,10 +341,10 @@ spec_write(v) switch (vp->v_type) { case VCHR: - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); error = (*cdevsw[major(vp->v_rdev)].d_write) (vp->v_rdev, uio, ap->a_ioflag); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); return (error); case VBLK: @@ -535,74 +514,6 @@ loop: /* * Just call the device strategy routine */ -int fs_read[16], fs_write[16]; - -int cur_found[10]; - -int fs_bwrite[64][10]; -int fs_bwrite_cnt[64]; -int num_found; - -int num_levels = 4; -#include <machine/cpu.h> -#include <machine/pcb.h> - -int find_stack(int); - -int find_stack(int levels) - -{ - struct pcb stack; - int *eip, *ebp; - - savectx(&stack); - ebp = (int *)stack.pcb_ebp; - eip = (int *) *(ebp + 1); - - while ((int)ebp > 0xf0000000 && levels--) { - eip = (int *) *(ebp + 1); - - ebp = (int *) *ebp; - } - - return ((int)eip); -} - -void track_write __P((void)); - -void track_write(void) - -{ - int idx, cnt; - - for (idx = 0; idx < 10; idx++) { - cur_found[idx] = find_stack(idx + num_levels); - } - - for (cnt = 0; cnt < num_found; cnt++) { - for (idx = 0; idx < 10; idx++) { - if (fs_bwrite[cnt][idx] != cur_found[idx]) - goto next_iter; - } - - fs_bwrite_cnt[cnt]++; - break; - next_iter: - } - - if ((cnt == num_found) && - (num_found != 64)) { - for (idx = 0; idx < 10; idx++) { - fs_bwrite[num_found][idx] = cur_found[idx]; - } - - fs_bwrite_cnt[num_found] = 1; - num_found++; - } - - return; -} - int spec_strategy(v) void *v; @@ -610,31 +521,8 @@ spec_strategy(v) struct vop_strategy_args /* { struct buf *a_bp; } */ *ap = v; - struct buf *bp; - - int maj = major(ap->a_bp->b_dev); - - if ((maj >= 0) && (maj < 16)) { - if (ap->a_bp->b_flags & B_READ) - fs_read[maj]++; - else { - fs_write[maj]++; - if (maj == 4) - track_write(); - - } - } - -#if 0 - assert (!(flags & (B_DELWRI | B_DONE))); -#endif - bp = ap->a_bp; - - if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_start) - (*bioops.io_start)(bp); - - (*bdevsw[maj].d_strategy)(ap->a_bp); + (*bdevsw[major(ap->a_bp->b_dev)].d_strategy)(ap->a_bp); return (0); } @@ -650,16 +538,33 @@ spec_bmap(v) daddr_t a_bn; struct vnode **a_vpp; daddr_t *a_bnp; - int *a_runp; } */ *ap = v; if (ap->a_vpp != NULL) *ap->a_vpp = ap->a_vp; if (ap->a_bnp != NULL) *ap->a_bnp = ap->a_bn; - if (ap->a_runp != NULL) - *ap->a_runp = 0; - + return (0); +} + +/* + * At the moment we do not do any locking. + */ +/* ARGSUSED */ +int +spec_lock(v) + void *v; +{ + + return (0); +} + +/* ARGSUSED */ +int +spec_unlock(v) + void *v; +{ + return (0); } @@ -716,9 +621,7 @@ spec_close(v) * we must invalidate any in core blocks, so that * we can, for instance, change floppy disks. */ - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p); error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0); - VOP_UNLOCK(vp, 0, ap->a_p); if (error) return (error); /* diff --git a/sys/kern/subr_xxx.c b/sys/kern/subr_xxx.c index a19a8a11a1e..f28d988d9a2 100644 --- a/sys/kern/subr_xxx.c +++ b/sys/kern/subr_xxx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_xxx.c,v 1.4 1997/10/06 15:12:26 csapuntz Exp $ */ +/* $OpenBSD: subr_xxx.c,v 1.5 1997/10/06 20:20:00 deraadt Exp $ */ /* $NetBSD: subr_xxx.c,v 1.10 1996/02/04 02:16:51 christos Exp $ */ /* @@ -91,10 +91,8 @@ enosys () * Return error for operation not supported * on a specific object or file type. */ -/*ARGSUSED*/ int -eopnotsupp(v) - void *v; +eopnotsupp() { return (EOPNOTSUPP); diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index ab02e3bb9d2..4e9e7c8e10b 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_generic.c,v 1.9 1997/10/06 15:12:28 csapuntz Exp $ */ +/* $OpenBSD: sys_generic.c,v 1.10 1997/10/06 20:20:01 deraadt Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* @@ -178,12 +178,18 @@ sys_readv(p, v, retval) goto done; auio.uio_resid = 0; for (i = 0; i < SCARG(uap, iovcnt); i++) { - if (auio.uio_resid + iov->iov_len < auio.uio_resid) { +#if 0 + /* Cannot happen iov_len is unsigned */ + if (iov->iov_len < 0) { error = EINVAL; goto done; } - +#endif auio.uio_resid += iov->iov_len; + if (auio.uio_resid < 0) { + error = EINVAL; + goto done; + } iov++; } #ifdef KTRACE @@ -331,12 +337,18 @@ sys_writev(p, v, retval) goto done; auio.uio_resid = 0; for (i = 0; i < SCARG(uap, iovcnt); i++) { - if (auio.uio_resid + iov->iov_len < auio.uio_resid) { +#if 0 + /* Cannot happen iov_len is unsigned */ + if (iov->iov_len < 0) { error = EINVAL; goto done; } - +#endif auio.uio_resid += iov->iov_len; + if (auio.uio_resid < 0) { + error = EINVAL; + goto done; + } iov++; } #ifdef KTRACE diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index b4f48d76604..1823a253d43 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_pipe.c,v 1.6 1997/10/06 15:12:29 csapuntz Exp $ */ +/* $OpenBSD: sys_pipe.c,v 1.7 1997/10/06 20:20:02 deraadt Exp $ */ /* * Copyright (c) 1996 John S. Dyson @@ -77,7 +77,7 @@ #include <vm/vm.h> #include <vm/vm_prot.h> #include <vm/vm_param.h> -#include <sys/lock.h> +#include <vm/lock.h> #include <vm/vm_object.h> #include <vm/vm_kern.h> #include <vm/vm_extern.h> diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 9a593842688..9fe1894c125 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.28 1997/10/06 15:12:31 csapuntz Exp $ */ +/* $OpenBSD: tty.c,v 1.29 1997/10/06 20:20:04 deraadt Exp $ */ /* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */ /*- @@ -812,9 +812,9 @@ ttioctl(tp, cmd, data, flag, p) error = namei(&nid); if (error) return (error); - vn_lock(nid.ni_vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(nid.ni_vp); error = VOP_ACCESS(nid.ni_vp, VREAD, p->p_ucred, p); - VOP_UNLOCK(nid.ni_vp, 0, p); + VOP_UNLOCK(nid.ni_vp); vrele(nid.ni_vp); if (error) return (error); diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c index 0f70fcbda85..61360e34849 100644 --- a/sys/kern/tty_tty.c +++ b/sys/kern/tty_tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty_tty.c,v 1.4 1997/10/06 15:12:32 csapuntz Exp $ */ +/* $OpenBSD: tty_tty.c,v 1.5 1997/10/06 20:20:05 deraadt Exp $ */ /* $NetBSD: tty_tty.c,v 1.13 1996/03/30 22:24:46 christos Exp $ */ /*- @@ -63,7 +63,7 @@ cttyopen(dev, flag, mode, p) if (ttyvp == NULL) return (ENXIO); - vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(ttyvp); #ifdef PARANOID /* * Since group is tty and mode is 620 on most terminal lines @@ -78,7 +78,7 @@ cttyopen(dev, flag, mode, p) if (!error) #endif /* PARANOID */ error = VOP_OPEN(ttyvp, flag, NOCRED, p); - VOP_UNLOCK(ttyvp, 0, p); + VOP_UNLOCK(ttyvp); return (error); } @@ -89,15 +89,14 @@ cttyread(dev, uio, flag) struct uio *uio; int flag; { - struct proc *p = uio->uio_procp; register struct vnode *ttyvp = cttyvp(uio->uio_procp); int error; if (ttyvp == NULL) return (EIO); - vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(ttyvp); error = VOP_READ(ttyvp, uio, flag, NOCRED); - VOP_UNLOCK(ttyvp, 0, p); + VOP_UNLOCK(ttyvp); return (error); } @@ -108,15 +107,14 @@ cttywrite(dev, uio, flag) struct uio *uio; int flag; { - struct proc *p = uio->uio_procp; register struct vnode *ttyvp = cttyvp(uio->uio_procp); int error; if (ttyvp == NULL) return (EIO); - vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(ttyvp); error = VOP_WRITE(ttyvp, uio, flag, NOCRED); - VOP_UNLOCK(ttyvp, 0, p); + VOP_UNLOCK(ttyvp); return (error); } diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 58e0fcc5bad..5687fbc0ded 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.5 1997/10/06 15:12:33 csapuntz Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.6 1997/10/06 20:20:06 deraadt Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -427,7 +427,7 @@ unp_bind(unp, nam, p) vp->v_socket = unp->unp_socket; unp->unp_vnode = vp; unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL); - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (0); } diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index c8e596db9a9..87381210bcf 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_bio.c,v 1.16 1997/10/06 15:12:35 csapuntz Exp $ */ +/* $OpenBSD: vfs_bio.c,v 1.17 1997/10/06 20:20:07 deraadt Exp $ */ /* $NetBSD: vfs_bio.c,v 1.44 1996/06/11 11:15:36 pk Exp $ */ /*- @@ -63,8 +63,6 @@ #include <vm/vm.h> -#include <miscfs/specfs/specdev.h> - /* Macros to clear/set/test flags. */ #define SET(t, f) (t) |= (f) #define CLR(t, f) (t) &= ~(f) @@ -96,7 +94,6 @@ u_long bufhash; TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES]; int needbuffer; -struct bio_ops bioops; /* * Insq/Remq for the buffer free lists. @@ -142,6 +139,7 @@ bufinit() register int i; int base, residual; + TAILQ_INIT(&bdirties); for (dp = bufqueues; dp < &bufqueues[BQUEUES]; dp++) TAILQ_INIT(dp); bufhashtbl = hashinit(nbuf, M_CACHE, &bufhash); @@ -155,7 +153,6 @@ bufinit() bp->b_wcred = NOCRED; bp->b_vnbufs.le_next = NOLIST; bp->b_data = buffers + i * MAXBSIZE; - LIST_INIT(&bp->b_dep); if (i < residual) bp->b_bufsize = (base + 1) * CLBYTES; else @@ -281,7 +278,7 @@ int bwrite(bp) struct buf *bp; { - int rv, async, wasdelayed, s; + int rv, sync, wasdelayed, s; /* * Remember buffer type, to switch on it later. If the write was @@ -290,28 +287,34 @@ bwrite(bp) * XXX note that this relies on delayed tape writes being converted * to async, not sync writes (which is safe, but ugly). */ - async = ISSET(bp->b_flags, B_ASYNC); - if (!async && bp->b_vp && bp->b_vp->v_mount && + sync = !ISSET(bp->b_flags, B_ASYNC); + if (sync && bp->b_vp && bp->b_vp->v_mount && ISSET(bp->b_vp->v_mount->mnt_flag, MNT_ASYNC)) { bdwrite(bp); return (0); } wasdelayed = ISSET(bp->b_flags, B_DELWRI); CLR(bp->b_flags, (B_READ | B_DONE | B_ERROR | B_DELWRI)); - - s = splbio(); - /* - * If not synchronous, pay for the I/O operation and make - * sure the buf is on the correct vnode queue. We have - * to do this now, because if we don't, the vnode may not - * be properly notified that its I/O has completed. + * If this was a delayed write, remove it from the + * list of dirty blocks now */ if (wasdelayed) - reassignbuf(bp, bp->b_vp); - else - curproc->p_stats->p_ru.ru_oublock++; - + TAILQ_REMOVE(&bdirties, bp, b_synclist); + + s = splbio(); + if (!sync) { + /* + * If not synchronous, pay for the I/O operation and make + * sure the buf is on the correct vnode queue. We have + * to do this now, because if we don't, the vnode may not + * be properly notified that its I/O has completed. + */ + if (wasdelayed) + reassignbuf(bp, bp->b_vp); + else + curproc->p_stats->p_ru.ru_oublock++; + } /* Initiate disk write. Make sure the appropriate party is charged. */ bp->b_vp->v_numoutput++; @@ -319,18 +322,31 @@ bwrite(bp) SET(bp->b_flags, B_WRITEINPROG); VOP_STRATEGY(bp); - if (async) - return (0); + if (sync) { + /* + * If I/O was synchronous, wait for it to complete. + */ + rv = biowait(bp); - /* - * If I/O was synchronous, wait for it to complete. - */ - rv = biowait(bp); + /* + * Pay for the I/O operation, if it's not been paid for, and + * make sure it's on the correct vnode queue. (async operatings + * were payed for above.) + */ + s = splbio(); + if (wasdelayed) + reassignbuf(bp, bp->b_vp); + else + curproc->p_stats->p_ru.ru_oublock++; + splx(s); - /* Release the buffer. */ - brelse(bp); + /* Release the buffer. */ + brelse(bp); - return (rv); + return (rv); + } else { + return (0); + } } int @@ -366,10 +382,23 @@ bdwrite(bp) * (3) Make sure it's on its vnode's correct block list, * (4) If a buffer is rewritten, move it to end of dirty list */ + bp->b_synctime = time.tv_sec + 30; if (!ISSET(bp->b_flags, B_DELWRI)) { + /* + * Add the buffer to the list of dirty blocks. + * If it is the first entry on the list, schedule + * a timeout to flush it to disk + */ + TAILQ_INSERT_TAIL(&bdirties, bp, b_synclist); + if (bdirties.tqh_first == bp) { + untimeout((void (*)__P((void *)))wakeup, + &bdirties); /* XXX */ + timeout((void (*)__P((void *)))wakeup, + &bdirties, 30 * hz); + } SET(bp->b_flags, B_DELWRI); - reassignbuf(bp, bp->b_vp); curproc->p_stats->p_ru.ru_oublock++; /* XXX */ + reassignbuf(bp, bp->b_vp); } /* If this is a tape block, write the block now. */ @@ -397,17 +426,142 @@ bawrite(bp) VOP_BWRITE(bp); } +/* + * Write out dirty buffers if they have been on the dirty + * list for more than 30 seconds; scan for such buffers + * once a second. + */ void -bdirty(bp) - struct buf *bp; +vn_update() { - struct proc *p = curproc; /* XXX */ + struct mount *mp, *nmp; + struct timespec ts; + struct vnode *vp; + struct buf *bp; + int async, s; - if (ISSET(bp->b_flags, B_DELWRI) == 0) { - SET(bp->b_flags, B_DELWRI); - reassignbuf(bp, bp->b_vp); - if (p) - p->p_stats->p_ru.ru_oublock++; + /* + * In case any buffers got scheduled for write before the + * process got started (should never happen) + */ + untimeout((void (*)__P((void *)))wakeup, + &bdirties); + for (;;) { + s = splbio(); + /* + * Schedule a wakeup when the next buffer is to + * be flushed to disk. If no buffers are enqueued, + * a wakeup will be scheduled at the time a new + * buffer is enqueued + */ + if ((bp = bdirties.tqh_first) != NULL) { + untimeout((void (*)__P((void *)))wakeup, + &bdirties); /* XXX */ + timeout((void (*)__P((void *)))wakeup, + &bdirties, (bp->b_synctime - time.tv_sec) * hz); + } + tsleep(&bdirties, PZERO - 1, "dirty", 0); + /* + * Walk the dirty block list, starting an asyncroneous + * write of any block that has timed out + */ + while ((bp = bdirties.tqh_first) != NULL && + bp->b_synctime <= time.tv_sec) { + /* + * If the block is currently busy (perhaps being + * written), move it to the end of the dirty list + * and go to the next block + */ + if (ISSET(bp->b_flags, B_BUSY)) { + TAILQ_REMOVE(&bdirties, bp, b_synclist); + TAILQ_INSERT_TAIL(&bdirties, bp, b_synclist); + bp->b_synctime = time.tv_sec + 30; + continue; + } + /* + * Remove the block from the per-vnode dirty + * list and mark it as busy + */ + bremfree(bp); + SET(bp->b_flags, B_BUSY); + splx(s); + /* + * Start an asyncroneous write of the buffer. + * Note that this will also remove the buffer + * from the dirty list + */ + bawrite(bp); + s = splbio(); + } + splx(s); + /* + * We also need to flush out modified vnodes + */ + for (mp = mountlist.cqh_last; + mp != (void *)&mountlist; + mp = nmp) { + /* + * Get the next pointer in case we hang of vfs_busy() + * while being unmounted + */ + nmp = mp->mnt_list.cqe_prev; + /* + * The lock check below is to avoid races with mount + * and unmount + */ + if ((mp->mnt_flag & (MNT_MLOCK | MNT_RDONLY | MNT_MPBUSY)) == 0 && + !vfs_busy(mp)) { + /* + * Turn off the file system async flag until + * we are done writing out vnodes + */ + async = mp->mnt_flag & MNT_ASYNC; + mp->mnt_flag &= ~MNT_ASYNC; + /* + * Walk the vnode list for the file system, + * writing each modified vnode out + */ +loop: + for (vp = mp->mnt_vnodelist.lh_first; + vp != NULL; + vp = vp->v_mntvnodes.le_next) { + /* + * If the vnode is no longer associated + * with the file system in question, skip + * it + */ + if (vp->v_mount != mp) + goto loop; + /* + * If the vnode is currently locked, + * ignore it + */ + if (VOP_ISLOCKED(vp)) + continue; + /* + * Lock the vnode, start a write and + * release the vnode + */ + if (vget(vp, 1)) + goto loop; + TIMEVAL_TO_TIMESPEC(&time, &ts); + VOP_UPDATE(vp, &ts, &ts, 0); + vput(vp); + } + /* + * Restore the file system async flag if it + * were previously set for this file system + */ + mp->mnt_flag |= async; + /* + * Get the next pointer again as the next + * file system might have been unmounted + * while we were flushing vnodes + */ + nmp = mp->mnt_list.cqe_prev; + vfs_unbusy(mp); + } + } } } @@ -422,6 +576,18 @@ brelse(bp) struct bqueues *bufq; int s; + /* Wake up any processes waiting for any buffer to become free. */ + if (needbuffer) { + needbuffer = 0; + wakeup(&needbuffer); + } + + /* Wake up any proceeses waiting for _this_ buffer to become free. */ + if (ISSET(bp->b_flags, B_WANTED)) { + CLR(bp->b_flags, B_WANTED); + wakeup(bp); + } + /* Block disk interrupts. */ s = splbio(); @@ -456,14 +622,11 @@ brelse(bp) * If it's invalid or empty, dissociate it from its vnode * and put on the head of the appropriate queue. */ - if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate) { - (*bioops.io_deallocate)(bp); - } - CLR(bp->b_flags, B_DELWRI); - if (bp->b_vp) { - reassignbuf(bp, bp->b_vp); + if (bp->b_vp) brelvp(bp); - } + if (ISSET(bp->b_flags, B_DELWRI)) + TAILQ_REMOVE(&bdirties, bp, b_synclist); + CLR(bp->b_flags, B_DELWRI); if (bp->b_bufsize <= 0) /* no data */ bufq = &bufqueues[BQ_EMPTY]; @@ -494,18 +657,6 @@ already_queued: /* Allow disk interrupts. */ splx(s); - - /* Wake up any processes waiting for any buffer to become free. */ - if (needbuffer) { - needbuffer = 0; - wakeup(&needbuffer); - } - - /* Wake up any proceeses waiting for _this_ buffer to become free. */ - if (ISSET(bp->b_flags, B_WANTED)) { - CLR(bp->b_flags, B_WANTED); - wakeup(bp); - } } /* @@ -655,7 +806,7 @@ allocbuf(bp, size) /* find a buffer */ while ((nbp = getnewbuf(0, 0)) == NULL) ; - SET(nbp->b_flags, B_INVAL); + SET(nbp->b_flags, B_INVAL); binshash(nbp, &invalhash); /* and steal its pages, up to the amount we need */ @@ -724,16 +875,16 @@ getnewbuf(slpflag, slptimeo) start: s = splbio(); - if ((bp = bufqueues[BQ_AGE].tqh_first) == NULL && - (bp = bufqueues[BQ_LRU].tqh_first) == NULL) { + if ((bp = bufqueues[BQ_AGE].tqh_first) != NULL || + (bp = bufqueues[BQ_LRU].tqh_first) != NULL) { + bremfree(bp); + } else { /* wait for a free buffer of any kind */ needbuffer = 1; tsleep(&needbuffer, slpflag|(PRIBIO+1), "getnewbuf", slptimeo); splx(s); return (0); - } - - bremfree(bp); + } if (ISSET(bp->b_flags, B_VFLUSH)) { /* @@ -765,12 +916,8 @@ start: /* disassociate us from our vnode, if we had one... */ if (bp->b_vp) brelvp(bp); - splx(s); - if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate) - (*bioops.io_deallocate)(bp); - /* clear out various other fields */ bp->b_flags = B_BUSY; bp->b_dev = NODEV; @@ -815,9 +962,7 @@ biowait(bp) if (ISSET(bp->b_flags, B_EINTR)) { CLR(bp->b_flags, B_EINTR); return (EINTR); - } - - if (ISSET(bp->b_flags, B_ERROR)) + } else if (ISSET(bp->b_flags, B_ERROR)) return (bp->b_error ? bp->b_error : EIO); else return (0); @@ -847,18 +992,13 @@ biodone(bp) panic("biodone already"); SET(bp->b_flags, B_DONE); /* note that it's done */ - if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_complete) - (*bioops.io_complete)(bp); + if (!ISSET(bp->b_flags, B_READ)) /* wake up reader */ + vwakeup(bp); if (ISSET(bp->b_flags, B_CALL)) { /* if necessary, call out */ CLR(bp->b_flags, B_CALL); /* but note callout done */ (*bp->b_iodone)(bp); - } - - if (!ISSET(bp->b_flags, B_READ)) /* wake up reader */ - vwakeup(bp); - - if (ISSET(bp->b_flags, B_ASYNC)) /* if async, release it */ + } else if (ISSET(bp->b_flags, B_ASYNC)) /* if async, release it */ brelse(bp); else { /* or just wakeup the buffer */ CLR(bp->b_flags, B_WANTED); diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index 87b024600bc..b1017f6f21c 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_cluster.c,v 1.9 1997/10/06 15:12:36 csapuntz Exp $ */ +/* $OpenBSD: vfs_cluster.c,v 1.10 1997/10/06 20:20:08 deraadt Exp $ */ /* $NetBSD: vfs_cluster.c,v 1.12 1996/04/22 01:39:05 christos Exp $ */ /*- @@ -48,6 +48,15 @@ #include <vm/vm.h> +#ifdef DEBUG +#include <sys/sysctl.h> +int doreallocblks = 0; +struct ctldebug debug13 = { "doreallocblks", &doreallocblks }; +#else +/* XXX for cluster_write */ +#define doreallocblks 0 +#endif + /* * Local declarations */ @@ -509,7 +518,8 @@ cluster_write(bp, filesize) * Otherwise try reallocating to make it sequential. */ cursize = vp->v_lastw - vp->v_cstart + 1; - if ((lbn + 1) * bp->b_bcount != filesize || + if (!doreallocblks || + (lbn + 1) * bp->b_bcount != filesize || lbn != vp->v_lastw + 1 || vp->v_clen <= cursize) { cluster_wbuild(vp, NULL, bp->b_bcount, vp->v_cstart, cursize, lbn); @@ -698,14 +708,13 @@ redo: panic("Clustered write to wrong blocks"); } - if (LIST_FIRST(&tbp->b_dep) != NULL && bioops.io_start) - (*bioops.io_start)(tbp); - pagemove(tbp->b_data, cp, size); bp->b_bcount += size; bp->b_bufsize += size; tbp->b_bufsize -= size; + if (tbp->b_flags & B_DELWRI) + TAILQ_REMOVE(&bdirties, tbp, b_synclist); tbp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI); /* * We might as well AGE the buffer here; it's either empty, or diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c index 527450f20e5..3e3ae79a7d3 100644 --- a/sys/kern/vfs_conf.c +++ b/sys/kern/vfs_conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_conf.c,v 1.6 1997/10/06 15:12:37 csapuntz Exp $ */ +/* $OpenBSD: vfs_conf.c,v 1.7 1997/10/06 20:20:09 deraadt Exp $ */ /* $NetBSD: vfs_conf.c,v 1.21.4.1 1995/11/01 00:06:26 jtc Exp $ */ /* @@ -40,28 +40,6 @@ #include <sys/mount.h> #include <sys/vnode.h> -#ifdef FFS -#include <ufs/ufs/quota.h> -#include <ufs/ufs/inode.h> -#include <ufs/ffs/ffs_extern.h> -#endif - -#ifdef CD9660 -#include <isofs/cd9660/iso.h> -#endif - -#ifdef MFS -#include <ufs/mfs/mfs_extern.h> -#endif - -#ifdef NFSCLIENT -#include <nfs/rpcv2.h> -#include <nfs/nfsproto.h> -#include <nfs/nfsnode.h> -#include <nfs/nfs.h> -#include <nfs/nfsmount.h> -#endif - /* * These define the root filesystem and device. */ @@ -72,8 +50,6 @@ struct vnode *rootvnode; * Set up the filesystem operations for vnodes. * The types are defined in mount.h. */ - - #ifdef FFS extern struct vfsops ffs_vfsops; #endif @@ -139,102 +115,107 @@ extern struct vfsops ext2fs_vfsops; #endif /* - * Set up the filesystem operations for vnodes. + * XXX ORDERING MATTERS, for COMPAT_09. when that goes away, + * empty slots can go away. */ -static struct vfsconf vfsconflist[] = { - - /* Fast Filesystem */ +struct vfsops *vfssw[] = { + NULL, /* 0 = MOUNT_NONE */ #ifdef FFS - { &ffs_vfsops, "ffs", 1, 0, MNT_LOCAL, ffs_mountroot, NULL }, + &ffs_vfsops, /* 1 = MOUNT_FFS */ +#else + NULL, #endif - - /* Log-based Filesystem */ -#ifdef LFS - { &lfs_vfsops, "lfs", 5, 0, MNT_LOCAL, lfs_mountroot, NULL }, +#ifdef NFSCLIENT + &nfs_vfsops, /* 2 = MOUNT_NFS */ +#else + NULL, #endif - - /* Memory-based Filesystem */ #ifdef MFS - { &mfs_vfsops, "mfs", 3, 0, MNT_LOCAL, mfs_mountroot, NULL }, + &mfs_vfsops, /* 3 = MOUNT_MFS */ +#else + NULL, #endif - - /* ISO9660 (aka CDROM) Filesystem */ -#ifdef CD9660 - { &cd9660_vfsops, "cd9660", 14, 0, MNT_LOCAL, cd9660_mountroot, NULL }, -#endif - - /* MSDOS Filesystem */ #ifdef MSDOSFS - { &msdosfs_vfsops, "msdos", 4, 0, MNT_LOCAL, NULL, NULL }, + &msdosfs_vfsops, /* 4 = MOUNT_MSDOS */ +#else + NULL, #endif - - /* AmigaDOS Filesystem */ -#ifdef ADOSFS - { &adosfs_vfsops, "adosfs", 16, 0, MNT_LOCAL, NULL, NULL }, +#ifdef LFS + &lfs_vfsops, /* 5 = MOUNT_LFS */ +#else + NULL, #endif - - /* Sun-compatible Network Filesystem */ -#ifdef NFSCLIENT - { &nfs_vfsops, "nfs", 2, 0, 0, nfs_mountroot, NULL }, + NULL, /* 6 = MOUNT_LOFS */ +#ifdef FDESC + &fdesc_vfsops, /* 7 = MOUNT_FDESC */ +#else + NULL, #endif - - /* Andrew Filesystem */ -#ifdef AFS - { &afs_vfsops, "andrewfs", 13, 0, 0, afs_mountroot, NULL }, +#ifdef PORTAL + &portal_vfsops, /* 8 = MOUNT_PORTAL */ +#else + NULL, +#endif +#ifdef NULLFS + &null_vfsops, /* 9 = MOUNT_NULL */ +#else + NULL, +#endif +#ifdef UMAPFS + &umap_vfsops, /* 10 = MOUNT_UMAP */ +#else + NULL, +#endif +#ifdef KERNFS + &kernfs_vfsops, /* 11 = MOUNT_KERNFS */ +#else + NULL, #endif - - /* /proc Filesystem */ #ifdef PROCFS - { &procfs_vfsops, "procfs", 12, 0, 0, NULL, NULL }, + &procfs_vfsops, /* 12 = MOUNT_PROCFS */ +#else + NULL, #endif - - /* Loopback (Minimal) Filesystem Layer */ -#ifdef NULLFS - { &null_vfsops, "loopback", 9, 0, 0, NULL, NULL }, +#ifdef AFS + &afs_vfsops, /* 13 = MOUNT_AFS */ +#else + NULL, #endif - - /* Union (translucent) Filesystem */ -#ifdef UNION - { &union_vfsops, "union", 15, 0, 0, NULL, NULL }, +#ifdef CD9660 + &cd9660_vfsops, /* 14 = MOUNT_ISOFS */ +#else + NULL, #endif - - /* User/Group Identifer Remapping Filesystem */ -#ifdef UMAPFS - { &umap_vfsops, "umap", 10, 0, 0, NULL, NULL }, +#ifdef UNION + &union_vfsops, /* 15 = MOUNT_UNION */ +#else + NULL, #endif - - /* Portal Filesystem */ -#ifdef PORTAL - { &portal_vfsops, "portal", 8, 0, 0, NULL, NULL }, +#ifdef ADOSFS + &adosfs_vfsops, /* 16 = MOUNT_ADOSFS */ +#else + NULL, #endif - - /* File Descriptor Filesystem */ -#ifdef FDESC - { &fdesc_vfsops, "fdesc", 7, 0, 0, NULL, NULL }, +#ifdef EXT2FS + &ext2fs_vfsops, /* 17 = MOUNT_EXT2FS */ +#else + NULL, #endif - - /* Kernel Information Filesystem */ -#ifdef KERNFS - { &kernfs_vfsops, "kernfs", 11, 0, 0, NULL, NULL }, +#ifdef LKM /* for LKM's. add new FS's before these */ + NULL, + NULL, + NULL, + NULL, #endif - + 0 }; - - -/* - * Initially the size of the list, vfs_init will set maxvfsconf - * to the highest defined type number. - */ -int maxvfsconf = sizeof(vfsconflist) / sizeof (struct vfsconf); -struct vfsconf *vfsconf = vfsconflist; - +int nvfssw = sizeof(vfssw) / sizeof(vfssw[0]); /* * vfs_opv_descs enumerates the list of vnode classes, each with it's own * vnode operation vector. It is consulted at system boot to build operation * vectors. It is NULL terminated. */ -extern struct vnodeopv_desc sync_vnodeop_opv_desc; extern struct vnodeopv_desc ffs_vnodeop_opv_desc; extern struct vnodeopv_desc ffs_specop_opv_desc; extern struct vnodeopv_desc ffs_fifoop_opv_desc; @@ -265,7 +246,6 @@ extern struct vnodeopv_desc ext2fs_specop_opv_desc; extern struct vnodeopv_desc ext2fs_fifoop_opv_desc; struct vnodeopv_desc *vfs_opv_descs[] = { - &sync_vnodeop_opv_desc, #ifdef FFS &ffs_vnodeop_opv_desc, &ffs_specop_opv_desc, diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index a10e5a3ff41..f956458fa17 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_init.c,v 1.5 1997/10/06 15:12:39 csapuntz Exp $ */ +/* $OpenBSD: vfs_init.c,v 1.6 1997/10/06 20:20:10 deraadt Exp $ */ /* $NetBSD: vfs_init.c,v 1.6 1996/02/09 19:00:58 christos Exp $ */ /* @@ -243,8 +243,7 @@ struct vattr va_null; void vfsinit() { - struct vfsconf *vfsp; - int i, maxtypenum; + struct vfsops **vfsp; /* * Initialize the vnode table @@ -263,15 +262,9 @@ vfsinit() * Initialize each file system type. */ vattr_null(&va_null); - maxtypenum = 0; - - for (vfsp = vfsconf, i = 1; i <= maxvfsconf; i++, vfsp++) { - if (i < maxvfsconf) - vfsp->vfc_next = vfsp + 1; - if (maxtypenum <= vfsp->vfc_typenum) - maxtypenum = vfsp->vfc_typenum + 1; - (*vfsp->vfc_vfsops->vfs_init)(vfsp); - } - /* next vfc_typenum to be used */ - maxvfsconf = maxtypenum; + for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) { + if (*vfsp == NULL) + continue; + (*(*vfsp)->vfs_init)(); + } } diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index aa86b97412e..4fee676eeaa 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_lookup.c,v 1.9 1997/10/06 15:12:40 csapuntz Exp $ */ +/* $OpenBSD: vfs_lookup.c,v 1.10 1997/10/06 20:20:11 deraadt Exp $ */ /* $NetBSD: vfs_lookup.c,v 1.17 1996/02/09 19:00:59 christos Exp $ */ /* @@ -88,7 +88,6 @@ namei(ndp) struct uio auio; int error, linklen; struct componentname *cnp = &ndp->ni_cnd; - struct proc *p = cnp->cn_proc; ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; #ifdef DIAGNOSTIC @@ -165,7 +164,7 @@ namei(ndp) return (0); } if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) - VOP_UNLOCK(ndp->ni_dvp, 0, p); + VOP_UNLOCK(ndp->ni_dvp); if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { error = ELOOP; break; @@ -272,7 +271,7 @@ lookup(ndp) int error = 0; int slashes; struct componentname *cnp = &ndp->ni_cnd; - struct proc *p = cnp->cn_proc; + /* * Setup: break out flag bits into variables. */ @@ -286,7 +285,7 @@ lookup(ndp) cnp->cn_flags &= ~ISSYMLINK; dp = ndp->ni_startdir; ndp->ni_startdir = NULLVP; - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(dp); /* * If we have a leading string of slashes, remove them, and just make @@ -411,7 +410,7 @@ dirloop: dp = dp->v_mount->mnt_vnodecovered; vput(tdp); VREF(dp); - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(dp); } } @@ -420,7 +419,6 @@ dirloop: */ unionlookup: ndp->ni_dvp = dp; - ndp->ni_vp = NULL; if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) { #ifdef DIAGNOSTIC if (ndp->ni_vp != NULL) @@ -436,7 +434,7 @@ unionlookup: dp = dp->v_mount->mnt_vnodecovered; vput(tdp); VREF(dp); - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(dp); goto unionlookup; } @@ -493,11 +491,12 @@ unionlookup: */ while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && (cnp->cn_flags & NOCROSSMOUNT) == 0) { - if (vfs_busy(mp, 0, 0, p)) + if (mp->mnt_flag & MNT_MLOCK) { + mp->mnt_flag |= MNT_MWAIT; + sleep((caddr_t)mp, PVFS); continue; - error = VFS_ROOT(mp, &tdp); - vfs_unbusy(mp, p); - if (error) + } + if ((error = VFS_ROOT(dp->v_mountedhere, &tdp)) != 0) goto bad2; vput(dp); ndp->ni_vp = dp = tdp; @@ -559,12 +558,12 @@ terminal: vrele(ndp->ni_dvp); } if ((cnp->cn_flags & LOCKLEAF) == 0) - VOP_UNLOCK(dp, 0, p); + VOP_UNLOCK(dp); return (0); bad2: if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) - VOP_UNLOCK(ndp->ni_dvp, 0, p); + VOP_UNLOCK(ndp->ni_dvp); vrele(ndp->ni_dvp); bad: vput(dp); @@ -580,7 +579,6 @@ relookup(dvp, vpp, cnp) struct vnode *dvp, **vpp; struct componentname *cnp; { - struct proc *p = cnp->cn_proc; register struct vnode *dp = 0; /* the directory we are searching */ int docache; /* == 0 do not cache last component */ int wantparent; /* 1 => wantparent or lockparent flag */ @@ -602,7 +600,7 @@ relookup(dvp, vpp, cnp) rdonly = cnp->cn_flags & RDONLY; cnp->cn_flags &= ~ISSYMLINK; dp = dvp; - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(dp); /* dirloop: */ /* @@ -696,17 +694,15 @@ relookup(dvp, vpp, cnp) if (!wantparent) vrele(dvp); if ((cnp->cn_flags & LOCKLEAF) == 0) - VOP_UNLOCK(dp, 0, p); + VOP_UNLOCK(dp); return (0); bad2: if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) - VOP_UNLOCK(dvp, 0, p); + VOP_UNLOCK(dvp); vrele(dvp); bad: vput(dp); *vpp = NULL; return (error); } - - diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index f265b15051d..c593ef0f9aa 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_subr.c,v 1.11 1997/10/06 15:12:42 csapuntz Exp $ */ +/* $OpenBSD: vfs_subr.c,v 1.12 1997/10/06 20:20:12 deraadt Exp $ */ /* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */ /* @@ -51,7 +51,6 @@ #include <sys/mount.h> #include <sys/time.h> #include <sys/fcntl.h> -#include <sys/kernel.h> #include <sys/vnode.h> #include <sys/stat.h> #include <sys/namei.h> @@ -89,28 +88,8 @@ int suid_clear = 1; /* 1 => clear SUID / SGID on owner change */ LIST_REMOVE(bp, b_vnbufs); \ (bp)->b_vnbufs.le_next = NOLIST; \ } - -struct freelst vnode_hold_list; /* list of vnodes referencing buffers */ -struct freelst vnode_free_list; /* vnode free list */ - +TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ struct mntlist mountlist; /* mounted filesystem list */ -struct simplelock mountlist_slock; -static struct simplelock mntid_slock; -struct simplelock mntvnode_slock; -struct simplelock vnode_free_list_slock; -static struct simplelock spechash_slock; - -/* - * The workitem queue. - */ -#define SYNCER_MAXDELAY 32 -int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */ -time_t syncdelay = 30; /* time to delay syncing vnodes */ - -static int syncer_delayno = 0; -static long syncer_mask; -LIST_HEAD(synclist, vnode); -static struct synclist *syncer_workitem_pending; int vfs_lock __P((struct mount *)); void vfs_unlock __P((struct mount *)); @@ -128,16 +107,15 @@ int bdevvp __P((dev_t, struct vnode **)); int cdevvp __P((dev_t, struct vnode **)); int getdevvp __P((dev_t, struct vnode **, enum vtype)); struct vnode *checkalias __P((struct vnode *, dev_t, struct mount *)); +int vget __P((struct vnode *, int)); void vref __P((struct vnode *)); void vput __P((struct vnode *)); void vrele __P((struct vnode *)); -int vunref __P((struct vnode *)); void vhold __P((struct vnode *)); void holdrele __P((struct vnode *)); int vflush __P((struct mount *, struct vnode *, int)); void vgoneall __P((struct vnode *)); void vgone __P((struct vnode *)); -void vgonel __P((struct vnode *, struct proc *)); int vcount __P((struct vnode *)); void vprint __P((char *, struct vnode *)); int vfs_mountedon __P((struct vnode *)); @@ -148,10 +126,10 @@ int vaccess __P((mode_t, uid_t, gid_t, mode_t, struct ucred *)); void vfs_unmountall __P((void)); void vfs_shutdown __P((void)); -int vfs_hang_addrlist __P((struct mount *, struct netexport *, +static int vfs_hang_addrlist __P((struct mount *, struct netexport *, struct export_args *)); -int vfs_free_netcred __P((struct radix_node *, void *)); -void vfs_free_addrlist __P((struct netexport *)); +static int vfs_free_netcred __P((struct radix_node *, void *)); +static void vfs_free_addrlist __P((struct netexport *)); #ifdef DEBUG void printlockedvnodes __P((void)); @@ -164,191 +142,124 @@ void vntblinit() { - simple_lock_init(&mntvnode_slock); - simple_lock_init(&mntid_slock); - simple_lock_init(&spechash_slock); - TAILQ_INIT(&vnode_hold_list); TAILQ_INIT(&vnode_free_list); - simple_lock_init(&vnode_free_list_slock); CIRCLEQ_INIT(&mountlist); - /* - * Initialize the filesystem syncer. - */ - syncer_workitem_pending = hashinit(syncer_maxdelay, M_VNODE, - &syncer_mask); - syncer_maxdelay = syncer_mask + 1; - } - /* - * Mark a mount point as busy. Used to synchornize access and to delay - * unmounting. Interlock is not released n failure. + * Lock a filesystem. + * Used to prevent access to it while mounting and unmounting. */ - int -vfs_busy(mp, flags, interlkp, p) - struct mount *mp; - int flags; - struct simplelock *interlkp; - struct proc *p; +vfs_lock(mp) + register struct mount *mp; { - int lkflags; - if (mp->mnt_flag & MNT_UNMOUNT) { - if (flags & LK_NOWAIT) - return (ENOENT); + while (mp->mnt_flag & MNT_MLOCK) { mp->mnt_flag |= MNT_MWAIT; - if (interlkp) - simple_unlock(interlkp); - /* - * Since all busy locks are shared except the exclusive - * lock granted when unmounting, the only place that a - * wakeup needs to be done is at the release of the - * exclusive lock at the end of dounmount. - */ - sleep((caddr_t)mp, PVFS); - if (interlkp) - simple_lock(interlkp); - return (ENOENT); + tsleep((caddr_t)mp, PVFS, "vfslock", 0); } - lkflags = LK_SHARED; - if (interlkp) - lkflags |= LK_INTERLOCK; - if (lockmgr(&mp->mnt_lock, lkflags, interlkp, p)) - panic("vfs_busy: unexpected lock failure"); - return (0); + mp->mnt_flag |= MNT_MLOCK; + return (0); } - /* - * Free a busy file system + * Unlock a locked filesystem. + * Panic if filesystem is not locked. */ void -vfs_unbusy(mp, p) - struct mount *mp; - struct proc *p; +vfs_unlock(mp) + register struct mount *mp; { - lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, p); + + if ((mp->mnt_flag & MNT_MLOCK) == 0) + panic("vfs_unlock: not locked"); + mp->mnt_flag &= ~MNT_MLOCK; + if (mp->mnt_flag & MNT_MWAIT) { + mp->mnt_flag &= ~MNT_MWAIT; + wakeup((caddr_t)mp); + } } /* - * Lookup a filesystem type, and if found allocate and initialize - * a mount structure for it. - * - * Devname is usually updated by mount(8) after booting. + * Mark a mount point as busy. + * Used to synchronize access and to delay unmounting. */ - int -vfs_rootmountalloc(fstypename, devname, mpp) - char *fstypename; - char *devname; - struct mount **mpp; - { - struct proc *p = curproc; /* XXX */ - struct vfsconf *vfsp; - struct mount *mp; - - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (!strcmp(vfsp->vfc_name, fstypename)) - break; - if (vfsp == NULL) - return (ENODEV); - mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); - bzero((char *)mp, (u_long)sizeof(struct mount)); - lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); - (void)vfs_busy(mp, LK_NOWAIT, 0, p); - LIST_INIT(&mp->mnt_vnodelist); - mp->mnt_vfc = vfsp; - mp->mnt_op = vfsp->vfc_vfsops; - mp->mnt_flag = MNT_RDONLY; - mp->mnt_vnodecovered = NULLVP; - vfsp->vfc_refcount++; - mp->mnt_stat.f_type = vfsp->vfc_typenum; - mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; - strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); - mp->mnt_stat.f_mntonname[0] = '/'; - (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0); - *mpp = mp; - return (0); - } +vfs_busy(mp) + register struct mount *mp; +{ + + while(mp->mnt_flag & MNT_MPBUSY) { + mp->mnt_flag |= MNT_MPWANT; + tsleep((caddr_t)&mp->mnt_flag, PVFS, "vfsbusy", 0); + } + if (mp->mnt_flag & MNT_UNMOUNT) + return (1); + mp->mnt_flag |= MNT_MPBUSY; + return (0); +} /* - * Find an appropriate filesystem to use for the root. If a filesystem - * has not been preselected, walk through the list of known filesystems - * trying those that have mountroot routines, and try them until one - * works or we have tried them all. - */ -int -vfs_mountroot() + * Free a busy filesystem. + * Panic if filesystem is not busy. + */ +void +vfs_unbusy(mp) + register struct mount *mp; { - struct vfsconf *vfsp; - extern int (*mountroot)(void); - int error; - - if (mountroot != NULL) - return ((*mountroot)()); - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { - if (vfsp->vfc_mountroot == NULL) - continue; - if ((error = (*vfsp->vfc_mountroot)()) == 0) - return (0); - printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error); - } - return (ENODEV); + + if ((mp->mnt_flag & MNT_MPBUSY) == 0) + panic("vfs_unbusy: not busy"); + mp->mnt_flag &= ~MNT_MPBUSY; + if (mp->mnt_flag & MNT_MPWANT) { + mp->mnt_flag &= ~MNT_MPWANT; + wakeup((caddr_t)&mp->mnt_flag); + } } - + /* * Lookup a mount point by filesystem identifier. */ struct mount * -vfs_getvfs(fsid) +getvfs(fsid) fsid_t *fsid; { register struct mount *mp; - simple_lock(&mountlist_slock); for (mp = mountlist.cqh_first; mp != (void *)&mountlist; - mp = mp->mnt_list.cqe_next) { + mp = mp->mnt_list.cqe_next) if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] && - mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) { - simple_unlock(&mountlist_slock); + mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) return (mp); - } - } - simple_unlock(&mountlist_slock); return ((struct mount *)0); } - /* * Get a new unique fsid */ void -vfs_getnewfsid(mp) +getnewfsid(mp, mtype) struct mount *mp; + int mtype; { static u_short xxxfs_mntid; fsid_t tfsid; - int mtype; - simple_lock(&mntid_slock); - mtype = mp->mnt_vfc->vfc_typenum; - mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0); + mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + 11, 0); /* XXX */ mp->mnt_stat.f_fsid.val[1] = mtype; if (xxxfs_mntid == 0) ++xxxfs_mntid; - tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid); + tfsid.val[0] = makedev((nblkdev + mtype) & 0xff, xxxfs_mntid); tfsid.val[1] = mtype; if (mountlist.cqh_first != (void *)&mountlist) { - while (vfs_getvfs(&tfsid)) { + while (getvfs(&tfsid)) { tfsid.val[0]++; xxxfs_mntid++; } } mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; - simple_unlock(&mntid_slock); } /* @@ -407,56 +318,20 @@ getnewvnode(tag, mp, vops, vpp) int (**vops) __P((void *)); struct vnode **vpp; { - struct proc *p = curproc; /* XXX */ - struct freelst *listhd; - static int toggle; - struct vnode *vp; + register struct vnode *vp; #ifdef DIAGNOSTIC int s; #endif - /* - * We must choose whether to allocate a new vnode or recycle an - * existing one. The criterion for allocating a new one is that - * the total number of vnodes is less than the number desired or - * there are no vnodes on either free list. Generally we only - * want to recycle vnodes that have no buffers associated with - * them, so we look first on the vnode_free_list. If it is empty, - * we next consider vnodes with referencing buffers on the - * vnode_hold_list. The toggle ensures that half the time we - * will use a buffer from the vnode_hold_list, and half the time - * we will allocate a new one unless the list has grown to twice - * the desired size. We are reticent to recycle vnodes from the - * vnode_hold_list because we will lose the identity of all its - * referencing buffers. - */ - toggle ^= 1; - if (numvnodes > 2 * desiredvnodes) - toggle = 0; - - - simple_lock(&vnode_free_list_slock); - if ((numvnodes < desiredvnodes) || - ((TAILQ_FIRST(listhd = &vnode_free_list) == NULL) && - ((TAILQ_FIRST(listhd = &vnode_hold_list) == NULL) || toggle))) { - simple_unlock(&vnode_free_list_slock); + if ((vnode_free_list.tqh_first == NULL && + numvnodes < 2 * desiredvnodes) || + numvnodes < desiredvnodes) { vp = (struct vnode *)malloc((u_long)sizeof *vp, M_VNODE, M_WAITOK); bzero((char *)vp, sizeof *vp); numvnodes++; } else { - for (vp = TAILQ_FIRST(listhd); vp != NULLVP; - vp = TAILQ_NEXT(vp, v_freelist)) { - if (simple_lock_try(&vp->v_interlock)) - break; - } - /* - * Unless this is a bad time of the month, at most - * the first NCPUS items on the free list are - * locked, so this is close enough to being empty. - */ - if (vp == NULLVP) { - simple_unlock(&vnode_free_list_slock); + if ((vp = vnode_free_list.tqh_first) == NULL) { tablefull("vnode"); *vpp = 0; return (ENFILE); @@ -465,15 +340,12 @@ getnewvnode(tag, mp, vops, vpp) vprint("free vnode", vp); panic("free vnode isn't"); } - TAILQ_REMOVE(listhd, vp, v_freelist); + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); /* see comment on why 0xdeadb is set at end of vgone (below) */ - vp->v_flag |= VGONEHACK; - simple_unlock(&vnode_free_list_slock); + vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb; vp->v_lease = NULL; if (vp->v_type != VBAD) - vgonel(vp, p); - else - simple_unlock(&vp->v_interlock); + vgone(vp); #ifdef DIAGNOSTIC if (vp->v_data) { vprint("cleaned vnode", vp); @@ -513,19 +385,18 @@ insmntque(vp, mp) register struct vnode *vp; register struct mount *mp; { - simple_lock(&mntvnode_slock); + /* * Delete from old mount point vnode list, if on one. */ - if (vp->v_mount != NULL) LIST_REMOVE(vp, v_mntvnodes); /* * Insert into list of vnodes for the new mount point, if available. */ - if ((vp->v_mount = mp) != NULL) - LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes); - simple_unlock(&mntvnode_slock); + if ((vp->v_mount = mp) == NULL) + return; + LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes); } /* @@ -564,15 +435,14 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo) struct buf *nbp, *blist; int s, error; - if ((flags & V_SAVE) && vp->v_dirtyblkhd.lh_first != NULL) { + if (flags & V_SAVE) { if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) != 0) return (error); if (vp->v_dirtyblkhd.lh_first != NULL) panic("vinvalbuf: dirty bufs"); } for (;;) { - if ((blist = vp->v_cleanblkhd.lh_first) && - (flags & V_SAVEMETA)) + if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA) while (blist && blist->b_lblkno < 0) blist = blist->b_vnbufs.le_next; if (!blist && (blist = vp->v_dirtyblkhd.lh_first) && @@ -692,140 +562,30 @@ brelvp(bp) register struct buf *bp; { struct vnode *vp; - struct buf *wasdirty; - if ((vp = bp->b_vp) == (struct vnode *) 0) + if (bp->b_vp == (struct vnode *) 0) panic("brelvp: NULL"); /* * Delete from old vnode list, if on one. */ - wasdirty = vp->v_dirtyblkhd.lh_first; if (bp->b_vnbufs.le_next != NOLIST) bufremvn(bp); - if (wasdirty && LIST_FIRST(&vp->v_dirtyblkhd) == NULL) - LIST_REMOVE(vp, v_synclist); + vp = bp->b_vp; bp->b_vp = (struct vnode *) 0; HOLDRELE(vp); } /* - * The workitem queue. - * - * It is useful to delay writes of file data and filesystem metadata - * for tens of seconds so that quickly created and deleted files need - * not waste disk bandwidth being created and removed. To realize this, - * we append vnodes to a "workitem" queue. When running with a soft - * updates implementation, most pending metadata dependencies should - * not wait for more than a few seconds. Thus, mounted on block devices - * are delayed only about a half the time that file data is delayed. - * Similarly, directory updates are more critical, so are only delayed - * about a third the time that file data is delayed. Thus, there are - * SYNCER_MAXDELAY queues that are processed round-robin at a rate of - * one each second (driven off the filesystem syner process). The - * syncer_delayno variable indicates the next queue that is to be processed. - * Items that need to be processed soon are placed in this queue: - * - * syncer_workitem_pending[syncer_delayno] - * - * A delay of fifteen seconds is done by placing the request fifteen - * entries later in the queue: - * - * syncer_workitem_pending[(syncer_delayno + 15) & syncer_mask] - * - */ - -/* - * Add an item to the syncer work queue. - */ -void -vn_syncer_add_to_worklist(vp, delay) - struct vnode *vp; - int delay; -{ - int s, slot; - - s = splbio(); - if (delay > syncer_maxdelay - 2) - delay = syncer_maxdelay - 2; - slot = (syncer_delayno + delay) & syncer_mask; - LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist); - splx(s); -} - -/* - * System filesystem synchronizer daemon. - */ - -extern int lbolt; - -void -sched_sync(p) - struct proc *p; -{ - struct synclist *slp; - struct vnode *vp; - long starttime; - int s; - - for (;;) { - starttime = time.tv_sec; - - /* - * Push files whose dirty time has expired. - */ - s = splbio(); - slp = &syncer_workitem_pending[syncer_delayno]; - syncer_delayno += 1; - if (syncer_delayno == syncer_maxdelay) - syncer_delayno = 0; - splx(s); - while ((vp = LIST_FIRST(slp)) != NULL) { - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - (void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p); - VOP_UNLOCK(vp, 0, p); - if (LIST_FIRST(slp) == vp) { - if (LIST_FIRST(&vp->v_dirtyblkhd) == NULL) - panic("sched_sync: fsync failed"); - /* - * Move ourselves to the back of the sync list. - */ - LIST_REMOVE(vp, v_synclist); - vn_syncer_add_to_worklist(vp, syncdelay); - } - } - - /* - * Do soft update processing. - */ - if (bioops.io_sync) - (*bioops.io_sync)(NULL); - - /* - * If it has taken us less than a second to process the - * current work, then wait. Otherwise start right over - * again. We can still lose time if any single round - * takes more than two seconds, but it does not really - * matter as we are just trying to generally pace the - * filesystem activity. - */ - if (time.tv_sec == starttime) - tsleep(&lbolt, PPAUSE, "syncer", 0); - } -} - -/* - * Reassign a buffer from one vnode to another. Used to assign buffers - * to the appropriate clean or dirty list and to add newly dirty vnodes - * to the appropriate filesystem syncer list. + * Reassign a buffer from one vnode to another. + * Used to assign file specific control information + * (indirect blocks) to the vnode to which they belong. */ void reassignbuf(bp, newvp) register struct buf *bp; register struct vnode *newvp; { - struct buflists *listheadp; - struct buf *wasdirty; - int delay; + register struct buflists *listheadp; if (newvp == NULL) { printf("reassignbuf: NULL"); @@ -834,36 +594,16 @@ reassignbuf(bp, newvp) /* * Delete from old vnode list, if on one. */ - wasdirty = newvp->v_dirtyblkhd.lh_first; if (bp->b_vnbufs.le_next != NOLIST) bufremvn(bp); /* * If dirty, put on list of dirty buffers; * otherwise insert onto list of clean buffers. */ - if ((bp->b_flags & B_DELWRI) == 0) { - listheadp = &newvp->v_cleanblkhd; - if (wasdirty && LIST_FIRST(&newvp->v_dirtyblkhd) == NULL) - LIST_REMOVE(newvp, v_synclist); - } else { + if (bp->b_flags & B_DELWRI) listheadp = &newvp->v_dirtyblkhd; - if (LIST_FIRST(listheadp) == NULL) { - switch (newvp->v_type) { - case VDIR: - delay = syncdelay / 3; - break; - case VBLK: - if (newvp->v_specmountpoint != NULL) { - delay = syncdelay / 2; - break; - } - /* fall through */ - default: - delay = syncdelay; - } - vn_syncer_add_to_worklist(newvp, delay); - } - } + else + listheadp = &newvp->v_cleanblkhd; bufinsvn(bp, listheadp); } @@ -909,10 +649,8 @@ getdevvp(dev, vpp, type) struct vnode *nvp; int error; - if (dev == NODEV) { - *vpp = NULLVP; + if (dev == NODEV) return (0); - } error = getnewvnode(VT_NON, NULL, spec_vnodeop_p, &nvp); if (error) { *vpp = NULLVP; @@ -942,7 +680,6 @@ checkalias(nvp, nvp_rdev, mp) dev_t nvp_rdev; struct mount *mp; { - struct proc *p = curproc; register struct vnode *vp; struct vnode **vpp; @@ -951,23 +688,18 @@ checkalias(nvp, nvp_rdev, mp) vpp = &speclisth[SPECHASH(nvp_rdev)]; loop: - simple_lock(&spechash_slock); for (vp = *vpp; vp; vp = vp->v_specnext) { - simple_lock(&vp->v_interlock); if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type) continue; /* * Alias, but not in use, so flush it out. */ if (vp->v_usecount == 0) { - simple_unlock(&spechash_slock); - vgonel(vp, p); + vgone(vp); goto loop; } - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { - simple_unlock(&spechash_slock); + if (vget(vp, 1)) goto loop; - } break; } if (vp == NULL || vp->v_tag != VT_NON || vp->v_type != VBLK) { @@ -976,21 +708,18 @@ loop: nvp->v_rdev = nvp_rdev; nvp->v_hashchain = vpp; nvp->v_specnext = *vpp; - nvp->v_specmountpoint = NULL; + nvp->v_specflags = 0; nvp->v_speclockf = NULL; - simple_unlock(&spechash_slock); *vpp = nvp; - if (vp != NULLVP) { + if (vp != NULL) { nvp->v_flag |= VALIASED; vp->v_flag |= VALIASED; vput(vp); } return (NULLVP); } - simple_unlock(&spechash_slock); - VOP_UNLOCK(vp, 0, p); - simple_lock(&vp->v_interlock); - vclean(vp, 0, p); + VOP_UNLOCK(vp); + vclean(vp, 0); vp->v_op = nvp->v_op; vp->v_tag = nvp->v_tag; nvp->v_type = VNON; @@ -1007,260 +736,91 @@ loop: * been changed to a new file system type). */ int -vget(vp, flags, p) - struct vnode *vp; - int flags; - struct proc *p; +vget(vp, lockflag) + register struct vnode *vp; + int lockflag; { - int error; + /* * If the vnode is in the process of being cleaned out for * another use, we wait for the cleaning to finish and then - * return failure. Cleaning is determined by checking that - * the VXLOCK flag is set. + * return failure. Cleaning is determined either by checking + * that the VXLOCK flag is set, or that the use count is + * zero with the back pointer set to show that it has been + * removed from the free list by getnewvnode. The VXLOCK + * flag may not have been set yet because vclean is blocked in + * the VOP_LOCK call waiting for the VOP_INACTIVE to complete. */ - if ((flags & LK_INTERLOCK) == 0) - simple_lock(&vp->v_interlock); - if (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - simple_unlock(&vp->v_interlock); + if ((vp->v_flag & VXLOCK) || + (vp->v_usecount == 0 && + vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb)) { + vp->v_flag |= VXWANT; tsleep((caddr_t)vp, PINOD, "vget", 0); - return (ENOENT); - } - if (vp->v_usecount == 0) { - simple_lock(&vnode_free_list_slock); - if (vp->v_holdcnt > 0) - TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist); - else - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - simple_unlock(&vnode_free_list_slock); - } - vp->v_usecount++; - if (flags & LK_TYPE_MASK) { - if ((error = vn_lock(vp, flags | LK_INTERLOCK, p)) != 0) { - vunref(vp); - simple_unlock(&vp->v_interlock); - } - return (error); + return (1); } - simple_unlock(&vp->v_interlock); + if (vp->v_usecount == 0) + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + vp->v_usecount++; + if (lockflag) + VOP_LOCK(vp); 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_nolock(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_nolock: 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_nounlock(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_noislocked(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)); -} - -/* - * Vnode reference. + * Vnode reference, just increment the count */ void vref(vp) struct vnode *vp; { - simple_lock(&vp->v_interlock); + if (vp->v_usecount <= 0) panic("vref used where vget required"); vp->v_usecount++; - simple_unlock(&vp->v_interlock); } - -int -vunref(vp) - struct vnode *vp; +/* + * vput(), just unlock and vrele() + */ +void +vput(vp) + register struct vnode *vp; { -#ifdef DIAGNOSTIC - if (vp == NULL) - panic("vrele: null vp"); -#endif - simple_lock (&vp->v_interlock); - vp->v_usecount--; - if (vp->v_usecount > 0) { - simple_unlock(&vp->v_interlock); - return (vp->v_usecount); - } -#ifdef DIAGNOSTIC - if (vp->v_usecount < 0 || vp->v_writecount != 0) { - vprint("vrele: bad ref count", vp); - panic("vrele: ref cnt"); - } -#endif - /* - * insert at tail of LRU list - */ - simple_lock(&vnode_free_list_slock); - if (vp->v_holdcnt > 0) - TAILQ_INSERT_TAIL(&vnode_hold_list, vp, v_freelist); - else - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - simple_unlock(&vnode_free_list_slock); - return (0); + VOP_UNLOCK(vp); + vrele(vp); } /* - * vput(), just unlock and vrele() + * Vnode release. + * If count drops to zero, call inactive routine and return to freelist. */ void -vput(vp) +vrele(vp) register struct vnode *vp; { - struct proc *p = curproc; /* XXX */ -#ifdef DIGANOSTIC +#ifdef DIAGNOSTIC if (vp == NULL) - panic("vput: null vp"); + panic("vrele: null vp"); #endif - simple_lock(&vp->v_interlock); vp->v_usecount--; - if (vp->v_usecount > 0) { - simple_unlock(&vp->v_interlock); - VOP_UNLOCK(vp, 0, p); + if (vp->v_usecount > 0) return; - } #ifdef DIAGNOSTIC - if (vp->v_usecount < 0 || vp->v_writecount != 0) { - vprint("vput: bad ref count", vp); - panic("vput: ref cnt"); + if (vp->v_usecount != 0 || vp->v_writecount != 0) { + vprint("vrele: bad ref count", vp); + panic("vrele: ref cnt"); } #endif /* * insert at tail of LRU list */ - simple_lock(&vnode_free_list_slock); - if (vp->v_holdcnt > 0) - TAILQ_INSERT_TAIL(&vnode_hold_list, vp, v_freelist); - else - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - simple_unlock(&vnode_free_list_slock); - simple_unlock(&vp->v_interlock); - VOP_INACTIVE(vp, p); + TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); + VOP_INACTIVE(vp); } /* - * Vnode release - use for active VNODES. - * If count drops to zero, call inactive routine and return to freelist. - */ -void -vrele(vp) - register struct vnode *vp; -{ - struct proc *p = curproc; - - if (vunref(vp) == 0 && - vn_lock(vp, LK_EXCLUSIVE |LK_INTERLOCK, p) == 0) - VOP_INACTIVE(vp, p); -} - -#ifdef DIAGNOSTIC -/* * Page or buffer structure gets a reference. */ void @@ -1268,27 +828,7 @@ vhold(vp) register struct vnode *vp; { - /* - * If it is on the freelist and the hold count is currently - * zero, move it to the hold list. - * - * The VGONEHACK flag reflects a call from getnewvnode, - * which will remove the vnode from the free list, but - * will not increment the ref count until after it calls vgone - * If the ref count we're incremented first, vgone would - * (incorrectly) try to close the previous instance of the - * underlying object. - */ - simple_lock(&vp->v_interlock); - if (!(vp->v_flag & VGONEHACK) && - vp->v_holdcnt == 0 && vp->v_usecount == 0) { - simple_lock(&vnode_free_list_slock); - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_hold_list, vp, v_freelist); - simple_unlock(&vnode_free_list_slock); - } vp->v_holdcnt++; - simple_unlock(&vp->v_interlock); } /* @@ -1299,26 +839,10 @@ holdrele(vp) register struct vnode *vp; { - simple_lock(&vp->v_interlock); if (vp->v_holdcnt <= 0) panic("holdrele: holdcnt"); vp->v_holdcnt--; - /* - * If it is on the holdlist and the hold count drops to - * zero, move it to the free list. - * - * See above for VGONEHACK - */ - if (!(vp->v_flag & VGONEHACK) && - vp->v_holdcnt == 0 && vp->v_usecount == 0) { - simple_lock(&vnode_free_list_slock); - TAILQ_REMOVE(&vnode_hold_list, vp, v_freelist); - TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); - simple_unlock(&vnode_free_list_slock); - } - simple_unlock(&vp->v_interlock); } -#endif /* DIAGNOSTIC */ /* * Remove any vnodes in the vnode table belonging to mount point mp. @@ -1339,11 +863,11 @@ vflush(mp, skipvp, flags) struct vnode *skipvp; int flags; { - struct proc *p = curproc; register struct vnode *vp, *nvp; int busy = 0; - simple_lock(&mntvnode_slock); + if ((mp->mnt_flag & MNT_MPBUSY) == 0) + panic("vflush: not busy"); loop: for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) { if (vp->v_mount != mp) @@ -1354,32 +878,24 @@ loop: */ if (vp == skipvp) continue; - - simple_lock(&vp->v_interlock); /* * Skip over a vnodes marked VSYSTEM. */ - if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) { - simple_unlock(&vp->v_interlock); + if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) continue; - } /* * If WRITECLOSE is set, only flush out regular file * vnodes open for writing. */ if ((flags & WRITECLOSE) && - (vp->v_writecount == 0 || vp->v_type != VREG)) { - simple_unlock(&vp->v_interlock); + (vp->v_writecount == 0 || vp->v_type != VREG)) continue; - } /* * With v_usecount == 0, all we need to do is clear * out the vnode data structures and we are done. */ if (vp->v_usecount == 0) { - simple_unlock(&mntvnode_slock); - vgonel(vp, p); - simple_lock(&mntvnode_slock); + vgone(vp); continue; } /* @@ -1388,25 +904,21 @@ loop: * anonymous device. For all other files, just kill them. */ if (flags & FORCECLOSE) { - simple_unlock(&mntvnode_slock); if (vp->v_type != VBLK && vp->v_type != VCHR) { - vgonel(vp, p); + vgone(vp); } else { - vclean(vp, 0, p); + vclean(vp, 0); vp->v_op = spec_vnodeop_p; insmntque(vp, (struct mount *)0); } - simple_lock(&mntvnode_slock); continue; } #ifdef DEBUG if (busyprt) vprint("vflush: busy vnode", vp); #endif - simple_unlock(&vp->v_interlock); busy++; } - simple_unlock(&mntvnode_slock); if (busy) return (EBUSY); return (0); @@ -1414,13 +926,11 @@ loop: /* * Disassociate the underlying file system from a vnode. - * The vnode interlock is held on entry. */ void -vclean(vp, flags, p) +vclean(vp, flags) register struct vnode *vp; int flags; - struct proc *p; { int active; @@ -1431,17 +941,7 @@ vclean(vp, flags, p) * race against ourselves to recycle it. */ if ((active = vp->v_usecount) != 0) - vp->v_usecount++; - - /* - * Prevent the vnode from being recycled or - * brought into use while we clean it out. - */ - if (vp->v_flag & VXLOCK) - panic("vclean: deadlock"); - vp->v_flag |= VXLOCK; - - + VREF(vp); /* * Even if the count is zero, the VOP_INACTIVE routine may still * have the object locked while it cleans it out. The VOP_LOCK @@ -1449,48 +949,40 @@ vclean(vp, flags, p) * For active vnodes, it ensures that no other activity can * occur while the underlying object is being cleaned out. */ - VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p); - + VOP_LOCK(vp); + /* + * Prevent the vnode from being recycled or + * brought into use while we clean it out. + */ + if (vp->v_flag & VXLOCK) + panic("vclean: deadlock"); + vp->v_flag |= VXLOCK; /* * Clean out any buffers associated with the vnode. */ if (flags & DOCLOSE) - vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); + vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0); + /* + * Any other processes trying to obtain this lock must first + * wait for VXLOCK to clear, then call the new lock operation. + */ + VOP_UNLOCK(vp); /* * If purging an active vnode, it must be closed and - * deactivated before being reclaimed. Note that the - * VOP_INACTIVE will unlock the vnode + * deactivated before being reclaimed. */ if (active) { if (flags & DOCLOSE) - VOP_CLOSE(vp, FNONBLOCK, NOCRED, p); - VOP_INACTIVE(vp, p); - } else { - /* - * Any other processes trying to obtain this lock must first - * wait for VXLOCK to clear, then call the new lock operation. - */ - VOP_UNLOCK(vp, 0, p); + VOP_CLOSE(vp, FNONBLOCK, NOCRED, NULL); + VOP_INACTIVE(vp); } - /* * Reclaim the vnode. */ - if (VOP_RECLAIM(vp, p)) + if (VOP_RECLAIM(vp)) panic("vclean: cannot reclaim"); - if (active) { - if (vunref(vp) == 0 && - vp->v_holdcnt > 0) - panic("vclean: not clean"); - simple_unlock(&vp->v_interlock); - } - cache_purge(vp); - if (vp->v_vnlock) { - if ((vp->v_vnlock->lk_flags & LK_DRAINED) == 0) - vprint("vclean: lock not drained", vp); - FREE(vp->v_vnlock, M_VNODE); - vp->v_vnlock = NULL; - } + if (active) + vrele(vp); /* * Done with purge, notify sleepers of the grim news. @@ -1508,25 +1000,12 @@ vclean(vp, flags, p) * Eliminate all activity associated with the requested vnode * and with all vnodes aliased to the requested vnode. */ -int -vop_revoke(v) - void *v; +void +vgoneall(vp) + register struct vnode *vp; { - 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_revoke"); -#endif + register struct vnode *vq; - vp = ap->a_vp; - simple_lock(&vp->v_interlock); - if (vp->v_flag & VALIASED) { /* * If a vgone (or vclean) is already in progress, @@ -1534,23 +1013,19 @@ vop_revoke(v) */ if (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; - simple_unlock(&vp->v_interlock); - tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0); - return(0); + tsleep((caddr_t)vp, PINOD, "vgoneall", 0); + return; } /* * 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; } @@ -1560,34 +1035,9 @@ vop_revoke(v) * 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); -} - - -/* - * Recycle an unused vnode to the front of the free list. - * Release the passed interlock if the vnode will be recycled. - */ -int -vrecycle(vp, inter_lkp, p) - struct vnode *vp; - struct simplelock *inter_lkp; - struct proc *p; -{ - - simple_lock(&vp->v_interlock); - if (vp->v_usecount == 0) { - if (inter_lkp) - simple_unlock(inter_lkp); - vgonel(vp, p); - return (1); - } - simple_unlock(&vp->v_interlock); - return (0); + vgone(vp); } /* @@ -1598,20 +1048,6 @@ void vgone(vp) register struct vnode *vp; { - struct proc *p = curproc; - - simple_lock (&vp->v_interlock); - vgonel(vp, p); -} - -/* - * vgone, with the vp interlock held. - */ -void -vgonel(vp, p) - struct vnode *vp; - struct proc *p; -{ register struct vnode *vq; struct vnode *vx; @@ -1621,25 +1057,21 @@ vgonel(vp, p) */ if (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; - simple_unlock(&vp->v_interlock); tsleep((caddr_t)vp, PINOD, "vgone", 0); return; } /* * Clean out the filesystem specific data. */ - vclean(vp, DOCLOSE, p); + vclean(vp, DOCLOSE); /* * Delete from old mount point vnode list, if on one. */ - if (vp->v_mount != NULL) - insmntque(vp, (struct mount *)0); + insmntque(vp, (struct mount *)0); /* - * If special device, remove it from special device alias list - * if it is on one. + * If special device, remove it from special device alias list. */ - if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) { - simple_lock(&spechash_slock); + if (vp->v_type == VBLK || vp->v_type == VCHR) { if (*vp->v_hashchain == vp) { *vp->v_hashchain = vp->v_specnext; } else { @@ -1668,26 +1100,27 @@ vgonel(vp, p) vx->v_flag &= ~VALIASED; vp->v_flag &= ~VALIASED; } - simple_unlock(&spechash_slock); FREE(vp->v_specinfo, M_VNODE); vp->v_specinfo = NULL; } /* * If it is on the freelist and not already at the head, - * move it to the head of the list. - * - * See above about the VGONEHACK + * move it to the head of the list. The test of the back + * pointer and the reference count of zero is because + * it will be removed from the free list by getnewvnode, + * but will not have its reference count incremented until + * after calling vgone. If the reference count were + * incremented first, vgone would (incorrectly) try to + * close the previous instance of the underlying object. + * So, the back pointer is explicitly set to `0xdeadb' in + * getnewvnode after removing it from the freelist to ensure + * that we do not try to move it here. */ - if (vp->v_usecount == 0) { - simple_lock(&vnode_free_list_slock); - if (vp->v_holdcnt > 0) - panic("vgonel: not clean"); - if (!(vp->v_flag & VGONEHACK) && - TAILQ_FIRST(&vnode_free_list) != vp) { - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); - } - simple_unlock(&vnode_free_list_slock); + if (vp->v_usecount == 0 && + vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb && + vnode_free_list.tqh_first != vp) { + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } vp->v_type = VBAD; } @@ -1702,18 +1135,14 @@ vfinddev(dev, type, vpp) struct vnode **vpp; { register struct vnode *vp; - int rc =0; - simple_lock(&spechash_slock); for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) { if (dev != vp->v_rdev || type != vp->v_type) continue; *vpp = vp; - rc = 1; - break; + return (1); } - simple_unlock(&spechash_slock); - return (rc); + return (0); } /* @@ -1721,15 +1150,14 @@ vfinddev(dev, type, vpp) */ int vcount(vp) - struct vnode *vp; + register struct vnode *vp; { - struct vnode *vq, *vnext; + register struct vnode *vq, *vnext; int count; loop: if ((vp->v_flag & VALIASED) == 0) return (vp->v_usecount); - simple_lock(&spechash_slock); for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) { vnext = vq->v_specnext; if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) @@ -1738,13 +1166,11 @@ loop: * Alias, but not in use, so flush it out. */ if (vq->v_usecount == 0 && vq != vp) { - simple_unlock(&spechash_slock); vgone(vq); goto loop; } count += vq->v_usecount; } - simple_unlock(&spechash_slock); return (count); } @@ -1799,76 +1225,20 @@ vprint(label, vp) void printlockedvnodes() { - struct proc *p = curproc; - register struct mount *mp, *nmp; + register struct mount *mp; register struct vnode *vp; printf("Locked vnodes\n"); - simple_lock(&mountlist_slock); for (mp = mountlist.cqh_first; mp != (void *)&mountlist; - mp = nmp) { - if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { - nmp = mp->mnt_list.cque_next; - continue; - } + mp = mp->mnt_list.cqe_next) { for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; - vp = vp->v_mntvnodes.le_next) { + vp = vp->v_mntvnodes.le_next) if (VOP_ISLOCKED(vp)) vprint((char *)0, vp); - simple_lock(&mountlist_slock); - nmp = mp->mnt_list.cqe_next; - vfs_unbusy(mp, p); - } - simple_unlock(&mountlist_slock); - -} -#endif - -/* - * Top level filesystem related information gathering. - */ -int -vfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) - int *name; - u_int namelen; - void *oldp; - size_t *oldlenp; - void *newp; - size_t newlen; - struct proc *p; -{ - struct vfsconf *vfsp; - - /* all sysctl names at this level are at least name and field */ - if (namelen < 2) - return (ENOTDIR); /* overloaded */ - if (name[0] != VFS_GENERIC) { - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (vfsp->vfc_typenum == name[0]) - break; - if (vfsp == NULL) - return (EOPNOTSUPP); - return ((*vfsp->vfc_vfsops->vfs_sysctl)(&name[1], namelen - 1, - oldp, oldlenp, newp, newlen, p)); } - switch (name[1]) { - case VFS_MAXTYPENUM: - return (sysctl_rdint(oldp, oldlenp, newp, maxvfsconf)); - case VFS_CONF: - if (namelen < 3) - return (ENOTDIR); /* overloaded */ - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (vfsp->vfc_typenum == name[2]) - break; - if (vfsp == NULL) - return (EOPNOTSUPP); - return (sysctl_rdstruct(oldp, oldlenp, newp, vfsp, - sizeof(struct vfsconf))); - } - return (EOPNOTSUPP); } - +#endif int kinfo_vdebug = 1; int kinfo_vgetfailed; @@ -1879,13 +1249,12 @@ int kinfo_vgetfailed; */ /* ARGSUSED */ int -sysctl_vnode(where, sizep, p) +sysctl_vnode(where, sizep) char *where; size_t *sizep; - struct proc *p; { register struct mount *mp, *nmp; - struct vnode *vp, *nvp; + struct vnode *vp; register char *bp = where, *savebp; char *ewhere; int error; @@ -1898,32 +1267,27 @@ sysctl_vnode(where, sizep, p) } ewhere = where + *sizep; - simple_lock(&mountlist_slock); for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { - if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { - nmp = mp->mnt_list.cqe_next; + nmp = mp->mnt_list.cqe_next; + if (vfs_busy(mp)) continue; - } savebp = bp; again: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; - vp = nvp) { + vp = vp->v_mntvnodes.le_next) { /* * Check that the vp is still associated with * this filesystem. RACE: could have been * recycled onto the same filesystem. */ if (vp->v_mount != mp) { - simple_unlock(&mntvnode_slock); if (kinfo_vdebug) printf("kinfo: vp changed\n"); bp = savebp; goto again; } - nvp = vp->v_mntvnodes.le_next; if (bp + VPTRSZ + VNODESZ > ewhere) { - simple_unlock(&mntvnode_slock); *sizep = bp - where; return (ENOMEM); } @@ -1931,17 +1295,10 @@ again: (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ))) return (error); bp += VPTRSZ + VNODESZ; - simple_lock(&mntvnode_slock); } - - simple_unlock(&mntvnode_slock); - simple_lock(&mountlist_slock); - nmp = mp->mnt_list.cqe_next; - vfs_unbusy(mp, p); + vfs_unbusy(mp); } - simple_unlock(&mountlist_slock); - *sizep = bp - where; return (0); } @@ -1954,31 +1311,26 @@ vfs_mountedon(vp) register struct vnode *vp; { register struct vnode *vq; - int error = 0; - if (vp->v_specmountpoint != NULL) + if (vp->v_specflags & SI_MOUNTEDON) return (EBUSY); if (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) continue; - if (vq->v_specmountpoint != NULL) { - error = EBUSY; - break; - } - } - simple_unlock(&spechash_slock); + if (vq->v_specflags & SI_MOUNTEDON) + return (EBUSY); + } } - return (error); + return (0); } /* * Build hash lists of net addresses and hang them off the mount point. * Called by ufs_mount() to set up the lists of export addresses. */ -int +static int vfs_hang_addrlist(mp, nep, argp) struct mount *mp; struct netexport *nep; @@ -2052,7 +1404,7 @@ out: } /* ARGSUSED */ -int +static int vfs_free_netcred(rn, w) struct radix_node *rn; void *w; @@ -2067,7 +1419,7 @@ vfs_free_netcred(rn, w) /* * Free the net address hash lists that are hanging off the mount points. */ -void +static void vfs_free_addrlist(nep) struct netexport *nep; { @@ -2314,161 +1666,3 @@ fs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) } return (*fn)(name + 1, namelen - 1, oldp, oldlenp, newp, newlen, p); } - -/* - * Routine to create and manage a filesystem syncer vnode. - */ -#define sync_close nullop -int sync_fsync __P((void *)); -int sync_inactive __P((void *)); -#define sync_reclaim nullop -#define sync_lock vop_nolock -#define sync_unlock vop_nounlock -int sync_print __P((void *)); -#define sync_islocked vop_noislocked - -int (**sync_vnodeop_p) __P((void *)); -struct vnodeopv_entry_desc sync_vnodeop_entries[] = { - { &vop_default_desc, vn_default_error }, - { &vop_close_desc, sync_close }, /* close */ - { &vop_fsync_desc, sync_fsync }, /* fsync */ - { &vop_inactive_desc, sync_inactive }, /* inactive */ - { &vop_reclaim_desc, sync_reclaim }, /* reclaim */ - { &vop_lock_desc, sync_lock }, /* lock */ - { &vop_unlock_desc, sync_unlock }, /* unlock */ - { &vop_print_desc, sync_print }, /* print */ - { &vop_islocked_desc, sync_islocked }, /* islocked */ - { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } -}; -struct vnodeopv_desc sync_vnodeop_opv_desc = - { &sync_vnodeop_p, sync_vnodeop_entries }; - -/* - * Create a new filesystem syncer vnode for the specified mount point. - */ -int -vfs_allocate_syncvnode(mp) - struct mount *mp; -{ - struct vnode *vp; - static long start, incr, next; - int error; - - /* Allocate a new vnode */ - if ((error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, &vp)) != 0) { - mp->mnt_syncer = NULL; - return (error); - } - vp->v_writecount = 1; - vp->v_type = VNON; - /* - * Place the vnode onto the syncer worklist. We attempt to - * scatter them about on the list so that they will go off - * at evenly distributed times even if all the filesystems - * are mounted at once. - */ - next += incr; - if (next == 0 || next > syncer_maxdelay) { - start /= 2; - incr /= 2; - if (start == 0) { - start = syncer_maxdelay / 2; - incr = syncer_maxdelay; - } - next = start; - } - vn_syncer_add_to_worklist(vp, next); - mp->mnt_syncer = vp; - return (0); -} - -/* - * Do a lazy sync of the filesystem. - */ -int -sync_fsync(v) - void *v; -{ - struct vop_fsync_args /* { - struct vnode *a_vp; - struct ucred *a_cred; - int a_waitfor; - struct proc *a_p; - } */ *ap = v; - - struct vnode *syncvp = ap->a_vp; - struct mount *mp = syncvp->v_mount; - int asyncflag; - - /* - * We only need to do something if this is a lazy evaluation. - */ - if (ap->a_waitfor != MNT_LAZY) - return (0); - - /* - * Move ourselves to the back of the sync list. - */ - LIST_REMOVE(syncvp, v_synclist); - vn_syncer_add_to_worklist(syncvp, syncdelay); - - /* - * Walk the list of vnodes pushing all that are dirty and - * not already on the sync list. - */ - simple_lock(&mountlist_slock); - if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, ap->a_p) == 0) { - asyncflag = mp->mnt_flag & MNT_ASYNC; - mp->mnt_flag &= ~MNT_ASYNC; - VFS_SYNC(mp, MNT_LAZY, ap->a_cred, ap->a_p); - if (asyncflag) - mp->mnt_flag |= MNT_ASYNC; - vfs_unbusy(mp, ap->a_p); - } - return (0); -} - -/* - * The syncer vnode is no longer needed and is being decommissioned. - */ -int -sync_inactive(v) - void *v; - -{ - struct vop_inactive_args /* { - struct vnode *a_vp; - struct proc *a_p; - } */ *ap = v; - - struct vnode *vp = ap->a_vp; - - if (vp->v_usecount == 0) - return (0); - vp->v_mount->mnt_syncer = NULL; - LIST_REMOVE(vp, v_synclist); - vp->v_writecount = 0; - vput(vp); - return (0); -} - -/* - * Print out a syncer vnode. - */ -int -sync_print(v) - void *v; - -{ - struct vop_print_args /* { - struct vnode *a_vp; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - - printf("syncer vnode"); - if (vp->v_vnlock != NULL) - lockmgr_printinfo(vp->v_vnlock); - printf("\n"); - return (0); -} - diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index f1e566ae6b8..8fb9377c231 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.26 1997/10/06 15:12:43 csapuntz Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.27 1997/10/06 20:20:14 deraadt Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -102,11 +102,10 @@ sys_mount(p, v, retval) register struct vnode *vp; register struct mount *mp; int error, flag = 0; - u_long fstypenum = 0; + u_long fsindex = 0; char fstypename[MFSNAMELEN]; struct vattr va; struct nameidata nd; - struct vfsconf *vfsp; if (usermount == 0 && (error = suser(p->p_ucred, &p->p_acflag))) return (error); @@ -157,7 +156,7 @@ sys_mount(p, v, retval) } SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; } - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); goto update; } /* @@ -196,19 +195,12 @@ sys_mount(p, v, retval) * string, we check to see if it matches one of the historic * filesystem types. */ - fstypenum = (u_long)SCARG(uap, type); - - if (fstypenum < maxvfsconf) { - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (vfsp->vfc_typenum == fstypenum) - break; - if (vfsp == NULL) { - vput(vp); - return (ENODEV); - } - strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); - + fsindex = (u_long)SCARG(uap, type); + if (fsindex >= nvfssw || vfssw[fsindex] == NULL) { + vput(vp); + return (ENODEV); } + strncpy(fstypename, vfssw[fsindex]->vfs_name, MFSNAMELEN); #else vput(vp); return (error); @@ -220,16 +212,14 @@ sys_mount(p, v, retval) strncpy( fstypename, "ffs", MFSNAMELEN); } #endif - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) { - if (!strcmp(vfsp->vfc_name, fstypename)) + for (fsindex = 0; fsindex < nvfssw; fsindex++) + if (vfssw[fsindex] != NULL && + !strncmp(vfssw[fsindex]->vfs_name, fstypename, MFSNAMELEN)) break; - } - - if (vfsp == NULL) { + if (fsindex >= nvfssw) { vput(vp); return (ENODEV); } - if (vp->v_mountedhere != NULL) { vput(vp); return (EBUSY); @@ -241,14 +231,14 @@ sys_mount(p, v, retval) mp = (struct mount *)malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, (u_long)sizeof(struct mount)); - lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); - vfs_busy(mp, LK_NOWAIT, 0, p); - mp->mnt_op = vfsp->vfc_vfsops; - mp->mnt_vfc = vfsp; - vfsp->vfc_refcount++; - mp->mnt_stat.f_type = vfsp->vfc_typenum; - mp->mnt_flag |= (vfsp->vfc_flags & MNT_VISFLAGMASK); - strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); + mp->mnt_op = vfssw[fsindex]; + if ((error = vfs_lock(mp)) != 0) { + free((caddr_t)mp, M_MOUNT); + vput(vp); + return (error); + } + /* Do this early in case we block later. */ + vfssw[fsindex]->vfs_refcount++; vp->v_mountedhere = mp; mp->mnt_vnodecovered = vp; mp->mnt_stat.f_owner = p->p_ucred->cr_uid; @@ -276,17 +266,6 @@ update: (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR); if (error) mp->mnt_flag = flag; - - if ((mp->mnt_flag & MNT_RDONLY) == 0) { - if (mp->mnt_syncer == NULL) - error = vfs_allocate_syncvnode(mp); - } else { - if (mp->mnt_syncer != NULL) - vgone(mp->mnt_syncer); - mp->mnt_syncer = NULL; - } - - vfs_unbusy(mp, p); return (error); } /* @@ -294,20 +273,16 @@ update: */ cache_purge(vp); if (!error) { - simple_lock(&mountlist_slock); CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); - simple_unlock(&mountlist_slock); checkdirs(vp); - VOP_UNLOCK(vp, 0, p); - if ((mp->mnt_flag & MNT_RDONLY) == 0) - error = vfs_allocate_syncvnode(mp); - vfs_unbusy(mp, p); + VOP_UNLOCK(vp); + vfs_unlock(mp); (void) VFS_STATFS(mp, &mp->mnt_stat, p); - if ((error = VFS_START(mp, 0, p)) != 0) - vrele(vp); + error = VFS_START(mp, 0, p); } else { mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; - vfs_unbusy(mp, p); + vfssw[fsindex]->vfs_refcount--; + vfs_unlock(mp); free((caddr_t)mp, M_MOUNT); vput(vp); } @@ -422,40 +397,36 @@ dounmount(mp, flags, p) struct vnode *coveredvp; int error; - simple_lock(&mountlist_slock); + coveredvp = mp->mnt_vnodecovered; + if (vfs_busy(mp)) + return (EBUSY); mp->mnt_flag |= MNT_UNMOUNT; - lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p); - mp->mnt_flag &=~ MNT_ASYNC; - vnode_pager_umount(mp); /* release cached vnodes */ - cache_purgevfs(mp); /* remove cache entries for this file sys */ - if (mp->mnt_syncer != NULL) - vgone(mp->mnt_syncer); - if (((mp->mnt_flag & MNT_RDONLY) || - (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || - (flags & MNT_FORCE)) - error = VFS_UNMOUNT(mp, flags, p); - simple_lock(&mountlist_slock); - if (error) { - if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) - (void) vfs_allocate_syncvnode(mp); - mp->mnt_flag &= ~MNT_UNMOUNT; - lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, - &mountlist_slock, p); + if ((error = vfs_lock(mp)) != 0) return (error); + + mp->mnt_flag &=~ MNT_ASYNC; + vnode_pager_umount(mp); /* release cached vnodes */ + cache_purgevfs(mp); /* remove cache entries for this file sys */ + if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 || + (flags & MNT_FORCE)) + error = VFS_UNMOUNT(mp, flags, p); + mp->mnt_flag &= ~MNT_UNMOUNT; + vfs_unbusy(mp); + if (error) { + vfs_unlock(mp); + } else { + CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); + if (coveredvp != NULLVP) { + vrele(coveredvp); + coveredvp->v_mountedhere = (struct mount *)0; + } + mp->mnt_op->vfs_refcount--; + vfs_unlock(mp); + if (mp->mnt_vnodelist.lh_first != NULL) + panic("unmount: dangling vnode"); + free((caddr_t)mp, M_MOUNT); } - CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); - if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { - coveredvp->v_mountedhere = (struct mount *)0; - vrele(coveredvp); - } - mp->mnt_vfc->vfc_refcount--; - if (mp->mnt_vnodelist.lh_first != NULL) - panic("unmount: dangling vnode"); - lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p); - if (mp->mnt_flag & MNT_MWAIT) - wakeup((caddr_t)mp); - free((caddr_t)mp, M_MOUNT); - return (0); + return (error); } /* @@ -476,25 +447,31 @@ sys_sync(p, v, retval) register struct mount *mp, *nmp; int asyncflag; - simple_lock(&mountlist_slock); for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) { - if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { - nmp = mp->mnt_list.cqe_next; - continue; - } - if ((mp->mnt_flag & MNT_RDONLY) == 0) { + /* + * Get the next pointer in case we hang on vfs_busy + * while we are being unmounted. + */ + nmp = mp->mnt_list.cqe_prev; + /* + * The lock check below is to avoid races with mount + * and unmount. + */ + if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && + !vfs_busy(mp)) { asyncflag = mp->mnt_flag & MNT_ASYNC; mp->mnt_flag &= ~MNT_ASYNC; VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); if (asyncflag) mp->mnt_flag |= MNT_ASYNC; + /* + * Get the next pointer again, as the next filesystem + * might have been unmounted while we were sync'ing. + */ + nmp = mp->mnt_list.cqe_prev; + vfs_unbusy(mp); } - simple_lock(&mountlist_slock); - nmp = mp->mnt_list.cqe_next; - vfs_unbusy(mp, p); } - simple_unlock(&mountlist_slock); - #ifdef DEBUG if (syncprt) vfs_bufstats(); @@ -619,7 +596,7 @@ sys_getfsstat(p, v, retval) syscallarg(long) bufsize; syscallarg(int) flags; } */ *uap = v; - register struct mount *mp, *nmp; + register struct mount *mp; register struct statfs *sp; caddr_t sfsp; long count, maxcount, error; @@ -627,28 +604,20 @@ sys_getfsstat(p, v, retval) maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); sfsp = (caddr_t)SCARG(uap, buf); - count = 0; - simple_lock(&mountlist_slock); - for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { - if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { - nmp = mp->mnt_list.cqe_next; - continue; - } - if (sfsp && count < maxcount) { + for (count = 0, mp = mountlist.cqh_first; + mp != (void *)&mountlist; + mp = mp->mnt_list.cqe_next) { + if (sfsp && count < maxcount && + ((mp->mnt_flag & MNT_MLOCK) == 0)) { sp = &mp->mnt_stat; /* - * If MNT_NOWAIT or MNT_LAZY is specified, do not - * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY - * overrides MNT_WAIT. - */ - if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || + * If MNT_NOWAIT is specified, do not refresh the + * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. + */ + if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 || (SCARG(uap, flags) & MNT_WAIT)) && - (error = VFS_STATFS(mp, sp, p))) { - simple_lock(&mountlist_slock); - nmp = mp->mnt_list.cqe_next; - vfs_unbusy(mp, p); - continue; - } + (error = VFS_STATFS(mp, sp, p))) + continue; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; if (suser(p->p_ucred, &p->p_acflag)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); @@ -661,11 +630,7 @@ sys_getfsstat(p, v, retval) sfsp += sizeof(*sp); } count++; - simple_lock(&mountlist_slock); - nmp = mp->mnt_list.cqe_next; - vfs_unbusy(mp, p); } - simple_unlock(&mountlist_slock); if (sfsp && count > maxcount) *retval = maxcount; else @@ -696,7 +661,7 @@ sys_fchdir(p, v, retval) return (error); vp = (struct vnode *)fp->f_data; VREF(vp); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_type != VDIR) error = ENOTDIR; else @@ -712,21 +677,11 @@ sys_fchdir(p, v, retval) vput(vp); vp = tdp; } - while (!error && (mp = vp->v_mountedhere) != NULL) { - if (vfs_busy(mp, 0, 0, p)) - continue; - error = VFS_ROOT(mp, &tdp); - vfs_unbusy(mp, p); - if (error) - break; - vput(vp); - vp = tdp; - } + VOP_UNLOCK(vp); if (error) { - vput(vp); + vrele(vp); return (error); } - VOP_UNLOCK(vp, 0, p); vrele(fdp->fd_cdir); fdp->fd_cdir = vp; return (0); @@ -813,10 +768,9 @@ change_dir(ndp, p) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); + VOP_UNLOCK(vp); if (error) - vput(vp); - else - VOP_UNLOCK(vp, 0, p); + vrele(vp); return (error); } @@ -883,7 +837,7 @@ sys_open(p, v, retval) type = F_FLOCK; if ((flags & FNONBLOCK) == 0) type |= F_WAIT; - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); if (error) { (void) vn_close(vp, fp->f_flag, fp->f_cred, p); @@ -891,10 +845,10 @@ sys_open(p, v, retval) fdp->fd_ofiles[indx] = NULL; return (error); } - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); fp->f_flag |= FHASLOCK; } - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); *retval = indx; return (0); } @@ -1463,7 +1417,7 @@ sys_chflags(p, v, retval) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { @@ -1498,7 +1452,7 @@ sys_fchflags(p, v, retval) return (error); vp = (struct vnode *)fp->f_data; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { @@ -1506,7 +1460,7 @@ sys_fchflags(p, v, retval) vattr.va_flags = SCARG(uap, flags); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -1534,7 +1488,7 @@ sys_chmod(p, v, retval) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { @@ -1569,7 +1523,7 @@ sys_fchmod(p, v, retval) return (error); vp = (struct vnode *)fp->f_data; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { @@ -1577,7 +1531,7 @@ sys_fchmod(p, v, retval) vattr.va_mode = SCARG(uap, mode) & ALLPERMS; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -1607,7 +1561,7 @@ sys_chown(p, v, retval) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { @@ -1659,7 +1613,7 @@ sys_lchown(p, v, retval) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { @@ -1704,88 +1658,88 @@ sys_fchown(p, v, retval) struct vattr vattr; int error; struct file *fp; - u_short mode; - - if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) - return (error); - vp = (struct vnode *)fp->f_data; - VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - if (suser(p->p_ucred, &p->p_acflag) || - suid_clear) { - error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); - if (error) - goto out; - mode = vattr.va_mode & ~(VSUID | VSGID); - if (mode == vattr.va_mode) - mode = VNOVAL; - } - else - mode = VNOVAL; - VATTR_NULL(&vattr); - vattr.va_uid = SCARG(uap, uid); - vattr.va_gid = SCARG(uap, gid); - vattr.va_mode = mode; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + u_short mode; + + if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) + return (error); + vp = (struct vnode *)fp->f_data; + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + VOP_LOCK(vp); + if (vp->v_mount->mnt_flag & MNT_RDONLY) + error = EROFS; + else { + if (suser(p->p_ucred, &p->p_acflag) || + suid_clear) { + error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); + if (error) + goto out; + mode = vattr.va_mode & ~(VSUID | VSGID); + if (mode == vattr.va_mode) + mode = VNOVAL; + } + else + mode = VNOVAL; + VATTR_NULL(&vattr); + vattr.va_uid = SCARG(uap, uid); + vattr.va_gid = SCARG(uap, gid); + vattr.va_mode = mode; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); + } out: - VOP_UNLOCK(vp, 0, p); - return (error); + VOP_UNLOCK(vp); + return (error); } + /* * Set the access and modification times given a path name. */ /* ARGSUSED */ int sys_utimes(p, v, retval) - struct proc *p; - void *v; - register_t *retval; + struct proc *p; + void *v; + register_t *retval; { - register struct sys_utimes_args /* { - syscallarg(char *) path; - syscallarg(struct timeval *) tptr; - } */ *uap = v; - register struct vnode *vp; - struct timeval tv[2]; - struct vattr vattr; - int error; - struct nameidata nd; - - VATTR_NULL(&vattr); - if (SCARG(uap, tptr) == NULL) { - microtime(&tv[0]); - tv[1] = tv[0]; - vattr.va_vaflags |= VA_UTIMES_NULL; - } else { - error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, - sizeof (tv)); - if (error) - return (error); - } - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); - if ((error = namei(&nd)) != 0) - return (error); - vp = nd.ni_vp; - VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - if (vp->v_mount->mnt_flag & MNT_RDONLY) - error = EROFS; - else { - vattr.va_atime.tv_sec = tv[0].tv_sec; - vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; - vattr.va_mtime.tv_sec = tv[1].tv_sec; - vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; - error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); - } + register struct sys_utimes_args /* { + syscallarg(char *) path; + syscallarg(struct timeval *) tptr; + } */ *uap = v; + register struct vnode *vp; + struct timeval tv[2]; + struct vattr vattr; + int error; + struct nameidata nd; + + VATTR_NULL(&vattr); + if (SCARG(uap, tptr) == NULL) { + microtime(&tv[0]); + tv[1] = tv[0]; + vattr.va_vaflags |= VA_UTIMES_NULL; + } else { + error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, + sizeof (tv)); + if (error) + return (error); + } + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if ((error = namei(&nd)) != 0) + return (error); + vp = nd.ni_vp; + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + VOP_LOCK(vp); + if (vp->v_mount->mnt_flag & MNT_RDONLY) + error = EROFS; + else { + vattr.va_atime.tv_sec = tv[0].tv_sec; + vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; + vattr.va_mtime.tv_sec = tv[1].tv_sec; + vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; + error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); + } vput(vp); - return (error); + return (error); } - /* * Set the access and modification times given a file descriptor. */ @@ -1821,7 +1775,7 @@ sys_futimes(p, v, retval) return (error); vp = (struct vnode *)fp->f_data; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { @@ -1831,7 +1785,7 @@ sys_futimes(p, v, retval) vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -1860,7 +1814,7 @@ sys_truncate(p, v, retval) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0 && @@ -1899,7 +1853,7 @@ sys_ftruncate(p, v, retval) return (EINVAL); vp = (struct vnode *)fp->f_data; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); if (vp->v_type == VDIR) error = EISDIR; else if ((error = vn_writechk(vp)) == 0) { @@ -1907,7 +1861,7 @@ sys_ftruncate(p, v, retval) vattr.va_size = SCARG(uap, length); error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); } - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -1931,9 +1885,9 @@ sys_fsync(p, v, retval) if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) return (error); vp = (struct vnode *)fp->f_data; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -2154,11 +2108,11 @@ unionread: auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; auio.uio_resid = SCARG(uap, count); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); loff = auio.uio_offset = fp->f_offset; - error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0); + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *)0, 0); fp->f_offset = auio.uio_offset; - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); if (error) return (error); if ((SCARG(uap, count) == auio.uio_resid) && @@ -2228,13 +2182,17 @@ sys_revoke(p, v, retval) if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; + if (vp->v_type != VCHR && vp->v_type != VBLK) { + error = EINVAL; + goto out; + } if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) goto out; if (p->p_ucred->cr_uid != vattr.va_uid && (error = suser(p->p_ucred, &p->p_acflag))) goto out; if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) - VOP_REVOKE(vp, REVOKEALL); + vgoneall(vp); out: vrele(vp); return (error); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 3037cad20fe..2dc3f778374 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vnops.c,v 1.6 1997/10/06 15:12:45 csapuntz Exp $ */ +/* $OpenBSD: vfs_vnops.c,v 1.7 1997/10/06 20:20:15 deraadt Exp $ */ /* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */ /* @@ -133,9 +133,9 @@ vn_open(ndp, fmode, cmode) } } if (fmode & O_TRUNC) { - VOP_UNLOCK(vp, 0, p); /* XXX */ + VOP_UNLOCK(vp); /* XXX */ VOP_LEASE(vp, p, cred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ + VOP_LOCK(vp); /* XXX */ VATTR_NULL(&va); va.va_size = 0; if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0) @@ -153,14 +153,14 @@ bad: /* * Check for write permissions on the specified vnode. - * Prototype text segments cannot be written. + * The read-only status of the file system is checked. + * Also, prototype text segments cannot be written. */ int vn_writechk(vp) register struct vnode *vp; { -#if 0 /* * Disallow write attempts on read-only file systems; * unless the file is a socket or a block or character @@ -175,7 +175,6 @@ vn_writechk(vp) break; } } -#endif /* * If there's shared text associated with * the vnode, try to free it up once. If @@ -226,7 +225,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) int error; if ((ioflg & IO_NODELOCKED) == 0) - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = base; @@ -247,7 +246,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) if (auio.uio_resid && error == 0) error = EIO; if ((ioflg & IO_NODELOCKED) == 0) - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -262,17 +261,16 @@ vn_read(fp, uio, cred) { register struct vnode *vp = (struct vnode *)fp->f_data; int count, error = 0; - struct proc *p = uio->uio_procp; VOP_LEASE(vp, uio->uio_procp, cred, LEASE_READ); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); uio->uio_offset = fp->f_offset; count = uio->uio_resid; if (vp->v_type != VDIR) error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred); fp->f_offset += count - uio->uio_resid; - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -286,18 +284,14 @@ vn_write(fp, uio, cred) struct ucred *cred; { register struct vnode *vp = (struct vnode *)fp->f_data; - struct proc *p = uio->uio_procp; int count, error, ioflag = IO_UNIT; if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) ioflag |= IO_APPEND; if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; - if ((fp->f_flag & O_FSYNC) || - (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) - ioflag |= IO_SYNC; VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + VOP_LOCK(vp); uio->uio_offset = fp->f_offset; count = uio->uio_resid; error = VOP_WRITE(vp, uio, ioflag, cred); @@ -305,7 +299,7 @@ vn_write(fp, uio, cred) fp->f_offset = uio->uio_offset; else fp->f_offset += count - uio->uio_resid; - VOP_UNLOCK(vp, 0, p); + VOP_UNLOCK(vp); return (error); } @@ -433,36 +427,6 @@ vn_select(fp, which, p) } /* - * Check that the vnode is still valid, and if so - * acquire requested lock. - */ -int -vn_lock(vp, flags, p) - struct vnode *vp; - int flags; - struct proc *p; -{ - int error; - - do { - if ((flags & LK_INTERLOCK) == 0) - simple_lock(&vp->v_interlock); - if (vp->v_flag & VXLOCK) { - vp->v_flag |= VXWANT; - simple_unlock(&vp->v_interlock); - tsleep((caddr_t)vp, PINOD, "vn_lock", 0); - error = ENOENT; - } else { - error = VOP_LOCK(vp, flags | LK_INTERLOCK, p); - if (error == 0) - return (error); - } - flags &= ~LK_INTERLOCK; - } while (flags & LK_RETRY); - return (error); -} - -/* * File table vnode close routine. */ int diff --git a/sys/kern/vnode_if.c b/sys/kern/vnode_if.c index b373b57c591..14f1f0c5a09 100644 --- a/sys/kern/vnode_if.c +++ b/sys/kern/vnode_if.c @@ -218,22 +218,6 @@ struct vnodeop_desc vop_write_desc = { NULL, }; -int vop_lease_vp_offsets[] = { - VOPARG_OFFSETOF(struct vop_lease_args,a_vp), - VDESC_NO_OFFSET -}; -struct vnodeop_desc vop_lease_desc = { - 0, - "vop_lease", - 0, - vop_lease_vp_offsets, - VDESC_NO_OFFSET, - VOPARG_OFFSETOF(struct vop_lease_args, a_cred), - VOPARG_OFFSETOF(struct vop_lease_args, a_p), - VDESC_NO_OFFSET, - NULL, -}; - int vop_ioctl_vp_offsets[] = { VOPARG_OFFSETOF(struct vop_ioctl_args,a_vp), VDESC_NO_OFFSET @@ -266,22 +250,6 @@ struct vnodeop_desc vop_select_desc = { NULL, }; -int vop_revoke_vp_offsets[] = { - VOPARG_OFFSETOF(struct vop_revoke_args,a_vp), - VDESC_NO_OFFSET -}; -struct vnodeop_desc vop_revoke_desc = { - 0, - "vop_revoke", - 0, - vop_revoke_vp_offsets, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - NULL, -}; - int vop_mmap_vp_offsets[] = { VOPARG_OFFSETOF(struct vop_mmap_args,a_vp), VDESC_NO_OFFSET @@ -491,7 +459,7 @@ struct vnodeop_desc vop_inactive_desc = { vop_inactive_vp_offsets, VDESC_NO_OFFSET, VDESC_NO_OFFSET, - VOPARG_OFFSETOF(struct vop_inactive_args, a_p), + VDESC_NO_OFFSET, VDESC_NO_OFFSET, NULL, }; @@ -507,7 +475,7 @@ struct vnodeop_desc vop_reclaim_desc = { vop_reclaim_vp_offsets, VDESC_NO_OFFSET, VDESC_NO_OFFSET, - VOPARG_OFFSETOF(struct vop_reclaim_args, a_p), + VDESC_NO_OFFSET, VDESC_NO_OFFSET, NULL, }; @@ -523,7 +491,7 @@ struct vnodeop_desc vop_lock_desc = { vop_lock_vp_offsets, VDESC_NO_OFFSET, VDESC_NO_OFFSET, - VOPARG_OFFSETOF(struct vop_lock_args, a_p), + VDESC_NO_OFFSET, VDESC_NO_OFFSET, NULL, }; @@ -539,7 +507,7 @@ struct vnodeop_desc vop_unlock_desc = { vop_unlock_vp_offsets, VDESC_NO_OFFSET, VDESC_NO_OFFSET, - VOPARG_OFFSETOF(struct vop_unlock_args, a_p), + VDESC_NO_OFFSET, VDESC_NO_OFFSET, NULL, }; @@ -656,22 +624,6 @@ struct vnodeop_desc vop_valloc_desc = { NULL, }; -int vop_balloc_vp_offsets[] = { - VOPARG_OFFSETOF(struct vop_balloc_args,a_vp), - VDESC_NO_OFFSET -}; -struct vnodeop_desc vop_balloc_desc = { - 0, - "vop_balloc", - 0, - vop_balloc_vp_offsets, - VDESC_NO_OFFSET, - VOPARG_OFFSETOF(struct vop_balloc_args, a_cred), - VDESC_NO_OFFSET, - VDESC_NO_OFFSET, - NULL, -}; - int vop_reallocblks_vp_offsets[] = { VOPARG_OFFSETOF(struct vop_reallocblks_args,a_vp), VDESC_NO_OFFSET @@ -736,6 +688,22 @@ struct vnodeop_desc vop_update_desc = { NULL, }; +int vop_lease_vp_offsets[] = { + VOPARG_OFFSETOF(struct vop_lease_args,a_vp), + VDESC_NO_OFFSET +}; +struct vnodeop_desc vop_lease_desc = { + 0, + "vop_lease", + 0, + vop_lease_vp_offsets, + VDESC_NO_OFFSET, + VOPARG_OFFSETOF(struct vop_lease_args, a_cred), + VOPARG_OFFSETOF(struct vop_lease_args, a_p), + VDESC_NO_OFFSET, + NULL, +}; + int vop_whiteout_vp_offsets[] = { VOPARG_OFFSETOF(struct vop_whiteout_args,a_dvp), VDESC_NO_OFFSET @@ -801,10 +769,8 @@ struct vnodeop_desc *vfs_op_descs[] = { &vop_setattr_desc, &vop_read_desc, &vop_write_desc, - &vop_lease_desc, &vop_ioctl_desc, &vop_select_desc, - &vop_revoke_desc, &vop_mmap_desc, &vop_fsync_desc, &vop_seek_desc, @@ -828,11 +794,11 @@ struct vnodeop_desc *vfs_op_descs[] = { &vop_advlock_desc, &vop_blkatoff_desc, &vop_valloc_desc, - &vop_balloc_desc, &vop_reallocblks_desc, &vop_vfree_desc, &vop_truncate_desc, &vop_update_desc, + &vop_lease_desc, &vop_whiteout_desc, NULL }; diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 76edff456c6..33196d9cc51 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -1,4 +1,4 @@ -# $OpenBSD: vnode_if.src,v 1.5 1997/10/06 15:12:48 csapuntz Exp $ +# $OpenBSD: vnode_if.src,v 1.6 1997/10/06 20:20:17 deraadt Exp $ # $NetBSD: vnode_if.src,v 1.10 1996/05/11 18:26:27 mycroft Exp $ # # Copyright (c) 1992, 1993 @@ -34,43 +34,12 @@ # # @(#)vnode_if.src 8.3 (Berkeley) 2/3/94 # - - -# -# Above each of the vop descriptors is a specification of the locking -# protocol used by each vop call. The first column is the name of -# the variable, the remaining three columns are in, out and error -# respectively. The "in" column defines the lock state on input, -# the "out" column defines the state on succesful return, and the -# "error" column defines the locking state on error exit. -# -# The locking value can take the following values: -# L: locked. -# U: unlocked/ -# -: not applicable. vnode does not yet (or no longer) exists. -# =: the same on input and output, may be either L or U. -# X: locked if not nil. -# - -# -#% lookup dvp L ? ? -#% lookup vpp - L - -# -# XXX - the lookup locking protocol defies simple description and depends -# on the flags and operation fields in the (cnp) structure. Note -# especially that *vpp may equal dvp and both may be locked. - vop_lookup { IN struct vnode *dvp; INOUT struct vnode **vpp; IN struct componentname *cnp; }; -# -#% create dvp L U U -#% create vpp - L - -# - vop_create { IN WILLRELE struct vnode *dvp; OUT struct vnode **vpp; @@ -78,11 +47,6 @@ vop_create { IN struct vattr *vap; }; -# -#% mknod dvp L U U -#% mknod vpp - X - -# - vop_mknod { IN WILLRELE struct vnode *dvp; OUT WILLRELE struct vnode **vpp; @@ -90,10 +54,6 @@ vop_mknod { IN struct vattr *vap; }; -# -#% open vp L L L -# - vop_open { IN struct vnode *vp; IN int mode; @@ -101,10 +61,6 @@ vop_open { IN struct proc *p; }; -# -#% close vp U U U -# - vop_close { IN struct vnode *vp; IN int fflag; @@ -112,10 +68,6 @@ vop_close { IN struct proc *p; }; -# -#% access vp L L L -# - vop_access { IN struct vnode *vp; IN int mode; @@ -123,10 +75,6 @@ vop_access { IN struct proc *p; }; -# -#% getattr vp = = = -# - vop_getattr { IN struct vnode *vp; IN struct vattr *vap; @@ -134,11 +82,6 @@ vop_getattr { IN struct proc *p; }; - -# -#% setattr vp L L L -# - vop_setattr { IN struct vnode *vp; IN struct vattr *vap; @@ -146,10 +89,6 @@ vop_setattr { IN struct proc *p; }; -# -#% read vp L L L -# - vop_read { IN struct vnode *vp; INOUT struct uio *uio; @@ -157,10 +96,6 @@ vop_read { IN struct ucred *cred; }; -# -#% write vp L L L -# - vop_write { IN struct vnode *vp; INOUT struct uio *uio; @@ -168,20 +103,6 @@ vop_write { IN struct ucred *cred; }; -# -#% lease vp = = = -# -vop_lease { - IN struct vnode *vp; - IN struct proc *p; - IN struct ucred *cred; - IN int flag; -}; - -# -#% ioctl vp U U U -# - vop_ioctl { IN struct vnode *vp; IN u_long command; @@ -191,11 +112,7 @@ vop_ioctl { IN struct proc *p; }; -# -#% select vp U U U -# # Needs work? (fflags) -# vop_select { IN struct vnode *vp; IN int which; @@ -204,17 +121,6 @@ vop_select { IN struct proc *p; }; -# -#% revoke vp U U U -# -vop_revoke { - IN struct vnode *vp; - IN int flags; -}; - -# -# XXX - not used -# vop_mmap { IN struct vnode *vp; IN int fflags; @@ -222,9 +128,6 @@ vop_mmap { IN struct proc *p; }; -# -#% fsync vp L L L -# vop_fsync { IN struct vnode *vp; IN struct ucred *cred; @@ -232,10 +135,7 @@ vop_fsync { IN struct proc *p; }; -# -# XXX - not used -# Needs work: Is newoff right? What's it mean? -# +# Needs word: Is newoff right? What's it mean? vop_seek { IN struct vnode *vp; IN off_t oldoff; @@ -243,34 +143,18 @@ vop_seek { IN struct ucred *cred; }; -# -#% remove dvp L U U -#% remove vp L U U -# - vop_remove { IN WILLRELE struct vnode *dvp; IN WILLRELE struct vnode *vp; IN struct componentname *cnp; }; -# -#% link vp U U U -#% link tdvp L U U -# vop_link { IN WILLRELE struct vnode *dvp; IN struct vnode *vp; IN struct componentname *cnp; }; -# -#% rename fdvp U U U -#% rename fvp U U U -#% rename tdvp L U U -#% rename tvp X U U -# - vop_rename { IN WILLRELE struct vnode *fdvp; IN WILLRELE struct vnode *fvp; @@ -280,11 +164,6 @@ vop_rename { IN struct componentname *tcnp; }; -# -#% mkdir dvp L U U -#% mkdir vpp - L - -# - vop_mkdir { IN WILLRELE struct vnode *dvp; OUT struct vnode **vpp; @@ -292,26 +171,12 @@ vop_mkdir { IN struct vattr *vap; }; -# -#% rmdir dvp L U U -#% rmdir vp L U U -# - vop_rmdir { IN WILLRELE struct vnode *dvp; IN WILLRELE struct vnode *vp; IN struct componentname *cnp; }; -# -#% symlink dvp L U U -#% symlink vpp - U - -# -# XXX - note that the return vnode has already been VRELE'ed -# by the filesystem layer. To use it you must use vget, -# possibly with a further namei. -# - vop_symlink { IN WILLRELE struct vnode *dvp; OUT WILLRELE struct vnode **vpp; @@ -320,79 +185,42 @@ vop_symlink { IN char *target; }; -# -#% readdir vp L L L -# - vop_readdir { IN struct vnode *vp; INOUT struct uio *uio; IN struct ucred *cred; - INOUT int *eofflag; - OUT int *ncookies; - INOUT u_long **cookies; + OUT int *eofflag; + OUT u_long *cookies; + IN int ncookies; }; -# -#% readlink vp L L L -# vop_readlink { IN struct vnode *vp; INOUT struct uio *uio; IN struct ucred *cred; }; -# -#% abortop dvp = = = -# vop_abortop { IN struct vnode *dvp; IN struct componentname *cnp; }; - -# -#% inactive vp L U U -# vop_inactive { IN struct vnode *vp; - IN struct proc *p; }; -# -#% reclaim vp U U U -# - vop_reclaim { IN struct vnode *vp; - IN struct proc *p; }; -# -#% lock vp U L U -# - vop_lock { IN struct vnode *vp; - IN int flags; - IN struct proc *p; }; -# -#% unlock vp L U L -# - vop_unlock { IN struct vnode *vp; - IN int flags; - IN struct proc *p; }; -# -#% bmap vp L L L -#% bmap vpp - U - -# - vop_bmap { IN struct vnode *vp; IN daddr_t bn; @@ -401,39 +229,24 @@ vop_bmap { OUT int *runp; }; -# -# Needs work: no vp? -# #vop_strategy { # IN struct buf *bp; #}; -# -#% print vp = = = -# vop_print { IN struct vnode *vp; }; -# -#% islocked vp = = = -# vop_islocked { IN struct vnode *vp; }; -# -#% pathconf vp L L L -# vop_pathconf { IN struct vnode *vp; IN int name; OUT register_t *retval; }; -# -#% advlock vp U U U -# vop_advlock { IN struct vnode *vp; IN caddr_t id; @@ -442,9 +255,6 @@ vop_advlock { IN int flags; }; -# -#% blkatoff vp L L L -# vop_blkatoff { IN struct vnode *vp; IN off_t offset; @@ -452,9 +262,6 @@ vop_blkatoff { OUT struct buf **bpp; }; -# -#% valloc pvp L L L -# vop_valloc { IN struct vnode *pvp; IN int mode; @@ -462,40 +269,17 @@ vop_valloc { OUT struct vnode **vpp; }; -# -#% balloc vp L L L -# -vop_balloc { - IN struct vnode *vp; - IN off_t startoffset; - IN int size; - IN struct ucred *cred; - IN int flags; - OUT struct buf **bpp; -}; - -# -#% reallocblks vp L L L -# vop_reallocblks { IN struct vnode *vp; IN struct cluster_save *buflist; }; -# -#% vfree pvp L L L -# - vop_vfree { IN struct vnode *pvp; IN ino_t ino; IN int mode; }; -# -#% truncate vp L L L -# - vop_truncate { IN struct vnode *vp; IN off_t length; @@ -504,10 +288,6 @@ vop_truncate { IN struct proc *p; }; -# -#% update vp L L L -# - vop_update { IN struct vnode *vp; IN struct timespec *access; @@ -515,11 +295,12 @@ vop_update { IN int waitfor; }; -# -#% whiteout dvp L L L -#% whiteout cnp - - - -#% whiteout flag - - - -# +vop_lease { + IN struct vnode *vp; + IN struct proc *p; + IN struct ucred *cred; + IN int flag; +}; vop_whiteout { IN struct vnode *dvp; |