Merge with Lite2 + local changes trunk
authorfvdl <fvdl@NetBSD.org>
Sun, 01 Mar 1998 02:20:01 +0000
branchtrunk
changeset 37443 5f72269cb09c
parent 37442 a6e387be53d0
child 37444 049dc0e217b4
Merge with Lite2 + local changes
bin/df/df.c
libexec/lfs_cleanerd/clean.h
libexec/lfs_cleanerd/cleanerd.c
libexec/lfs_cleanerd/library.c
sbin/fsck_ext2fs/main.c
sbin/fsck_ext2fs/pass5.c
sbin/fsck_ffs/main.c
sbin/mount_ados/Makefile
sbin/mount_ados/mount_ados.c
sbin/mount_cd9660/mount_cd9660.c
sbin/mount_ext2fs/mount_ext2fs.c
sbin/mount_ffs/mount_ffs.c
sbin/mount_lfs/mount_lfs.c
sbin/mount_msdos/Makefile
sbin/mount_msdos/mount_msdos.c
sbin/mount_nfs/mount_nfs.c
sbin/newfs/newfs.c
sbin/newlfs/config.h
sbin/newlfs/extern.h
sbin/newlfs/lfs.c
sbin/newlfs/newfs.c
sys/adosfs/adlookup.c
sys/adosfs/adosfs.h
sys/adosfs/adutil.c
sys/adosfs/advfsops.c
sys/adosfs/advnops.c
sys/compat/common/tty_43.c
sys/compat/common/vfs_syscalls_43.c
sys/compat/ibcs2/ibcs2_misc.c
sys/compat/linux/common/linux_break.c
sys/compat/linux/common/linux_misc.c
sys/compat/linux/common/linux_misc_notalpha.c
sys/compat/linux/common/linux_oldmmap.c
sys/compat/linux/common/linux_oldolduname.c
sys/compat/linux/common/linux_oldselect.c
sys/compat/linux/common/linux_olduname.c
sys/compat/linux/common/linux_pipe.c
sys/compat/linux/linux_misc.c
sys/compat/linux/multiarch/linux_break.c
sys/compat/linux/multiarch/linux_misc_notalpha.c
sys/compat/linux/multiarch/linux_oldmmap.c
sys/compat/linux/multiarch/linux_oldolduname.c
sys/compat/linux/multiarch/linux_oldselect.c
sys/compat/linux/multiarch/linux_olduname.c
sys/compat/linux/multiarch/linux_pipe.c
sys/compat/sunos/sunos_misc.c
sys/compat/svr4/svr4_fcntl.c
sys/compat/svr4/svr4_misc.c
sys/dev/vnd.c
sys/isofs/cd9660/cd9660_extern.h
sys/isofs/cd9660/cd9660_lookup.c
sys/isofs/cd9660/cd9660_node.c
sys/isofs/cd9660/cd9660_node.h
sys/isofs/cd9660/cd9660_vfsops.c
sys/isofs/cd9660/cd9660_vnops.c
sys/isofs/cd9660/iso.h
sys/kern/exec_elf32.c
sys/kern/exec_script.c
sys/kern/init_main.c
sys/kern/kern_acct.c
sys/kern/kern_descrip.c
sys/kern/kern_exec.c
sys/kern/kern_exit.c
sys/kern/kern_fork.c
sys/kern/kern_ktrace.c
sys/kern/kern_lock.c
sys/kern/kern_malloc.c
sys/kern/kern_proc.c
sys/kern/kern_prot.c
sys/kern/kern_resource.c
sys/kern/kern_sig.c
sys/kern/kern_subr.c
sys/kern/kern_synch.c
sys/kern/kern_sysctl.c
sys/kern/kern_time.c
sys/kern/kern_xxx.c
sys/kern/subr_autoconf.c
sys/kern/subr_log.c
sys/kern/subr_prf.c
sys/kern/subr_prof.c
sys/kern/subr_xxx.c
sys/kern/sys_generic.c
sys/kern/sys_socket.c
sys/kern/tty.c
sys/kern/tty_conf.c
sys/kern/tty_pty.c
sys/kern/tty_tb.c
sys/kern/tty_tty.c
sys/kern/uipc_domain.c
sys/kern/uipc_mbuf.c
sys/kern/uipc_proto.c
sys/kern/uipc_socket.c
sys/kern/uipc_socket2.c
sys/kern/uipc_syscalls.c
sys/kern/uipc_usrreq.c
sys/kern/vfs_cache.c
sys/kern/vfs_cluster.c
sys/kern/vfs_init.c
sys/kern/vfs_lockf.c
sys/kern/vfs_lookup.c
sys/kern/vfs_subr.c
sys/kern/vfs_syscalls.c
sys/kern/vfs_vnops.c
sys/kern/vnode_if.c
sys/kern/vnode_if.sh
sys/kern/vnode_if.src
sys/lib/libkern/libkern.h
sys/lkm/netinet/if_ipl/mln_ipl.c
sys/miscfs/deadfs/dead_vnops.c
sys/miscfs/fdesc/fdesc.h
sys/miscfs/fdesc/fdesc_vfsops.c
sys/miscfs/fdesc/fdesc_vnops.c
sys/miscfs/fifofs/fifo.h
sys/miscfs/fifofs/fifo_vnops.c
sys/miscfs/genfs/genfs.h
sys/miscfs/genfs/genfs_vnops.c
sys/miscfs/kernfs/kernfs.h
sys/miscfs/kernfs/kernfs_vfsops.c
sys/miscfs/kernfs/kernfs_vnops.c
sys/miscfs/nullfs/null_subr.c
sys/miscfs/nullfs/null_vfsops.c
sys/miscfs/nullfs/null_vnops.c
sys/miscfs/portal/portal_vfsops.c
sys/miscfs/portal/portal_vnops.c
sys/miscfs/procfs/procfs.h
sys/miscfs/procfs/procfs_subr.c
sys/miscfs/procfs/procfs_vfsops.c
sys/miscfs/procfs/procfs_vnops.c
sys/miscfs/specfs/spec_vnops.c
sys/miscfs/specfs/specdev.h
sys/miscfs/umapfs/umap.h
sys/miscfs/umapfs/umap_subr.c
sys/miscfs/umapfs/umap_vfsops.c
sys/miscfs/umapfs/umap_vnops.c
sys/miscfs/union/union_subr.c
sys/miscfs/union/union_vfsops.c
sys/miscfs/union/union_vnops.c
sys/msdosfs/denode.h
sys/msdosfs/msdosfs_denode.c
sys/msdosfs/msdosfs_lookup.c
sys/msdosfs/msdosfs_vfsops.c
sys/msdosfs/msdosfs_vnops.c
sys/msdosfs/msdosfsmount.h
sys/net/bpf.c
sys/net/bpf.h
sys/net/if.c
sys/net/if.h
sys/net/if_ethersubr.c
sys/net/if_loop.c
sys/net/if_sl.c
sys/net/if_slvar.h
sys/net/if_types.h
sys/net/radix.c
sys/net/rtsock.c
sys/netccitt/llc_var.h
sys/netccitt/pk_acct.c
sys/netccitt/pk_llcsubr.c
sys/netccitt/pk_output.c
sys/netccitt/pk_usrreq.c
sys/netiso/esis.c
sys/netiso/if_eon.c
sys/netiso/iso.c
sys/netiso/iso.h
sys/netiso/iso_pcb.c
sys/netiso/iso_proto.c
sys/netiso/iso_snpac.c
sys/netiso/tp_iso.c
sys/netiso/tp_output.c
sys/netiso/tp_pcb.h
sys/netiso/tuba_table.c
sys/netiso/tuba_table.h
sys/netns/idp_usrreq.c
sys/netns/ns.c
sys/netns/ns_error.c
sys/netns/ns_input.c
sys/netns/ns_ip.c
sys/netns/ns_proto.c
sys/netns/spp_usrreq.c
sys/nfs/krpc_subr.c
sys/nfs/nfs_boot.c
sys/nfs/nfs_node.c
sys/nfs/nfs_nqlease.c
sys/nfs/nfs_serv.c
sys/nfs/nfs_subs.c
sys/nfs/nfs_vfsops.c
sys/nfs/nfs_vnops.c
sys/nfs/nfsmount.h
sys/nfs/nfsnode.h
sys/sys/buf.h
sys/sys/cdefs.h
sys/sys/conf.h
sys/sys/disk.h
sys/sys/exec.h
sys/sys/file.h
sys/sys/ioccom.h
sys/sys/ipc.h
sys/sys/ktrace.h
sys/sys/lock.h
sys/sys/lockf.h
sys/sys/malloc.h
sys/sys/mman.h
sys/sys/mount.h
sys/sys/namei.h
sys/sys/param.h
sys/sys/proc.h
sys/sys/reboot.h
sys/sys/resource.h
sys/sys/resourcevar.h
sys/sys/signal.h
sys/sys/signalvar.h
sys/sys/socket.h
sys/sys/socketvar.h
sys/sys/stat.h
sys/sys/sysctl.h
sys/sys/systm.h
sys/sys/tablet.h
sys/sys/time.h
sys/sys/tty.h
sys/sys/types.h
sys/sys/ucred.h
sys/sys/un.h
sys/sys/vnode.h
sys/sys/vnode_if.h
sys/ufs/ext2fs/ext2fs.h
sys/ufs/ext2fs/ext2fs_alloc.c
sys/ufs/ext2fs/ext2fs_balloc.c
sys/ufs/ext2fs/ext2fs_bmap.c
sys/ufs/ext2fs/ext2fs_extern.h
sys/ufs/ext2fs/ext2fs_inode.c
sys/ufs/ext2fs/ext2fs_lookup.c
sys/ufs/ext2fs/ext2fs_readwrite.c
sys/ufs/ext2fs/ext2fs_subr.c
sys/ufs/ext2fs/ext2fs_vfsops.c
sys/ufs/ext2fs/ext2fs_vnops.c
sys/ufs/ffs/ffs_alloc.c
sys/ufs/ffs/ffs_balloc.c
sys/ufs/ffs/ffs_extern.h
sys/ufs/ffs/ffs_inode.c
sys/ufs/ffs/ffs_subr.c
sys/ufs/ffs/ffs_vfsops.c
sys/ufs/ffs/ffs_vnops.c
sys/ufs/ffs/fs.h
sys/ufs/lfs/lfs.h
sys/ufs/lfs/lfs_alloc.c
sys/ufs/lfs/lfs_balloc.c
sys/ufs/lfs/lfs_bio.c
sys/ufs/lfs/lfs_cksum.c
sys/ufs/lfs/lfs_debug.c
sys/ufs/lfs/lfs_extern.h
sys/ufs/lfs/lfs_inode.c
sys/ufs/lfs/lfs_segment.c
sys/ufs/lfs/lfs_subr.c
sys/ufs/lfs/lfs_syscalls.c
sys/ufs/lfs/lfs_vfsops.c
sys/ufs/lfs/lfs_vnops.c
sys/ufs/mfs/mfs_extern.h
sys/ufs/mfs/mfs_vfsops.c
sys/ufs/mfs/mfs_vnops.c
sys/ufs/mfs/mfsnode.h
sys/ufs/ufs/dinode.h
sys/ufs/ufs/dir.h
sys/ufs/ufs/inode.h
sys/ufs/ufs/ufs_bmap.c
sys/ufs/ufs/ufs_extern.h
sys/ufs/ufs/ufs_ihash.c
sys/ufs/ufs/ufs_inode.c
sys/ufs/ufs/ufs_lookup.c
sys/ufs/ufs/ufs_quota.c
sys/ufs/ufs/ufs_readwrite.c
sys/ufs/ufs/ufs_vfsops.c
sys/ufs/ufs/ufs_vnops.c
sys/ufs/ufs/ufsmount.h
sys/uvm/uvm.h
sys/uvm/uvm_anon.h
sys/uvm/uvm_aobj.c
sys/uvm/uvm_device.c
sys/uvm/uvm_map.c
sys/uvm/uvm_swap.c
sys/uvm/uvm_vnode.c
sys/vm/vm.h
sys/vm/vm_extern.h
sys/vm/vm_fault.c
sys/vm/vm_glue.c
sys/vm/vm_kern.c
sys/vm/vm_map.c
sys/vm/vm_map.h
sys/vm/vm_meter.c
sys/vm/vm_mmap.c
sys/vm/vm_object.c
sys/vm/vm_object.h
sys/vm/vm_page.c
sys/vm/vm_page.h
sys/vm/vm_pageout.c
sys/vm/vm_pageout.h
sys/vm/vm_pager.c
sys/vm/vm_pager.h
sys/vm/vm_param.h
sys/vm/vm_swap.c
sys/vm/vm_unix.c
sys/vm/vnode_pager.c
usr.sbin/amd/include/amu_nfs_prot.h
usr.sbin/bad144/bad144.c
usr.sbin/dumplfs/Makefile
usr.sbin/dumplfs/dumplfs.c
usr.sbin/dumplfs/extern.h
usr.sbin/dumplfs/misc.c
usr.sbin/mountd/mountd.c
usr.sbin/pstat/pstat.c
usr.sbin/quot/quot.c
usr.sbin/sysctl/sysctl.c
--- a/bin/df/df.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/bin/df/df.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: df.c,v 1.24 1997/07/20 06:00:39 thorpej Exp $	*/
+/*	$NetBSD: df.c,v 1.25 1998/03/01 02:20:01 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1980, 1990, 1993, 1994
@@ -49,13 +49,14 @@
 #if 0
 static char sccsid[] = "@(#)df.c	8.7 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: df.c,v 1.24 1997/07/20 06:00:39 thorpej Exp $");
+__RCSID("$NetBSD: df.c,v 1.25 1998/03/01 02:20:01 fvdl Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/mount.h>
+#include <ufs/ufs/ufsmount.h>
 
 #include <err.h>
 #include <errno.h>
@@ -355,6 +356,7 @@
  * This code constitutes the pre-system call Berkeley df code for extracting
  * information from filesystem superblocks.
  */
+#include <ufs/ufs/dinode.h>
 #include <ufs/ffs/fs.h>
 #include <errno.h>
 #include <fstab.h>
--- a/libexec/lfs_cleanerd/clean.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/libexec/lfs_cleanerd/clean.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: clean.h,v 1.3 1997/10/07 13:44:03 mrg Exp $	*/
+/*	$NetBSD: clean.h,v 1.4 1998/03/01 02:20:07 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	from: @(#)clean.h	8.1 (Berkeley) 6/4/93
+ *	@(#)clean.h	8.2 (Berkeley) 5/4/95
  */
 
 /*
--- a/libexec/lfs_cleanerd/cleanerd.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/libexec/lfs_cleanerd/cleanerd.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: cleanerd.c,v 1.4 1997/10/20 02:04:03 enami Exp $	*/
+/*	$NetBSD: cleanerd.c,v 1.5 1998/03/01 02:20:07 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993
@@ -38,9 +38,9 @@
 __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
 	The Regents of the University of California.  All rights reserved.\n");
 #if 0
-static char sccsid[] = "from: @(#)cleanerd.c	8.2 (Berkeley) 1/13/94";
+static char sccsid[] = "@(#)cleanerd.c	8.5 (Berkeley) 6/10/95";
 #else
-__RCSID("$NetBSD: cleanerd.c,v 1.4 1997/10/20 02:04:03 enami Exp $");
+__RCSID("$NetBSD: cleanerd.c,v 1.5 1998/03/01 02:20:07 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -60,7 +60,10 @@
 char *special = "cleanerd";
 int do_small = 0;
 int do_mmap = 0;
+int stat_report = 0;
 struct cleaner_stats {
+	double	util_tot;
+	double	util_sos;
 	int	blocks_read;
 	int	blocks_written;
 	int	segs_cleaned;
@@ -71,7 +74,7 @@
 struct seglist { 
 	int sl_id;	/* segment number */
 	int sl_cost; 	/* cleaning cost */
-	char sl_empty;	/* is segment empty */
+	char sl_bytes;	/* bytets in segment */
 };
 
 struct tossstruct {
@@ -79,6 +82,8 @@
 	int seg;
 };
 
+#define	CLEAN_BYTES	0x1
+
 /* function prototypes for system calls; not sure where they should go */
 int	 lfs_segwait __P((fsid_t *, struct timeval *));
 int	 lfs_segclean __P((fsid_t *, u_long));
@@ -89,8 +94,8 @@
 int	 bi_tossold __P((const void *, const void *, const void *));
 int	 choose_segments __P((FS_INFO *, struct seglist *, 
 	     int (*)(FS_INFO *, SEGUSE *)));
-void	 clean_fs __P((FS_INFO	*, int (*)(FS_INFO *, SEGUSE *)));
-int	 clean_loop __P((FS_INFO *));
+void	 clean_fs __P((FS_INFO	*, int (*)(FS_INFO *, SEGUSE *), int, long));
+int	 clean_loop __P((FS_INFO *, int, long));
 int	 clean_segment __P((FS_INFO *, int));
 int	 cost_benefit __P((FS_INFO *, SEGUSE *));
 int	 cost_compare __P((const void *, const void *));
@@ -156,21 +161,37 @@
 	struct statfs *lstatfsp;	/* file system stats */
 	struct timeval timeout;		/* sleep timeout */
 	fsid_t fsid;
-	int nodaemon;
+	long clean_opts;		/* cleaning options */
+	int nodaemon, segs_per_clean;
 	int opt, cmd_err;
 	char *fs_name;			/* name of filesystem to clean */
 
 	cmd_err = nodaemon = 0;
+	clean_opts = 0;
+	segs_per_clean = 1;
 	while ((opt = getopt(argc, argv, "smd")) != -1) {
 		switch (opt) {
-			case 's':	/* small writes */
-				do_small = 1;
+			case 'b':
+				/*
+				 * Use live bytes to determine
+				 * how many segs to clean.
+				 */
+				clean_opts |= CLEAN_BYTES;
+				break;
+			case 'd':	/* Debug mode. */
+				nodaemon = 1;
 				break;
 			case 'm':
 				do_mmap = 1;
 				break;
-			case 'd':
-				nodaemon = 1;
+			case 'n':	/* How many segs to clean at once */
+				segs_per_clean = atoi(optarg);
+				break;
+			case 'r':	/* Report every stat_report segments */
+				stat_report = atoi(optarg);
+				break;
+			case 's':	/* small writes */
+				do_small = 1;
 				break;
 			default:
 				++cmd_err;
@@ -208,7 +229,7 @@
 		 * to make sure that some nasty process hasn't just
 		 * filled the disk system up.
 		 */
-		if (clean_loop(fsp))
+		if (clean_loop(fsp, segs_per_clean, clean_opts))
 			continue;
 
 #ifdef VERBOSE
@@ -224,17 +245,21 @@
 
 /* return the number of segments cleaned */
 int
-clean_loop(fsp)
+clean_loop(fsp, nsegs, options)
 	FS_INFO	*fsp;	/* file system information */
+	int nsegs;
+	long options;
 {
 	double loadavg[MAXLOADS];
 	time_t	now;
 	u_long max_free_segs;
+	u_long db_per_seg;
 
         /*
 	 * Compute the maximum possible number of free segments, given the
 	 * number of free blocks.
 	 */
+	db_per_seg = fsbtodb(&fsp->fi_lfs, fsp->fi_lfs.lfs_ssize);
 	max_free_segs = fsp->fi_statfsp->f_bfree / fsp->fi_lfs.lfs_ssize;
 	
 	/* 
@@ -242,12 +267,20 @@
 	 * space is less than BUSY_LIM % of possible clean space.
 	 */
 	now = time((time_t *)NULL);
-	if (fsp->fi_cip->clean < max_free_segs &&
+#ifdef VERBOSE
+	printf("db_per_seg = %lu max_free_segs = %lu, bfree = %u avail = %d ",
+	    db_per_seg, max_free_segs, fsp->fi_lfs.lfs_bfree,
+	    fsp->fi_lfs.lfs_avail);
+	printf("clean = %d\n", fsp->fi_cip->clean);
+#endif
+	if ((fsp->fi_lfs.lfs_bfree - fsp->fi_lfs.lfs_avail > db_per_seg &&
+	    fsp->fi_lfs.lfs_avail < db_per_seg) ||
+	    (fsp->fi_cip->clean < max_free_segs &&
 	    (fsp->fi_cip->clean <= MIN_SEGS(&fsp->fi_lfs) ||
-	    fsp->fi_cip->clean < max_free_segs * BUSY_LIM)) {
-		printf("Cleaner Running  at %s (%d of %ld segments available)\n",
+	    fsp->fi_cip->clean < max_free_segs * BUSY_LIM))) {
+		printf("Cleaner Running  at %s (%d of %lu segments available)\n",
 		    ctime(&now), fsp->fi_cip->clean, max_free_segs);
-		clean_fs(fsp, cost_benefit);
+		clean_fs(fsp, cost_benefit, nsegs, options);
 		return (1);
 	} else {
 	        /* 
@@ -261,7 +294,7 @@
 		}
 		if (loadavg[ONE_MIN] == 0.0 && loadavg[FIVE_MIN] &&
 		    fsp->fi_cip->clean < max_free_segs * IDLE_LIM) {
-		        clean_fs(fsp, cost_benefit);
+		        clean_fs(fsp, cost_benefit, nsegs, options);
 			printf("Cleaner Running  at %s (system idle)\n",
 			    ctime(&now));
 			return (1);
@@ -273,11 +306,14 @@
 
 
 void
-clean_fs(fsp, cost_func)
+clean_fs(fsp, cost_func, nsegs, options)
 	FS_INFO	*fsp;	/* file system information */
 	int (*cost_func) __P((FS_INFO *, SEGUSE *));
+	int nsegs;
+	long options;
 {
 	struct seglist *segs, *sp;
+	int to_clean, cleaned_bytes;
 	int i;
 
 	if ((segs =
@@ -291,15 +327,33 @@
 		i, fsp->fi_statfsp->f_mntonname);
 	fflush(stdout);
 #endif
-	if (i)
-		for (i = MIN(i, NUM_TO_CLEAN(fsp)), sp = segs; i-- ; ++sp) {
-			if (clean_segment(fsp, sp->sl_id) < 0)
-				perror("clean_segment failed");
-			else if (lfs_segclean(&fsp->fi_statfsp->f_fsid,
-			    sp->sl_id) < 0)
-				perror("lfs_segclean failed");
-			printf("Completed cleaning segment %d\n", sp->sl_id);
-		}
+	if (i) {
+		/* Check which cleaning algorithm to use. */
+		if (options & CLEAN_BYTES) {
+			cleaned_bytes = 0;
+			to_clean = nsegs <<
+			    (fsp->fi_lfs.lfs_segshift + fsp->fi_lfs.lfs_bshift);
+			for (sp = segs; i && cleaned_bytes < to_clean;
+			    i--, ++sp) {
+				if (clean_segment(fsp, sp->sl_id) < 0)
+					perror("clean_segment failed");
+				else if (lfs_segclean(&fsp->fi_statfsp->f_fsid,
+				    sp->sl_id) < 0)
+					perror("lfs_segclean failed");
+				printf("Cleaned segment %d (%d bytes)\n",
+				    sp->sl_id, sp->sl_bytes);
+				cleaned_bytes += sp->sl_bytes;
+			}
+		} else
+			for (i = MIN(i, nsegs), sp = segs; i-- ; ++sp) {
+				if (clean_segment(fsp, sp->sl_id) < 0)
+					perror("clean_segment failed");
+				else if (lfs_segclean(&fsp->fi_statfsp->f_fsid,
+				    sp->sl_id) < 0)
+					perror("lfs_segclean failed");
+				printf("Completed cleaning segment %d\n", sp->sl_id);
+			}
+	}
 	free(segs);
 }
 
@@ -352,7 +406,7 @@
 #endif
 		sp->sl_cost = (*cost_func)(fsp, sup);
 		sp->sl_id = i;
-		sp->sl_empty = sup->su_nbytes ? 0 : 1;
+		sp->sl_bytes = sup->su_nbytes;
 		++sp;
 	}
 	nsegs = sp - seglist;
@@ -373,6 +427,7 @@
 	SEGUSE *sp;
 	struct lfs *lfsp;
 	struct tossstruct t;
+	double util;
 	caddr_t seg_buf;
 	int num_blocks, maxblocks, clean_blocks;
 
@@ -441,7 +496,11 @@
 		}
 	}
 #endif
+	++cleaner_stats.segs_cleaned;
 	cleaner_stats.blocks_written += num_blocks;
+	util = ((double)num_blocks / fsp->fi_lfs.lfs_ssize);
+	cleaner_stats.util_tot += util;
+	cleaner_stats.util_sos += util * util;
 	if (do_small)
 		maxblocks = MAXPHYS / fsp->fi_lfs.lfs_bsize - 1;
 	else
@@ -460,7 +519,8 @@
 		
 	free(block_array);
 	munmap_segment(fsp, seg_buf, do_mmap);
-	++cleaner_stats.segs_cleaned;
+	if (stat_report && cleaner_stats.segs_cleaned % stat_report == 0)
+		sig_report(SIGUSR1);
 	return (0);
 }
 
@@ -483,18 +543,30 @@
 sig_report(sig)
 	int sig;
 {
+	double avg = 0.0;
+
 	printf("lfs_cleanerd:\t%s%d\n\t\t%s%d\n\t\t%s%d\n\t\t%s%d\n\t\t%s%d\n",
 		"blocks_read    ", cleaner_stats.blocks_read,
 		"blocks_written ", cleaner_stats.blocks_written,
 		"segs_cleaned   ", cleaner_stats.segs_cleaned,
 		"segs_empty     ", cleaner_stats.segs_empty,
 		"seg_error      ", cleaner_stats.segs_error);
+	printf("\t\t%s%5.2f\n\t\t%s%5.2f\n",
+		"util_tot       ", cleaner_stats.util_tot,
+		"util_sos       ", cleaner_stats.util_sos);
+	printf("\t\tavg util: %4.2f std dev: %9.6f\n",
+		avg = cleaner_stats.util_tot / cleaner_stats.segs_cleaned,
+		cleaner_stats.util_sos / cleaner_stats.segs_cleaned - avg * avg);
+
+
 	if (sig == SIGUSR2) {
 		cleaner_stats.blocks_read = 0;
 		cleaner_stats.blocks_written = 0;
 		cleaner_stats.segs_cleaned = 0;
 		cleaner_stats.segs_empty = 0;
 		cleaner_stats.segs_error = 0;
+		cleaner_stats.util_tot = 0.0;
+		cleaner_stats.util_sos = 0.0;
 	}
 	if (sig == SIGINT)
 		exit(0);
--- a/libexec/lfs_cleanerd/library.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/libexec/lfs_cleanerd/library.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: library.c,v 1.5 1998/02/20 09:27:20 mycroft Exp $	*/
+/*	$NetBSD: library.c,v 1.6 1998/03/01 02:20:07 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993
@@ -36,9 +36,9 @@
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
-static char sccsid[] = "from: @(#)library.c	8.1 (Berkeley) 6/4/93";
+static char sccsid[] = "@(#)library.c	8.3 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: library.c,v 1.5 1998/02/20 09:27:20 mycroft Exp $");
+__RCSID("$NetBSD: library.c,v 1.6 1998/03/01 02:20:07 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -246,18 +246,8 @@
 	 * and segment usage table multiplied by the number of ifile
 	 * entries per page.
 	 */
-	/*
-	 * XXX this used to read:
-	 *
-	 *	fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift -
-	 *	    fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *
-	 *	    fsp->fi_lfs.lfs_ifpb;
-	 *
-	 * but now has ()'s around the -'s to quell a GCC warning.  This
-	 * may not have been the intended purpose, however!
-	 */
-	fsp->fi_ifile_count = (fsp->fi_ifile_length >> (fsp->fi_lfs.lfs_bshift -
-	    fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz)) *
+	fsp->fi_ifile_count = ((fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift)
+	    - fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *
 	    fsp->fi_lfs.lfs_ifpb;
 
 	free (ifile_name);
@@ -283,12 +273,12 @@
 	SEGUSE *sup;
 	FINFO *fip;
 	struct lfs *lfsp;
-	caddr_t s, segend;
+	caddr_t s;
 	daddr_t pseg_addr, seg_addr;
-	int nelem, nblocks, sumsize;
+	int nelem, nblocks, nsegs, sumsize;
 	time_t timestamp;
-#if defined(VERBOSE) || defined(DIAGNOSTIC)
-	int i = 0;	/* XXX gcc */
+#if defined(DIAGNOSTIC)
+	int i;
 #endif
 
 	i = 0;
@@ -306,18 +296,15 @@
 #endif /* VERBOSE */
 
 	*bcount = 0;
-	for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) {
+	for (nsegs = 0, timestamp = 0; nsegs < sup->su_nsums; nsegs++) {
 		sp = (SEGSUM *)s;
 
-#ifdef VERBOSE
-		printf("\tpartial at: 0x%x\n", pseg_addr);
-		print_SEGSUM(lfsp, sp);
-		fflush(stdout);
-#endif /* VERBOSE */
-
 		nblocks = pseg_valid(fsp, sp);
-		if (nblocks <= 0)
+		if (nblocks <= 0) {
+			printf("Warning: invalid segment summary at 0x%x\n",
+			    pseg_addr);
 			break;
+		}
 
 		/* Check if we have hit old data */
 		if (timestamp > ((SEGSUM*)s)->ss_create)
@@ -328,7 +315,7 @@
 		/* Verfiy size of summary block */
 		sumsize = sizeof(SEGSUM) +
 		    (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
-		for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) {
+		for (i = 0, fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) {
 			sumsize += sizeof(FINFO) +
 			    (fip->fi_nblocks - 1) * sizeof(daddr_t);
 			fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]);
@@ -393,6 +380,7 @@
 	caddr_t	bp;
 	daddr_t	*dp, *iaddrp;
 	int db_per_block, i, j;
+	int db_frag;
 	u_long page_size;
 
 #ifdef VERBOSE
@@ -425,8 +413,24 @@
 			bip->bi_segcreate = (time_t)(sp->ss_create);
 			bip->bi_bp = bp;
 			bip->bi_version = ifp->if_version;
-			psegaddr += db_per_block;
-			bp += page_size;
+			if (fip->fi_lastlength == page_size) {
+				bip->bi_size = page_size;
+				psegaddr += db_per_block;
+				bp += page_size;
+			} else {
+				db_frag = fragstodb(&(fsp->fi_lfs),
+				    numfrags(&(fsp->fi_lfs),
+				    fip->fi_lastlength));
+#ifdef VERBOSE
+				printf("lastlength, frags: %d, %d, %d\n",
+				    fip->fi_lastlength, temp,
+				    bytetoda(fsp, temp));
+				fflush(stdout);
+#endif
+				bip->bi_size = fip->fi_lastlength;
+				bp += fip->fi_lastlength;
+				psegaddr += db_frag;
+			}
 			++bip;
 			++(*countp);
 		}
@@ -511,6 +515,9 @@
 	int i, nblocks;
 	u_long *datap;
 
+	if (ssp->ss_magic != SS_MAGIC)
+		return(0);
+
 	if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 ||
 	    nblocks > fsp->fi_lfs.lfs_ssize - 1)
 		return(0);
--- a/sbin/fsck_ext2fs/main.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/fsck_ext2fs/main.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.3 1997/10/01 02:15:48 enami Exp $	*/
+/*	$NetBSD: main.c,v 1.4 1998/03/01 02:20:25 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1997 Manuel Bouyer.
@@ -44,13 +44,14 @@
 #if 0
 static char sccsid[] = "@(#)main.c	8.2 (Berkeley) 1/23/94";
 #else
-__RCSID("$NetBSD: main.c,v 1.3 1997/10/01 02:15:48 enami Exp $");
+__RCSID("$NetBSD: main.c,v 1.4 1998/03/01 02:20:25 fvdl Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/mount.h>
+#include <ufs/ufs/ufsmount.h>
 #include <ufs/ext2fs/ext2fs_dinode.h>
 #include <ufs/ext2fs/ext2fs.h>
 #include <fstab.h>
--- a/sbin/fsck_ext2fs/pass5.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/fsck_ext2fs/pass5.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: pass5.c,v 1.4 1997/10/09 13:19:39 bouyer Exp $	*/
+/*	$NetBSD: pass5.c,v 1.5 1998/03/01 02:20:25 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1997 Manuel Bouyer.
@@ -39,12 +39,13 @@
 #if 0
 static char sccsid[] = "@(#)pass5.c	8.6 (Berkeley) 11/30/94";
 #else
-__RCSID("$NetBSD: pass5.c,v 1.4 1997/10/09 13:19:39 bouyer Exp $");
+__RCSID("$NetBSD: pass5.c,v 1.5 1998/03/01 02:20:25 fvdl Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/time.h>
+#include <ufs/ufs/dinode.h>
 #include <ufs/ext2fs/ext2fs_dinode.h>
 #include <ufs/ext2fs/ext2fs.h>
 #include <ufs/ext2fs/ext2fs_extern.h>
--- a/sbin/fsck_ffs/main.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/fsck_ffs/main.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.29 1997/11/02 01:42:44 mjacob Exp $	*/
+/*	$NetBSD: main.c,v 1.30 1998/03/01 02:20:37 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -43,7 +43,7 @@
 #if 0
 static char sccsid[] = "@(#)main.c	8.6 (Berkeley) 5/14/95";
 #else
-__RCSID("$NetBSD: main.c,v 1.29 1997/11/02 01:42:44 mjacob Exp $");
+__RCSID("$NetBSD: main.c,v 1.30 1998/03/01 02:20:37 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -53,6 +53,7 @@
 #include <sys/resource.h>
 
 #include <ufs/ufs/dinode.h>
+#include <ufs/ufs/ufsmount.h>
 #include <ufs/ffs/fs.h>
 
 #include <ctype.h>
--- a/sbin/mount_ados/Makefile	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_ados/Makefile	Sun Mar 01 02:20:01 1998 +0000
@@ -1,11 +1,11 @@
-#	$NetBSD: Makefile,v 1.7 1997/10/10 19:49:02 christos Exp $
+#	$NetBSD: Makefile,v 1.8 1998/03/01 02:20:11 fvdl Exp $
 
 PROG=	mount_ados
 SRCS=	mount_ados.c getmntopts.c
 MAN=	mount_ados.8
 
 MOUNT=	${.CURDIR}/../mount
-CPPFLAGS+= -I${MOUNT}
+CPPFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
 .PATH:	${MOUNT}
 
 .include <bsd.prog.mk>
--- a/sbin/mount_ados/mount_ados.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_ados/mount_ados.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount_ados.c,v 1.7 1997/09/16 12:23:34 lukem Exp $	*/
+/*	$NetBSD: mount_ados.c,v 1.8 1998/03/01 02:20:11 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christopher G. Demetriou
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mount_ados.c,v 1.7 1997/09/16 12:23:34 lukem Exp $");
+__RCSID("$NetBSD: mount_ados.c,v 1.8 1998/03/01 02:20:11 fvdl Exp $");
 #endif /* not lint */
 
 #include <sys/cdefs.h>
@@ -48,6 +48,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <adosfs/adosfs.h>
+
 #include "mntopts.h"
 
 const struct mntopt mopts[] = {
--- a/sbin/mount_cd9660/mount_cd9660.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_cd9660/mount_cd9660.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount_cd9660.c,v 1.5 1997/09/16 12:25:36 lukem Exp $	*/
+/*	$NetBSD: mount_cd9660.c,v 1.6 1998/03/01 02:20:17 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1994
@@ -50,7 +50,7 @@
 #if 0
 static char sccsid[] = "@(#)mount_cd9660.c	8.7 (Berkeley) 5/1/95";
 #else
-__RCSID("$NetBSD: mount_cd9660.c,v 1.5 1997/09/16 12:25:36 lukem Exp $");
+__RCSID("$NetBSD: mount_cd9660.c,v 1.6 1998/03/01 02:20:17 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -63,6 +63,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <isofs/cd9660/cd9660_mount.h>
+
 #include "mntopts.h"
 
 const struct mntopt mopts[] = {
--- a/sbin/mount_ext2fs/mount_ext2fs.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_ext2fs/mount_ext2fs.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount_ext2fs.c,v 1.3 1997/09/16 12:26:50 lukem Exp $	*/
+/*	$NetBSD: mount_ext2fs.c,v 1.4 1998/03/01 02:20:21 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1993, 1994
@@ -43,12 +43,13 @@
 #if 0
 static char sccsid[] = "@(#)mount_ufs.c	8.4 (Berkeley) 4/26/95";
 #else
-__RCSID("$NetBSD: mount_ext2fs.c,v 1.3 1997/09/16 12:26:50 lukem Exp $");
+__RCSID("$NetBSD: mount_ext2fs.c,v 1.4 1998/03/01 02:20:21 fvdl Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/mount.h>
+#include <ufs/ufs/ufsmount.h>
 
 #include <err.h>
 #include <errno.h>
--- a/sbin/mount_ffs/mount_ffs.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_ffs/mount_ffs.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount_ffs.c,v 1.6 1997/09/16 12:26:29 lukem Exp $	*/
+/*	$NetBSD: mount_ffs.c,v 1.7 1998/03/01 02:20:29 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1993, 1994
@@ -43,12 +43,13 @@
 #if 0
 static char sccsid[] = "@(#)mount_ufs.c	8.4 (Berkeley) 4/26/95";
 #else
-__RCSID("$NetBSD: mount_ffs.c,v 1.6 1997/09/16 12:26:29 lukem Exp $");
+__RCSID("$NetBSD: mount_ffs.c,v 1.7 1998/03/01 02:20:29 fvdl Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/mount.h>
+#include <ufs/ufs/ufsmount.h>
 
 #include <err.h>
 #include <errno.h>
--- a/sbin/mount_lfs/mount_lfs.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_lfs/mount_lfs.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount_lfs.c,v 1.6 1997/09/16 12:29:21 lukem Exp $	*/
+/*	$NetBSD: mount_lfs.c,v 1.7 1998/03/01 02:20:41 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1993, 1994
@@ -43,13 +43,15 @@
 #if 0
 static char sccsid[] = "@(#)mount_lfs.c	8.4 (Berkeley) 4/26/95";
 #else
-__RCSID("$NetBSD: mount_lfs.c,v 1.6 1997/09/16 12:29:21 lukem Exp $");
+__RCSID("$NetBSD: mount_lfs.c,v 1.7 1998/03/01 02:20:41 fvdl Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/mount.h>
 
+#include <ufs/ufs/ufsmount.h>
+
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
--- a/sbin/mount_msdos/Makefile	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_msdos/Makefile	Sun Mar 01 02:20:01 1998 +0000
@@ -1,11 +1,11 @@
-#	$NetBSD: Makefile,v 1.12 1997/10/10 19:50:25 christos Exp $
+#	$NetBSD: Makefile,v 1.13 1998/03/01 02:20:45 fvdl Exp $
 
 PROG=	mount_msdos
 SRCS=	mount_msdos.c getmntopts.c
 MAN=	mount_msdos.8
 
 MOUNT=	${.CURDIR}/../mount
-CPPFLAGS+= -I${MOUNT}
+CPPFLAGS+= -I${MOUNT} -I../../sys
 .PATH:	${MOUNT}
 
 .include <bsd.prog.mk>
--- a/sbin/mount_msdos/mount_msdos.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_msdos/mount_msdos.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount_msdos.c,v 1.18 1997/09/16 12:24:18 lukem Exp $	*/
+/*	$NetBSD: mount_msdos.c,v 1.19 1998/03/01 02:20:45 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christopher G. Demetriou
@@ -32,13 +32,14 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mount_msdos.c,v 1.18 1997/09/16 12:24:18 lukem Exp $");
+__RCSID("$NetBSD: mount_msdos.c,v 1.19 1998/03/01 02:20:45 fvdl Exp $");
 #endif /* not lint */
 
 #include <sys/cdefs.h>
 #include <sys/param.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
+#include <msdosfs/msdosfsmount.h>
 #include <ctype.h>
 #include <err.h>
 #include <grp.h>
--- a/sbin/mount_nfs/mount_nfs.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/mount_nfs/mount_nfs.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount_nfs.c,v 1.19 1998/02/03 03:32:43 perry Exp $	*/
+/*	$NetBSD: mount_nfs.c,v 1.20 1998/03/01 02:20:49 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1994
@@ -46,7 +46,7 @@
 #if 0
 static char sccsid[] = "@(#)mount_nfs.c	8.11 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: mount_nfs.c,v 1.19 1998/02/03 03:32:43 perry Exp $");
+__RCSID("$NetBSD: mount_nfs.c,v 1.20 1998/03/01 02:20:49 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -76,6 +76,7 @@
 #include <nfs/nfs.h>
 #undef _KERNEL
 #include <nfs/nqnfs.h>
+#include <nfs/nfsmount.h>
 
 #include <arpa/inet.h>
 
--- a/sbin/newfs/newfs.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/newfs/newfs.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: newfs.c,v 1.31 1997/11/19 09:48:52 drochner Exp $	*/
+/*	$NetBSD: newfs.c,v 1.32 1998/03/01 02:20:33 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1983, 1989, 1993, 1994
@@ -43,7 +43,7 @@
 #if 0
 static char sccsid[] = "@(#)newfs.c	8.13 (Berkeley) 5/1/95";
 #else
-__RCSID("$NetBSD: newfs.c,v 1.31 1997/11/19 09:48:52 drochner Exp $");
+__RCSID("$NetBSD: newfs.c,v 1.32 1998/03/01 02:20:33 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -61,6 +61,7 @@
 
 #include <ufs/ufs/dir.h>
 #include <ufs/ufs/dinode.h>
+#include <ufs/ufs/ufsmount.h>
 #include <ufs/ffs/fs.h>
 
 #include <ctype.h>
--- a/sbin/newlfs/config.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/newlfs/config.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: config.h,v 1.2 1995/03/18 14:58:47 cgd Exp $	*/
+/*	$NetBSD: config.h,v 1.3 1998/03/01 02:20:53 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)config.h	8.2 (Berkeley) 4/22/94
+ *	@(#)config.h	8.3 (Berkeley) 5/24/95
  */
 
 /*
@@ -134,3 +134,9 @@
 #define	DFL_LFSBLOCK		4096
 #define	DFL_LFSBLOCK_SHIFT	12
 #define	DFL_LFSBLOCK_MASK	0xFFF
+
+#define DFL_LFSFRAG		4096
+#define DFL_LFS_FFMASK		DFL_LFSBLOCK_MASK
+#define DFL_LFS_FFSHIFT		DFL_LFSBLOCK_SHIFT
+#define DFL_LFS_FBMASK		0
+#define DFL_LFS_FBSHIFT		0
--- a/sbin/newlfs/extern.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/newlfs/extern.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.2 1995/03/18 14:58:48 cgd Exp $	*/
+/*	$NetBSD: extern.h,v 1.3 1998/03/01 02:20:53 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)extern.h	8.1 (Berkeley) 6/5/93
+ *	@(#)extern.h	8.2 (Berkeley) 5/24/95
  */
 
 u_long	cksum __P((void *, size_t));
@@ -40,7 +40,8 @@
 void	fatal __P((const char *fmt, ...));
 u_int	log2 __P((u_int));
 int	make_lfs
-	    __P((int, struct disklabel *, struct partition *, int, int, int));
+	    __P((int, struct disklabel *, struct partition *, int,
+		int, int, int));
 int	mkfs __P((struct partition *, char *, int, int));
 
 extern char	*progname;
--- a/sbin/newlfs/lfs.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/newlfs/lfs.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs.c,v 1.11 1997/09/15 11:40:28 lukem Exp $	*/
+/*	$NetBSD: lfs.c,v 1.12 1998/03/01 02:20:53 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -36,9 +36,9 @@
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)lfs.c	8.1 (Berkeley) 6/5/93";
+static char sccsid[] = "@(#)lfs.c	8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: lfs.c,v 1.11 1997/09/15 11:40:28 lukem Exp $");
+__RCSID("$NetBSD: lfs.c,v 1.12 1998/03/01 02:20:53 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -98,7 +98,7 @@
 	/* lfs_ssize */		DFL_LFSSEG/DFL_LFSBLOCK,
 	/* lfs_dsize */		0,
 	/* lfs_bsize */		DFL_LFSBLOCK,
-	/* lfs_fsize */		DFL_LFSBLOCK,
+	/* lfs_fsize */		DFL_LFSFRAG,
 	/* lfs_frag */		1,
 	/* lfs_free */		LFS_FIRST_INUM,
 	/* lfs_bfree */		0,
@@ -128,10 +128,10 @@
 	/* lfs_segshift */	DFL_LFSSEG_SHIFT,
 	/* lfs_bmask */		DFL_LFSBLOCK_MASK,
 	/* lfs_bshift */	DFL_LFSBLOCK_SHIFT,
-	/* lfs_ffmask */	0,
-	/* lfs_ffshift */	0,
-	/* lfs_fbmask */	0,
-	/* lfs_fbshift */	0,
+	/* lfs_ffmask */	DFL_LFS_FFMASK,
+	/* lfs_ffshift */	DFL_LFS_FFSHIFT,
+	/* lfs_fbmask */	DFL_LFS_FBMASK,
+	/* lfs_fbshift */	DFL_LFS_FBSHIFT,
 	/* lfs_fsbtodb */	0,
 	/* lfs_sushift */	0,
 	/* lfs_maxsymlinklen */	MAXSYMLINKLEN,
@@ -151,6 +151,7 @@
 	/* lfs_ronly */		0,
 	/* lfs_flags */		0,
 	/* lfs_fsmnt */		{ 0 },
+	/* lfs_pad */ 		{ 0 },
 };
 
 
@@ -172,12 +173,13 @@
 static void put __P((int, off_t, void *, size_t));
 
 int
-make_lfs(fd, lp, partp, minfree, block_size, seg_size)
+make_lfs(fd, lp, partp, minfree, block_size, frag_size, seg_size)
 	int fd;
 	struct disklabel *lp;
 	struct partition *partp;
 	int minfree;
 	int block_size;
+	int frag_size;
 	int seg_size;
 {
 	struct dinode *dip;	/* Pointer to a disk inode */
@@ -203,6 +205,7 @@
 	u_long *datasump;	/* Used to computed checksum on data */
 	int block_array_size;	/* How many entries in block array */
 	int bsize;		/* Block size */
+	int fsize;		/* Fragment size */
 	int db_per_fb;		/* Disk blocks per file block */
 	int i, j;
 	int off;		/* Offset at which to write */
@@ -215,18 +218,27 @@
 
 	if (!(bsize = block_size))
 		bsize = DFL_LFSBLOCK;
+	if (!(fsize = frag_size))
+		fsize = DFL_LFSFRAG;
 	if (!(ssize = seg_size))
 		ssize = DFL_LFSSEG;
 
 	/* Modify parts of superblock overridden by command line arguments */
-	if (bsize != DFL_LFSBLOCK) {
+	if (bsize != DFL_LFSBLOCK || fsize != DFL_LFSFRAG) {
 		lfsp->lfs_bshift = log2(bsize);
 		if (1 << lfsp->lfs_bshift != bsize)
 			fatal("%d: block size not a power of 2", bsize);
 		lfsp->lfs_bsize = bsize;
-		lfsp->lfs_fsize = bsize;
+		lfsp->lfs_fsize = fsize;
 		lfsp->lfs_bmask = bsize - 1;
 		lfsp->lfs_inopb = bsize / sizeof(struct dinode);
+		lfsp->lfs_ffmask = fsize - 1;
+		lfsp->lfs_ffshift = log2(fsize);
+		if (1 << lfsp->lfs_ffshift != fsize)
+			fatal("%d: frag size not a power of 2", fsize);
+		lfsp->lfs_frag = numfrags(lfsp, bsize);
+		lfsp->lfs_fbmask = lfsp->lfs_frag - 1;
+		lfsp->lfs_fbshift = log2(lfsp->lfs_frag);
 /* MIS -- should I round to power of 2 */
 		lfsp->lfs_ifpb = bsize / sizeof(IFILE);
 		lfsp->lfs_sepb = bsize / sizeof(SEGUSE);
@@ -488,6 +500,7 @@
 	summary.ss_create = lfsp->lfs_tstamp;
 	summary.ss_nfinfo = 3;
 	summary.ss_ninos = 3;
+	summary.ss_magic = SS_MAGIC;
 	summary.ss_datasum = cksum(datasump, sizeof(u_long) * blocks_used);
 
 	/*
@@ -524,11 +537,12 @@
 	/* Now, add the ifile */
 	file_info.fi_nblocks = block_array_size;
 	file_info.fi_version = 1;
+	file_info.fi_lastlength = lfsp->lfs_bsize;
 	file_info.fi_ino = LFS_IFILE_INUM;
 
-	memcpy(sump, &file_info, sizeof(FINFO) - sizeof(u_long));
+	memmove(sump, &file_info, sizeof(FINFO) - sizeof(u_long));
 	sump += sizeof(FINFO) - sizeof(u_long);
-	memcpy(sump, block_array, sizeof(u_long) * file_info.fi_nblocks);
+	memmove(sump, block_array, sizeof(u_long) * file_info.fi_nblocks);
 	sump += sizeof(u_long) * file_info.fi_nblocks;
 
 	/* Now, add the root directory */
@@ -536,12 +550,12 @@
 	file_info.fi_version = 1;
 	file_info.fi_ino = ROOTINO;
 	file_info.fi_blocks[0] = 0;
-	memcpy(sump, &file_info, sizeof(FINFO));
+	memmove(sump, &file_info, sizeof(FINFO));
 	sump += sizeof(FINFO);
 
 	/* Now, add the lost and found */
 	file_info.fi_ino = LOSTFOUNDINO;
-	memcpy(sump, &file_info, sizeof(FINFO));
+	memmove(sump, &file_info, sizeof(FINFO));
 
 	((daddr_t *)ipagep)[LFS_SUMMARY_SIZE / sizeof(daddr_t) - 1] = 
 	    lfsp->lfs_idaddr;
@@ -554,6 +568,7 @@
 	sp->ss_nfinfo = 0;
 	sp->ss_ninos = 0;
 	sp->ss_datasum = 0;
+	sp->ss_magic = SS_MAGIC;
 
 	/* Now write the summary block for the next partial so it's invalid */
 	lfsp->lfs_tstamp = 0;
@@ -626,7 +641,7 @@
 	dip->di_blocks = nblocks << lfsp->lfs_fsbtodb;
 
 	dip->di_size = (nblocks << lfsp->lfs_bshift);
-	dip->di_atime = dip->di_mtime =dip->di_ctime = lfsp->lfs_tstamp;
+	dip->di_atime = dip->di_mtime = dip->di_ctime = lfsp->lfs_tstamp;
 	dip->di_atimensec = dip->di_mtimensec = dip->di_ctimensec = 0;
 	dip->di_inumber = ino;
 
@@ -660,11 +675,11 @@
 	spcleft = DIRBLKSIZ;
 	for (cp = bufp, i = 0; i < entries - 1; i++) {
 		protodir[i].d_reclen = DIRSIZ(NEWDIRFMT, &protodir[i]);
-		memcpy(cp, &protodir[i], protodir[i].d_reclen);
+		memmove(cp, &protodir[i], protodir[i].d_reclen);
 		cp += protodir[i].d_reclen;
 		if ((spcleft -= protodir[i].d_reclen) < 0)
 			fatal("%s: %s", special, "directory too big");
 	}
 	protodir[i].d_reclen = spcleft;
-	memcpy(cp, &protodir[i], DIRSIZ(NEWDIRFMT, &protodir[i]));
+	memmove(cp, &protodir[i], DIRSIZ(NEWDIRFMT, &protodir[i]));
 }
--- a/sbin/newlfs/newfs.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sbin/newlfs/newfs.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: newfs.c,v 1.9 1997/09/15 11:40:30 lukem Exp $	*/
+/*	$NetBSD: newfs.c,v 1.10 1998/03/01 02:20:54 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1992, 1993
@@ -41,9 +41,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)newfs.c	8.3 (Berkeley) 4/22/94";
+static char sccsid[] = "@(#)newfs.c	8.5 (Berkeley) 5/24/95";
 #else
-__RCSID("$NetBSD: newfs.c,v 1.9 1997/09/15 11:40:30 lukem Exp $");
+__RCSID("$NetBSD: newfs.c,v 1.10 1998/03/01 02:20:54 fvdl Exp $");
 #endif
 #endif /* not lint */
 
@@ -330,7 +330,7 @@
 		fatal("%s: `%c' partition is unavailable", argv[0], *cp);
 
 	/* If we're making a LFS, we break out here */
-	exit(make_lfs(fso, lp, pp, minfree, bsize, segsize));
+	exit(make_lfs(fso, lp, pp, minfree, bsize, fsize, segsize));
 }
 
 #ifdef COMPAT
--- a/sys/adosfs/adlookup.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/adosfs/adlookup.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: adlookup.c,v 1.19 1997/05/08 16:19:43 mycroft Exp $	*/
+/*	$NetBSD: adlookup.c,v 1.20 1998/03/01 02:25:17 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -76,6 +76,7 @@
 	struct ucred *ucp;	/* lookup credentials */
 	u_long bn, plen, hval;
 	const u_char *pelt;
+	struct proc *p;
 
 #ifdef ADOSFS_DIAGNOSTIC
 	advopprint(sp);
@@ -88,6 +89,7 @@
 	ucp = cnp->cn_cred;
 	nameiop = cnp->cn_nameiop;
 	flags = cnp->cn_flags;
+	p = cnp->cn_proc;
 	last = flags & ISLASTCN;
 	lockp = flags & LOCKPARENT;
 	wantp = flags & (LOCKPARENT | WANTPARENT);
@@ -101,6 +103,10 @@
 	if ((error = VOP_ACCESS(vdp, VEXEC, ucp, cnp->cn_proc)) != 0)
 		return (error);
 
+	if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
+	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+		return (EROFS);
+
 	/*
 	 * cache lookup algorithm borrowed from ufs_lookup()
 	 * its not consistent with otherthings in this function..
@@ -114,25 +120,25 @@
 			VREF(vdp);
 			error = 0;
 		} else if (flags & ISDOTDOT) {
-			VOP_UNLOCK(vdp);	/* race */
-			error = vget(*vpp, 1);
+			VOP_UNLOCK(vdp, 0);	/* race */
+			error = vget(*vpp, LK_EXCLUSIVE);
 			if (error == 0 && lockp && last)
-				error = VOP_LOCK(vdp);
+				error = vn_lock(vdp, LK_EXCLUSIVE);
 		} else {
-			error = vget(*vpp, 1);
+			error = vget(*vpp, LK_EXCLUSIVE);
 			/* if (lockp == 0 || error || last) */
 			if (lockp == 0 || error || last == 0)
-				VOP_UNLOCK(vdp);
+				VOP_UNLOCK(vdp, 0);
 		}
 		if (error == 0) {
 			if (vpid == vdp->v_id)
 				return (0);
 			vput(*vpp);
 			if (lockp && vdp != *vpp && last)
-				VOP_UNLOCK(vdp);
+				VOP_UNLOCK(vdp, 0);
 		}
 		*vpp = NULL;
-		if ((error = VOP_LOCK(vdp)) != 0)
+		if ((error = vn_lock(vdp, LK_EXCLUSIVE)) != 0)
 			return (error);
 	}
 
@@ -166,11 +172,12 @@
 		 * and fail. Otherwise we have succeded.
 		 * 
 		 */
-		VOP_UNLOCK(vdp); /* race */
+		VOP_UNLOCK(vdp, 0); /* race */
 		if ((error = VFS_VGET(vdp->v_mount, 
 				      (ino_t)adp->pblock, vpp)) != 0)
-			VOP_LOCK(vdp);
-		else if (last && lockp && (error = VOP_LOCK(vdp)))
+			vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY);
+		else if (last && lockp &&
+		    (error = vn_lock(vdp, LK_EXCLUSIVE)))
 			vput(*vpp);
 		if (error) {
 			*vpp = NULL;
@@ -222,6 +229,10 @@
 	 * not found
 	 */
 	if ((nameiop == CREATE || nameiop == RENAME) && last) {
+
+		if (vdp->v_mount->mnt_flag & MNT_RDONLY)
+			return (EROFS);
+
 		if ((error = VOP_ACCESS(vdp, VWRITE, ucp, cnp->cn_proc)) != 0) {
 #ifdef ADOSFS_DIAGNOSTIC
 			printf("[VOP_ACCESS] %d)", error);
@@ -229,7 +240,7 @@
 			return (error);
 		}
 		if (lockp == 0)
-			VOP_UNLOCK(vdp);
+			VOP_UNLOCK(vdp, 0);
 		cnp->cn_nameiop |= SAVENAME;
 #ifdef ADOSFS_DIAGNOSTIC
 		printf("EJUSTRETURN)");
@@ -267,7 +278,7 @@
 	if (vdp == *vpp)
 		VREF(vdp);
 	else if (lockp == 0 || last == 0)
-		VOP_UNLOCK(vdp);
+		VOP_UNLOCK(vdp, 0);
 found_lockdone:
 	if ((cnp->cn_flags & MAKEENTRY) && nocache == 0)
 		cache_enter(vdp, *vpp, cnp);
--- a/sys/adosfs/adosfs.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/adosfs/adosfs.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: adosfs.h,v 1.12 1996/10/08 22:18:02 thorpej Exp $	*/
+/*	$NetBSD: adosfs.h,v 1.13 1998/03/01 02:25:17 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -32,6 +32,18 @@
  */
 
 /*
+ * Arguments to mount amigados filesystems.
+ */
+struct adosfs_args {
+	char	*fspec;		/* blocks special holding the fs to mount */
+	struct	export_args export;	/* network export information */
+	uid_t	uid;		/* uid that owns msdosfs files */
+	gid_t	gid;		/* gid that owns msdosfs files */
+	mode_t	mask;		/* mask to be applied for msdosfs perms */
+};
+
+#ifdef _KERNEL
+/*
  * Amigados datestamp. (from 1/1/1978 00:00:00 local)
  */
 struct datestamp {
@@ -42,7 +54,6 @@
 };
 
 enum anode_type { AROOT, ADIR, AFILE, ALDIR, ALFILE, ASLINK };
-enum anode_flags { AWANT = 0x1, ALOCKED = 0x2 };
 
 /* 
  * similar to inode's, we use to represent:
@@ -69,6 +80,7 @@
 	u_long lastlindblk;	/* (f/hf) last logical indirect block */
 	u_long lastindblk;	/* (f/hf) last indirect block read */
 	u_long *tab;		/* (r/d) hash table */
+	struct lock lock;	/* node lock */
 	int *tabi;		/* (r/d) table info */
 	int ntabent;		/* (r/d) number of entries in table */
 	int nwords;		/* size of blocks in long words */
@@ -108,6 +120,7 @@
 	u_long numblks;		/* number of usable blocks */
 	u_long freeblks;	/* number of free blocks */
 };
+
 #define VFSTOADOSFS(mp) ((struct adosfsmount *)(mp)->mnt_data)
 
 #define IS_FFS(amp)	((amp)->dostype & 1)
@@ -153,3 +166,4 @@
 int adosfs_lookup __P((void *));
 
 int (**adosfs_vnodeop_p) __P((void *));
+#endif /* _KERNEL */
--- a/sys/adosfs/adutil.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/adosfs/adutil.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: adutil.c,v 1.16 1997/06/26 21:36:58 kleink Exp $	*/
+/*	$NetBSD: adutil.c,v 1.17 1998/03/01 02:25:18 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -47,6 +47,8 @@
 #define AHASH(an) ((an) & (ANODEHASHSZ - 1))
 static int CapitalChar __P((int, int));
 
+extern struct simplelock adosfs_hashlock;
+
 struct vnode * 
 adosfs_ahashget(mp, an)
 	struct mount *mp;
@@ -54,22 +56,23 @@
 {
 	struct anodechain *hp;
 	struct anode *ap;
+	struct vnode *vp;
 
 	hp = &VFSTOADOSFS(mp)->anodetab[AHASH(an)];
 
 start_over:
+	simple_lock(&adosfs_hashlock);
 	for (ap = hp->lh_first; ap != NULL; ap = ap->link.le_next) {
-		if (ap->block != an)
-			continue;
-		if (ap->flags & ALOCKED) {
-			ap->flags |= AWANT;
-			tsleep(ap, PINOD, "ahashget", 0);
-			goto start_over;
+		if (ap->block == an) {
+			vp = ATOV(ap);
+			simple_lock(&vp->v_interlock);
+			simple_unlock(&adosfs_hashlock);
+			if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
+				goto start_over;
+			return (ATOV(ap));
 		}
-		if (vget(ATOV(ap), 1))
-			goto start_over;
-		return (ATOV(ap));
 	}
+	simple_unlock(&adosfs_hashlock);
 	return (NULL);
 }
 
@@ -81,15 +84,20 @@
 	struct adosfsmount *amp;
 	struct anode *ap;
 {
+	lockmgr(&ap->lock, LK_EXCLUSIVE, (struct simplelock *)0);
+
+	simple_lock(&adosfs_hashlock);
 	LIST_INSERT_HEAD(&amp->anodetab[AHASH(ap->block)], ap, link);
-	ap->flags |= ALOCKED;
+	simple_unlock(&adosfs_hashlock);
 }
 
 void
 adosfs_aremhash(ap)
 	struct anode *ap;
 {
+	simple_lock(&adosfs_hashlock);
 	LIST_REMOVE(ap, link);
+	simple_unlock(&adosfs_hashlock);
 }
 
 int
--- a/sys/adosfs/advfsops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/adosfs/advfsops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: advfsops.c,v 1.27 1998/02/18 07:05:47 thorpej Exp $	*/
+/*	$NetBSD: advfsops.c,v 1.28 1998/03/01 02:25:18 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -62,6 +62,10 @@
 
 int adosfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
 int adosfs_loadbitmap __P((struct adosfsmount *));
+int adosfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+			struct proc *));
+
+struct simplelock adosfs_hashlock;
 
 int
 adosfs_mount(mp, path, data, ndp, p)
@@ -122,13 +126,13 @@
 		accessmode = VREAD;
 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
 			accessmode |= VWRITE;
-		VOP_LOCK(devvp);
+		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
 		error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
 		if (error) {
 			vput(devvp);
 			return (error);
 		}
-		VOP_UNLOCK(devvp);
+		VOP_UNLOCK(devvp, 0);
 	}
 /* MNT_UPDATE? */
 	if ((error = adosfs_mountfs(devvp, mp, p)) != 0) {
@@ -319,7 +323,11 @@
 	struct adosfsmount *amp;
 
 	amp = VFSTOADOSFS(mp);
+#ifdef COMPAT_09
+	sbp->f_type = 16;
+#else
 	sbp->f_type = 0;
+#endif
 	sbp->f_bsize = amp->bsize;
 	sbp->f_iosize = amp->dbsize;
 	sbp->f_blocks = amp->numblks;
@@ -743,6 +751,20 @@
 void
 adosfs_init()
 {
+	simple_lock_init(&adosfs_hashlock);
+}
+
+int
+adosfs_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;
+{
+	return (EOPNOTSUPP);
 }
 
 /*
@@ -769,6 +791,7 @@
 	adosfs_fhtovp,                  
 	adosfs_vptofh,                  
 	adosfs_init,                    
+	adosfs_sysctl,
 	NULL,				/* vfs_mountroot */
 	adosfs_vnodeopv_descs,
 };
--- a/sys/adosfs/advnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/adosfs/advnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: advnops.c,v 1.36 1997/10/10 01:57:31 fvdl Exp $	*/
+/*	$NetBSD: advnops.c,v 1.37 1998/03/01 02:25:18 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -89,6 +89,7 @@
 #define adosfs_create 	genfs_eopnotsupp
 #define adosfs_mkdir 	genfs_eopnotsupp
 #define adosfs_mknod 	genfs_eopnotsupp
+#define adosfs_revoke	genfs_revoke
 #define adosfs_mmap 	genfs_eopnotsupp
 #define adosfs_remove 	genfs_eopnotsupp
 #define adosfs_rename 	genfs_eopnotsupp
@@ -113,6 +114,7 @@
 	{ &vop_lease_desc, adosfs_lease_check },	/* lease */
 	{ &vop_ioctl_desc, adosfs_ioctl },		/* ioctl */
 	{ &vop_poll_desc, adosfs_poll },		/* poll */
+	{ &vop_revoke_desc, adosfs_poll },		/* revoke */
 	{ &vop_mmap_desc, adosfs_mmap },		/* mmap */
 	{ &vop_fsync_desc, adosfs_fsync },		/* fsync */
 	{ &vop_seek_desc, adosfs_seek },		/* seek */
@@ -459,32 +461,13 @@
 {
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		int a_flags;
+		struct proc *a_p;
 	} */ *sp = v;
-	struct vnode *vp;
-	struct anode *ap;
+	struct vnode *vp = sp->a_vp;
 
-#ifdef ADOSFS_DIAGNOSTIC
-	advopprint(sp);
-#endif
-	vp = sp->a_vp;
-start:
-	while (vp->v_flag & VXLOCK) {
-		vp->v_flag |= VXWANT;
-		tsleep(vp, PINOD, "adosfs_lock vp", 0);
-	}
-	if (vp->v_tag == VT_NON)
-		return (ENOENT);
-	ap = VTOA(vp);
-	if (ap->flags & ALOCKED) {
-		ap->flags |= AWANT;
-		tsleep(ap, PINOD, "adosfs_lock ap", 0);
-		goto start;
-	}
-	ap->flags |= ALOCKED;
-#ifdef ADOSFS_DIAGNOSTIC
-	printf(" 0)");
-#endif
-	return(0);
+	return (lockmgr(&VTOA(vp)->lock, sp->a_flags, &vp->v_interlock));
+
 }
 
 /*
@@ -496,23 +479,13 @@
 {
 	struct vop_unlock_args /* {
 		struct vnode *a_vp;
+		int a_flags;
+		struct proc *a_p;
 	} */ *sp = v;
-	struct anode *ap;
+	struct vnode *vp = sp->a_vp;
 
-#ifdef ADOSFS_DIAGNOSTIC
-	advopprint(sp);
-#endif
-	ap = VTOA(sp->a_vp);	
-	ap->flags &= ~ALOCKED;
-	if (ap->flags & AWANT) {
-		ap->flags &= ~AWANT;
-		wakeup(ap);
-	}
-
-#ifdef ADOSFS_DIAGNOSTIC
-	printf(" 0)");
-#endif
-	return(0);
+	return (lockmgr(&VTOA(vp)->lock, sp->a_flags | LK_RELEASE,
+		&vp->v_interlock));
 }
 
 
@@ -674,8 +647,8 @@
 		struct uio *a_uio;
 		struct ucred *a_cred;
 		int *a_eofflag;
-		off_t *a_cookies;
-		int a_ncookies;
+		off_t **a_cookies;
+		int *a_ncookies;
 	} */ *sp = v;
 	int error, useri, chainc, hashi, scanned, uavail;
 	struct adirent ad, *adp;
@@ -684,7 +657,8 @@
 	struct vnode *vp;
 	struct uio *uio;
 	u_long nextbn;
-	off_t uoff;
+	off_t uoff, *cookies = NULL;
+	int ncookies = 0;
 
 #ifdef ADOSFS_DIAGNOSTIC
 	advopprint(sp);
@@ -693,6 +667,7 @@
 		error = ENOTDIR;
 		goto reterr;
 	}
+
 	uio = sp->a_uio;
 	uoff = uio->uio_offset;
 	if (uoff < 0) {
@@ -715,7 +690,14 @@
 		goto reterr;
 	}
 
-	while (uavail && (sp->a_cookies == NULL || sp->a_ncookies > 0)) {
+	if (sp->a_ncookies) {
+		ncookies = 0;
+		MALLOC(cookies, off_t *, sizeof (off_t) * uavail, M_TEMP,
+		    M_WAITOK);
+		*sp->a_cookies = cookies;
+	}
+
+	while (uavail) {
 		if (hashi == pap->ntabent) {
 			*sp->a_eofflag = 1;
 			break;
@@ -807,9 +789,9 @@
 		error = uiomove((caddr_t) adp, sizeof(struct adirent), uio);
 		if (error)
 			break;
-		if (sp->a_cookies) {
-			*sp->a_cookies++ = uoff;
-			sp->a_ncookies--;
+		if (sp->a_ncookies) {
+			*cookies++ = uoff;
+			ncookies++;
 		}
 		uoff += sizeof(struct adirent);
 		useri++;
@@ -822,6 +804,14 @@
 #ifdef ADOSFS_DIAGNOSTIC
 	printf(" %d)", error);
 #endif
+	if (sp->a_ncookies) {
+		if (error) {
+			FREE(*sp->a_cookies, M_TEMP);
+			*sp->a_ncookies = 0;
+			*sp->a_cookies = NULL;
+		} else
+			*sp->a_ncookies = ncookies;
+	}
 	return(error);
 }
 
@@ -837,19 +827,35 @@
 		struct proc *a_p;
 	} */ *sp = v;
 	struct anode *ap;
+	struct vnode *vp = sp->a_vp;
 	int error;
 
 #ifdef ADOSFS_DIAGNOSTIC
 	advopprint(sp);
 #endif
 
-	ap = VTOA(sp->a_vp);
+	ap = VTOA(vp);
 #ifdef DIAGNOSTIC
-	if (!VOP_ISLOCKED(sp->a_vp)) {
+	if (!VOP_ISLOCKED(vp)) {
 		vprint("adosfs_access: not locked", sp->a_vp);
 		panic("adosfs_access: not locked");
 	}
 #endif
+	/*
+	 * Disallow write attempts unless the file is a socket,
+	 * fifo, or a block or character device resident on the
+	 * file system.
+	 */
+	if (sp->a_mode & VWRITE) {
+		switch (vp->v_type) {
+		case VDIR:
+		case VLNK:
+		case VREG:
+			return (EROFS);
+		default:
+			break;
+		}
+	}
 #ifdef QUOTA
 #endif
 	error = vaccess(sp->a_vp->v_type, adunixprot(ap->adprot) & ap->amp->mask,
@@ -898,12 +904,16 @@
 {
 	struct vop_inactive_args /* {
 		struct vnode *a_vp;
+		struct proc *a_p;
 	} */ *sp = v;
+	struct vnode *vp = sp->a_vp;
+	struct proc *p = sp->a_p;
 #ifdef ADOSFS_DIAGNOSTIC
 	advopprint(sp);
 #endif
-	if (sp->a_vp->v_usecount == 0 /* && check for file gone? */)
-		vgone(sp->a_vp);
+	VOP_UNLOCK(vp, 0);
+	/* XXX this needs to check if file was deleted */
+	vrecycle(vp, (struct simplelock *)0, p);
 
 #ifdef ADOSFS_DIAGNOSTIC
 	printf(" 0)");
@@ -918,18 +928,8 @@
 	struct vop_islocked_args /* {
 		struct vnode *a_vp;
 	} */ *sp = v;
-	int locked;
 
-#ifdef ADOSFS_DIAGNOSTIC
-	advopprint(sp);
-#endif
-
-	locked = (VTOA(sp->a_vp)->flags & ALOCKED) == ALOCKED;
-
-#ifdef ADOSFS_DIAGNOSTIC
-	printf(" %d)", locked);
-#endif
-	return(locked);
+	return (lockstatus(&VTOA(sp->a_vp)->lock));
 }
 
 /*
--- a/sys/compat/common/tty_43.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/common/tty_43.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty_43.c,v 1.7 1996/10/13 00:46:49 christos Exp $	*/
+/*	$NetBSD: tty_43.c,v 1.8 1998/03/01 02:22:41 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)tty_compat.c	8.1 (Berkeley) 6/10/93
+ *	@(#)tty_compat.c	8.2 (Berkeley) 1/9/95
  */
 
 /*
--- a/sys/compat/common/vfs_syscalls_43.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/common/vfs_syscalls_43.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_syscalls_43.c,v 1.9 1998/02/19 00:35:26 thorpej Exp $	*/
+/*	$NetBSD: vfs_syscalls_43.c,v 1.10 1998/03/01 02:22:41 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -127,7 +127,6 @@
 	return (error);
 }
 
-
 /*
  * Get file status; this version does not follow links.
  */
@@ -140,27 +139,55 @@
 {
 	register struct compat_43_sys_lstat_args /* {
 		syscallarg(char *) path;
-		syscallarg(struct stat43 *) ub;
+		syscallarg(struct ostat *) ub;
 	} */ *uap = v;
-	struct stat sb;
+	struct vnode *vp, *dvp;
+	struct stat sb, sb1;
 	struct stat43 osb;
 	int error;
 	struct nameidata nd;
 
-	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
 	    SCARG(uap, path), p);
-	if ((error = namei(&nd)) != 0)
+	if ((error = namei(&nd)))
 		return (error);
-	error = vn_stat(nd.ni_vp, &sb, p);
-	vput(nd.ni_vp);
-	if (error)
-		return (error);
+	/*
+	 * For symbolic links, always return the attributes of its
+	 * containing directory, except for mode, size, and links.
+	 */
+	vp = nd.ni_vp;
+	dvp = nd.ni_dvp;
+	if (vp->v_type != VLNK) {
+		if (dvp == vp)
+			vrele(dvp);
+		else
+			vput(dvp);
+		error = vn_stat(vp, &sb, p);
+		vput(vp);
+		if (error)
+			return (error);
+	} else {
+		error = vn_stat(dvp, &sb, p);
+		vput(dvp);
+		if (error) {
+			vput(vp);
+			return (error);
+		}
+		error = vn_stat(vp, &sb1, p);
+		vput(vp);
+		if (error)
+			return (error);
+		sb.st_mode &= ~S_IFDIR;
+		sb.st_mode |= S_IFLNK;
+		sb.st_nlink = sb1.st_nlink;
+		sb.st_size = sb1.st_size;
+		sb.st_blocks = sb1.st_blocks;
+	}
 	cvtstat(&sb, &osb);
-	error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
+	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
 	return (error);
 }
 
-
 /*
  * Return status information about a file descriptor.
  */
@@ -367,12 +394,12 @@
 	auio.uio_segflg = UIO_USERSPACE;
 	auio.uio_procp = p;
 	auio.uio_resid = SCARG(uap, count);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	loff = auio.uio_offset = fp->f_offset;
 #	if (BYTE_ORDER != LITTLE_ENDIAN)
 		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
 			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
-			    (off_t *)0, 0);
+			    (off_t **)0, (int *)0);
 			fp->f_offset = auio.uio_offset;
 		} else
 #	endif
@@ -384,7 +411,7 @@
 		MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
 		kiov.iov_base = dirbuf;
 		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
-			    (off_t *)0, 0);
+			    (off_t **)0, (int *)0);
 		fp->f_offset = kuio.uio_offset;
 		if (error == 0) {
 			readcnt = SCARG(uap, count) - kuio.uio_resid;
@@ -420,7 +447,7 @@
 		}
 		FREE(dirbuf, M_TEMP);
 	}
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	if (error)
 		return (error);
 
@@ -450,7 +477,7 @@
 		
 		if (lvp != NULLVP) {
 			error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
-			VOP_UNLOCK(lvp);
+			VOP_UNLOCK(lvp, 0);
 
 			if (error) {
 				vrele(lvp);
--- a/sys/compat/ibcs2/ibcs2_misc.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/ibcs2/ibcs2_misc.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: ibcs2_misc.c,v 1.32 1998/02/14 20:52:47 kleink Exp $	*/
+/*	$NetBSD: ibcs2_misc.c,v 1.33 1998/03/01 02:22:58 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995, 1998 Scott Bartram
@@ -370,13 +370,9 @@
 	if ((fp->f_flag & FREAD) == 0)
 		return (EBADF);
 	vp = (struct vnode *)fp->f_data;
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
 	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -392,8 +388,8 @@
 	 * First we read into the malloc'ed buffer, then
 	 * we massage it into user space, one record at a time.
 	 */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 	inp = buf;
@@ -450,7 +446,7 @@
 eof:
 	*retval = SCARG(uap, nbytes) - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return (error);
@@ -499,9 +495,7 @@
 	DPRINTF(("ibcs2_read: read directory\n"));
 	buflen = max(MAXBSIZE, SCARG(uap, nbytes));
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -517,8 +511,8 @@
 	 * First we read into the malloc'ed buffer, then
 	 * we massage it into user space, one record at a time.
 	 */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 	inp = buf;
@@ -573,7 +567,7 @@
 eof:
 	*retval = SCARG(uap, nbytes) - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return (error);
--- a/sys/compat/linux/common/linux_break.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_break.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_break.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_break.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/common/linux_misc.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_misc.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_misc.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_misc.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/common/linux_misc_notalpha.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_misc_notalpha.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_misc_notalpha.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_misc_notalpha.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/common/linux_oldmmap.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_oldmmap.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_oldmmap.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_oldmmap.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/common/linux_oldolduname.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_oldolduname.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_oldolduname.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_oldolduname.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/common/linux_oldselect.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_oldselect.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_oldselect.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_oldselect.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/common/linux_olduname.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_olduname.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_olduname.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_olduname.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/common/linux_pipe.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/common/linux_pipe.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_pipe.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_pipe.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/linux_misc.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/linux_misc.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_misc.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_misc.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/multiarch/linux_break.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/multiarch/linux_break.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_break.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_break.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/multiarch/linux_misc_notalpha.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/multiarch/linux_misc_notalpha.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_misc_notalpha.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_misc_notalpha.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/multiarch/linux_oldmmap.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/multiarch/linux_oldmmap.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_oldmmap.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_oldmmap.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/multiarch/linux_oldolduname.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/multiarch/linux_oldolduname.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_oldolduname.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_oldolduname.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/multiarch/linux_oldselect.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/multiarch/linux_oldselect.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_oldselect.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_oldselect.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/multiarch/linux_olduname.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/multiarch/linux_olduname.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_olduname.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_olduname.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/linux/multiarch/linux_pipe.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/linux/multiarch/linux_pipe.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_pipe.c,v 1.38 1998/02/20 18:09:04 mycroft Exp $	*/
+/*	$NetBSD: linux_pipe.c,v 1.39 1998/03/01 02:23:03 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Frank van der Linden
@@ -799,9 +799,6 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
 		return error;
 
@@ -817,10 +814,8 @@
 		oldcall = 0;
 	}
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
 
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -836,8 +831,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -908,7 +903,7 @@
 eof:
 	*retval = nbytes - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
--- a/sys/compat/sunos/sunos_misc.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/sunos/sunos_misc.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: sunos_misc.c,v 1.87 1998/02/19 00:43:56 thorpej Exp $	*/
+/*	$NetBSD: sunos_misc.c,v 1.88 1998/03/01 02:22:45 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -451,14 +451,9 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -474,8 +469,8 @@
 	 * First we read into the malloc'ed buffer, then
 	 * we massage it into user space, one record at a time.
 	 */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -534,7 +529,7 @@
 eof:
 	*retval = SCARG(uap, nbytes) - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return (error);
@@ -690,12 +685,12 @@
 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
 		return (error);
 	vp = (struct vnode *)fp->f_data;
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	if (vp->v_type != VDIR)
 		error = ENOTDIR;
 	else
 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	if (error)
 		return (error);
 	VREF(vp);
--- a/sys/compat/svr4/svr4_fcntl.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/svr4/svr4_fcntl.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: svr4_fcntl.c,v 1.21 1997/10/28 18:55:56 christos Exp $	 */
+/*	$NetBSD: svr4_fcntl.c,v 1.22 1998/03/01 02:22:50 fvdl Exp $	 */
 
 /*
  * Copyright (c) 1994, 1997 Christos Zoulas.  All rights reserved.
@@ -279,7 +279,7 @@
 		goto out;
 
 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
-		vgoneall(vp);
+		VOP_REVOKE(vp, REVOKEALL);
 out:
 	vrele(vp);
 	return error;
--- a/sys/compat/svr4/svr4_misc.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/compat/svr4/svr4_misc.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: svr4_misc.c,v 1.58 1998/02/14 01:33:18 thorpej Exp $	 */
+/*	$NetBSD: svr4_misc.c,v 1.59 1998/03/01 02:22:50 fvdl Exp $	 */
 
 /*
  * Copyright (c) 1994 Christos Zoulas
@@ -245,14 +245,9 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -268,8 +263,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -322,7 +317,7 @@
 eof:
 	*retval = SCARG(uap, nbytes) - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
@@ -359,14 +354,9 @@
 
 	vp = (struct vnode *)fp->f_data;
 
-	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */
-		return (EINVAL);
-
 	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
 	buf = malloc(buflen, M_TEMP, M_WAITOK);
-	ncookies = buflen / 16;
-	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	off = fp->f_offset;
 again:
 	aiov.iov_base = buf;
@@ -382,8 +372,8 @@
          * First we read into the malloc'ed buffer, then
          * we massage it into user space, one record at a time.
          */
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,
-	    ncookies);
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
+	    &ncookies);
 	if (error)
 		goto out;
 
@@ -440,7 +430,7 @@
 eof:
 	*retval = SCARG(uap, nbytes) - resid;
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	free(cookiebuf, M_TEMP);
 	free(buf, M_TEMP);
 	return error;
@@ -534,12 +524,12 @@
 	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
 		return error;
 	vp = (struct vnode *) fp->f_data;
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	if (vp->v_type != VDIR)
 		error = ENOTDIR;
 	else
 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	if (error)
 		return error;
 	VREF(vp);
--- a/sys/dev/vnd.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/dev/vnd.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnd.c,v 1.55 1998/02/19 00:47:02 thorpej Exp $	*/
+/*	$NetBSD: vnd.c,v 1.56 1998/03/01 02:21:00 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -75,7 +75,7 @@
  *
  * from: Utah $Hdr: vn.c 1.13 94/04/02$
  *
- *	@(#)vn.c	8.6 (Berkeley) 4/1/94
+ *	@(#)vn.c	8.9 (Berkeley) 5/14/95
  */
 
 /*
@@ -401,11 +401,11 @@
 		 */
 		if (!VOP_ISLOCKED(vnd->sc_vp)) {
 			dolock = 1;
-			VOP_LOCK(vnd->sc_vp);
+			vn_lock(vnd->sc_vp, 0);
 		}
 		error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra);
 		if (dolock)
-			VOP_UNLOCK(vnd->sc_vp);
+			VOP_UNLOCK(vnd->sc_vp, 0);
 
 		if (error == 0 && (long)nbn == -1)
 			error = EIO;
@@ -762,12 +762,12 @@
 		}
 		error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
 		if (error) {
-			VOP_UNLOCK(nd.ni_vp);
+			VOP_UNLOCK(nd.ni_vp, 0);
 			(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
 			vndunlock(vnd);
 			return(error);
 		}
-		VOP_UNLOCK(nd.ni_vp);
+		VOP_UNLOCK(nd.ni_vp, 0);
 		vnd->sc_vp = nd.ni_vp;
 		vnd->sc_size = btodb(vattr.va_size);	/* note truncation */
 
@@ -982,20 +982,20 @@
 	auio.uio_rw = UIO_READ;
 	auio.uio_segflg = UIO_SYSSPACE;
 	auio.uio_resid = aiov.iov_len;
-	VOP_LOCK(vnd->sc_vp);
+	vn_lock(vnd->sc_vp, LK_EXCLUSIVE | LK_RETRY);
 	error = VOP_READ(vnd->sc_vp, &auio, 0, vnd->sc_cred);
 	if (error == 0) {
 		/*
 		 * Because vnd does all IO directly through the vnode
-		 * we need to flush (atleast) the buffer from the above
+		 * we need to flush (at least) the buffer from the above
 		 * VOP_READ from the buffer cache to prevent cache
 		 * incoherencies.  Also, be careful to write dirty
 		 * buffers back to stable storage.
 		 */
 		error = vinvalbuf(vnd->sc_vp, V_SAVE, vnd->sc_cred,
-		    curproc, 0, 0);
+			    curproc, 0, 0);
 	}
-	VOP_UNLOCK(vnd->sc_vp);
+	VOP_UNLOCK(vnd->sc_vp, 0);
 
 	free(tmpbuf, M_TEMP);
 	return (error);
--- a/sys/isofs/cd9660/cd9660_extern.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/isofs/cd9660/cd9660_extern.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_extern.h,v 1.1 1997/01/24 00:24:53 cgd Exp $	*/
+/*	$NetBSD: cd9660_extern.h,v 1.2 1998/03/01 02:22:08 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -94,6 +94,8 @@
 	    struct vnode **, int *, struct ucred **));
 int cd9660_vptofh __P((struct vnode *, struct fid *));
 void cd9660_init __P((void));
+int cd9660_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+			struct proc *));
 
 int cd9660_mountroot __P((void)); 
 
--- a/sys/isofs/cd9660/cd9660_lookup.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/isofs/cd9660/cd9660_lookup.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_lookup.c,v 1.18 1997/05/08 16:19:59 mycroft Exp $	*/
+/*	$NetBSD: cd9660_lookup.c,v 1.19 1998/03/01 02:22:08 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993, 1994
@@ -39,7 +39,7 @@
  *
  *	from: @(#)ufs_lookup.c	7.33 (Berkeley) 5/19/91
  *
- *	@(#)cd9660_lookup.c	8.5 (Berkeley) 12/5/94
+ *	@(#)cd9660_lookup.c	8.5 (Berkeley) 5/27/95
  */
 
 #include <sys/param.h>
@@ -144,7 +144,11 @@
 	 */
 	if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0)
 		return (error);
-	
+
+	if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
+	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+		return (EROFS);
+
 	/*
 	 * We now have a segment name to search for, and a directory to search.
 	 *
@@ -174,14 +178,14 @@
 			VREF(vdp);
 			error = 0;
 		} else if (flags & ISDOTDOT) {
-			VOP_UNLOCK(pdp);
-			error = vget(vdp, 1);
+			VOP_UNLOCK(pdp, 0);
+			error = vget(vdp, LK_EXCLUSIVE);
 			if (!error && lockparent && (flags & ISLASTCN))
-				error = VOP_LOCK(pdp);
+				error = vn_lock(pdp, LK_EXCLUSIVE);
 		} else {
-			error = vget(vdp, 1);
+			error = vget(vdp, LK_EXCLUSIVE);
 			if (!lockparent || error || !(flags & ISLASTCN))
-				VOP_UNLOCK(pdp);
+				VOP_UNLOCK(pdp, 0);
 		}
 		/*
 		 * Check that the capability number did not change
@@ -192,9 +196,9 @@
 				return (0);
 			vput(vdp);
 			if (lockparent && pdp != vdp && (flags & ISLASTCN))
-				VOP_UNLOCK(pdp);
+				VOP_UNLOCK(pdp, 0);
 		}
-		if ((error = VOP_LOCK(pdp)) != 0)
+		if ((error = vn_lock(pdp, LK_EXCLUSIVE)) != 0)
 			return (error);
 		vdp = pdp;
 		dp = VTOI(pdp);
@@ -417,16 +421,16 @@
 	 * it's a relocated directory.
 	 */
 	if (flags & ISDOTDOT) {
-		VOP_UNLOCK(pdp);	/* race to get the inode */
+		VOP_UNLOCK(pdp, 0);	/* race to get the inode */
 		error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
 					     dp->i_ino != ino, ep);
 		brelse(bp);
 		if (error) {
-			VOP_LOCK(pdp);
+			vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
 			return (error);
 		}
 		if (lockparent && (flags & ISLASTCN) &&
-		    (error = VOP_LOCK(pdp))) {
+		    (error = vn_lock(pdp, LK_EXCLUSIVE))) {
 			vput(tdp);
 			return (error);
 		}
@@ -442,7 +446,7 @@
 		if (error)
 			return (error);
 		if (!lockparent || !(flags & ISLASTCN))
-			VOP_UNLOCK(pdp);
+			VOP_UNLOCK(pdp, 0);
 		*vpp = tdp;
 	}
 	
--- a/sys/isofs/cd9660/cd9660_node.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/isofs/cd9660/cd9660_node.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_node.c,v 1.18 1998/02/07 02:44:44 chs Exp $	*/
+/*	$NetBSD: cd9660_node.c,v 1.19 1998/03/01 02:22:08 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1994
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)cd9660_node.c	8.5 (Berkeley) 12/5/94
+ *	@(#)cd9660_node.c	8.8 (Berkeley) 5/22/95
  */
 
 #include <sys/param.h>
@@ -55,6 +55,7 @@
 #include <isofs/cd9660/iso.h>
 #include <isofs/cd9660/cd9660_extern.h>
 #include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
 #include <isofs/cd9660/iso_rrip.h>
 
 /*
@@ -63,6 +64,7 @@
 struct iso_node **isohashtbl;
 u_long isohash;
 #define	INOHASH(device, inum)	(((device) + ((inum)>>12)) & isohash)
+struct simplelock cd9660_ihash_slock;
 
 #ifdef ISODEVMAP
 struct iso_node **idvhashtbl;
@@ -82,8 +84,10 @@
 {
 
 	isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, M_WAITOK, &isohash);
+	simple_lock_init(&cd9660_ihash_slock);
 #ifdef ISODEVMAP
-	idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, M_WAITOK, &idvhash);
+	idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, M_WAITOK,
+			&idvhash);
 #endif
 }
 
@@ -148,30 +152,27 @@
  * to it. If it is in core, but locked, wait for it.
  */
 struct vnode *
-cd9660_ihashget(device, inum)
-	dev_t device;
+cd9660_ihashget(dev, inum)
+	dev_t dev;
 	ino_t inum;
 {
-	register struct iso_node *ip;
+	struct iso_node *ip;
 	struct vnode *vp;
 
-	for (;;)
-		for (ip = isohashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
-			if (ip == NULL)
-				return (NULL);
-			if (inum == ip->i_number && device == ip->i_dev) {
-				if (ip->i_flag & IN_LOCKED) {
-					ip->i_flag |= IN_WANTED;
-					sleep(ip, PINOD);
-					break;
-				}
-				vp = ITOV(ip);
-				if (!vget(vp, 1))
-					return (vp);
-				break;
-			}
+loop:
+	simple_lock(&cd9660_ihash_slock);
+	for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) {
+		if (inum == ip->i_number && dev == ip->i_dev) {
+			vp = ITOV(ip);
+			simple_lock(&vp->v_interlock);
+			simple_unlock(&cd9660_ihash_slock);
+			if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
+				goto loop;
+			return (vp);
 		}
-	/* NOTREACHED */
+	}
+	simple_unlock(&cd9660_ihash_slock);
+	return (NULL);
 }
 
 /*
@@ -183,19 +184,16 @@
 {
 	struct iso_node **ipp, *iq;
 
+	simple_lock(&cd9660_ihash_slock);
 	ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
 	if ((iq = *ipp) != NULL)
 		iq->i_prev = &ip->i_next;
 	ip->i_next = iq;
 	ip->i_prev = ipp;
 	*ipp = ip;
-	if (ip->i_flag & IN_LOCKED)
-		panic("cd9660_ihashins: already locked");
-	if (curproc)
-		ip->i_lockholder = curproc->p_pid;
-	else
-		ip->i_lockholder = -1;
-	ip->i_flag |= IN_LOCKED;
+	simple_unlock(&cd9660_ihash_slock);
+
+	lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0);
 }
 
 /*
@@ -207,6 +205,7 @@
 {
 	register struct iso_node *iq;
 
+	simple_lock(&cd9660_ihash_slock);
 	if ((iq = ip->i_next) != NULL)
 		iq->i_prev = ip->i_prev;
 	*ip->i_prev = iq;
@@ -214,6 +213,7 @@
 	ip->i_next = NULL;
 	ip->i_prev = NULL;
 #endif
+	simple_unlock(&cd9660_ihash_slock);
 }
 
 /*
@@ -226,8 +226,10 @@
 {
 	struct vop_inactive_args /* {
 		struct vnode *a_vp;
+		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
+	struct proc *p = ap->a_p;
 	register struct iso_node *ip = VTOI(vp);
 	int error = 0;
 	
@@ -235,12 +237,13 @@
 		vprint("cd9660_inactive: pushing active", vp);
 	
 	ip->i_flag = 0;
+	VOP_UNLOCK(vp, 0);
 	/*
 	 * If we are done with the inode, reclaim it
 	 * so that it can be reused immediately.
 	 */
-	if (vp->v_usecount == 0 && ip->inode.iso_mode == 0)
-		vgone(vp);
+	if (ip->inode.iso_mode == 0)
+		vrecycle(vp, (struct simplelock *)0, p);
 	return error;
 }
 
@@ -253,6 +256,7 @@
 {
 	struct vop_reclaim_args /* {
 		struct vnode *a_vp;
+		struct proc *a_p;
 	} */ *ap = v;
 	register struct vnode *vp = ap->a_vp;
 	register struct iso_node *ip = VTOI(vp);
--- a/sys/isofs/cd9660/cd9660_node.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/isofs/cd9660/cd9660_node.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_node.h,v 1.15 1997/04/11 21:52:01 kleink Exp $	*/
+/*	$NetBSD: cd9660_node.h,v 1.16 1998/03/01 02:22:09 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)cd9660_node.h	8.4 (Berkeley) 12/5/94
+ *	@(#)cd9660_node.h	8.6 (Berkeley) 5/14/95
  */
 
 /*
@@ -86,7 +86,7 @@
 	doff_t	i_diroff;	/* offset in dir, where we found last entry */
 	doff_t	i_offset;	/* offset of free space in directory */
 	ino_t	i_ino;		/* inode number of found directory */
-	pid_t	i_lockholder, i_lockwaiter;
+	struct lock i_lock;	/* node lock */
 
 	long iso_extent;	/* extent of file */
 	long i_size;
@@ -99,8 +99,6 @@
 #define	i_back		i_chain[1]
 
 /* flags */
-#define	IN_LOCKED	0x0001		/* inode is locked */
-#define	IN_WANTED	0x0002		/* some process waiting on lock */
 #define	IN_ACCESS	0x0020		/* inode access time to be updated */
 
 #define VTOI(vp) ((struct iso_node *)(vp)->v_data)
--- a/sys/isofs/cd9660/cd9660_vfsops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/isofs/cd9660/cd9660_vfsops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_vfsops.c,v 1.27 1998/02/18 07:05:48 thorpej Exp $	*/
+/*	$NetBSD: cd9660_vfsops.c,v 1.28 1998/03/01 02:22:09 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)cd9660_vfsops.c	8.9 (Berkeley) 12/5/94
+ *	@(#)cd9660_vfsops.c	8.18 (Berkeley) 5/22/95
  */
 
 #include <sys/param.h>
@@ -61,6 +61,7 @@
 #include <isofs/cd9660/cd9660_extern.h>
 #include <isofs/cd9660/iso_rrip.h>
 #include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
 
 extern struct vnodeopv_desc cd9660_vnodeop_opv_desc;
 extern struct vnodeopv_desc cd9660_specop_opv_desc;
@@ -90,6 +91,7 @@
 	cd9660_fhtovp,
 	cd9660_vptofh,
 	cd9660_init,
+	cd9660_sysctl,
 	cd9660_mountroot,
 	cd9660_vnodeopv_descs,
 };
@@ -107,11 +109,9 @@
 int
 cd9660_mountroot()
 {
-	register struct mount *mp;
+	struct mount *mp;
 	extern struct vnode *rootvp;
 	struct proc *p = curproc;	/* XXX */
-	struct iso_mnt *imp;
-	size_t size;
 	int error;
 	struct iso_args args;
 
@@ -124,32 +124,21 @@
 	if (bdevvp(rootdev, &rootvp))
 		panic("cd9660_mountroot: can't setup rootvp");
 
-	mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
-	bzero((char *)mp, (u_long)sizeof(struct mount));
-	mp->mnt_op = &cd9660_vfsops;
-	mp->mnt_flag = MNT_RDONLY;
-	LIST_INIT(&mp->mnt_vnodelist);
+	if ((error = vfs_rootmountalloc(MOUNT_CD9660, "root_device", &mp)) != 0)
+		return (error);
+
 	args.flags = ISOFSMNT_ROOT;
 	if ((error = iso_mountfs(rootvp, mp, p, &args)) != 0) {
+		mp->mnt_op->vfs_refcount--;
+		vfs_unbusy(mp);
 		free(mp, M_MOUNT);
 		return (error);
 	}
-	if ((error = vfs_lock(mp)) != 0) {
-		(void)cd9660_unmount(mp, 0, p);
-		free(mp, M_MOUNT);
-		return (error);
-	}
+	simple_lock(&mountlist_slock);
 	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
-	mp->mnt_vnodecovered = NULLVP;
-	imp = VFSTOISOFS(mp);
-	(void) copystr("/", mp->mnt_stat.f_mntonname, MNAMELEN - 1,
-	    &size);
-	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
-	(void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
-	    &size);
-	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+	simple_unlock(&mountlist_slock);
 	(void)cd9660_statfs(mp, &mp->mnt_stat, p);
-	vfs_unlock(mp);
+	vfs_unbusy(mp);
 	return (0);
 }
 
@@ -160,7 +149,7 @@
  */
 int
 cd9660_mount(mp, path, data, ndp, p)
-	register struct mount *mp;
+	struct mount *mp;
 	const char *path;
 	void *data;
 	struct nameidata *ndp;
@@ -641,6 +630,7 @@
 	MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
 	    M_WAITOK);
 	bzero((caddr_t)ip, sizeof(struct iso_node));
+	lockinit(&ip->i_lock, PINOD, "isonode", 0, 0);
 	vp->v_data = ip;
 	ip->i_vnode = vp;
 	ip->i_dev = dev;
@@ -785,9 +775,9 @@
 		if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {
 			/*
 			 * Discard unneeded vnode, but save its iso_node.
+			 * Note that the lock is carried over in the iso_node
+			 * to the replacement vnode.
 			 */
-			cd9660_ihashrem(ip);
-			VOP_UNLOCK(vp);
 			nvp->v_data = vp->v_data;
 			vp->v_data = NULL;
 			vp->v_op = spec_vnodeop_p;
@@ -798,7 +788,6 @@
 			 */
 			vp = nvp;
 			ip->i_vnode = vp;
-			cd9660_ihashins(ip);
 		}
 		break;
 	case VLNK:
@@ -845,3 +834,16 @@
 #endif
 	return 0;
 }
+
+int
+cd9660_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;
+{
+	return (EOPNOTSUPP);
+}
--- a/sys/isofs/cd9660/cd9660_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/isofs/cd9660/cd9660_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $	*/
+/*	$NetBSD: cd9660_vnops.c,v 1.43 1998/03/01 02:22:09 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)cd9660_vnops.c	8.15 (Berkeley) 12/5/94
+ *	@(#)cd9660_vnops.c	8.15 (Berkeley) 5/27/95
  */
 
 #include <sys/param.h>
@@ -161,6 +161,22 @@
 	struct vnode *vp = ap->a_vp;
 	struct iso_node *ip = VTOI(vp);
 
+	/*
+	 * Disallow write attempts unless the file is a socket,
+	 * fifo, or a block or character device resident on the
+	 * file system.
+	 */
+	if (ap->a_mode & VWRITE) {
+		switch (vp->v_type) {
+		case VDIR:
+		case VLNK:
+		case VREG:
+			return (EROFS);
+		default:
+			break;
+		}
+	}
+
 	return (vaccess(vp->v_type, ip->inode.iso_mode & ALLPERMS,
 	    ip->inode.iso_uid, ip->inode.iso_gid, ap->a_mode, ap->a_cred));
 }
@@ -423,8 +439,8 @@
 		struct uio *a_uio;
 		struct ucred *a_cred;
 		int *a_eofflag;
-		off_t *a_cookies;
-		int a_ncookies;
+		off_t **a_cookies;
+		int *a_ncookies;
 	} */ *ap = v;
 	register struct uio *uio = ap->a_uio;
 	struct isoreaddir *idp;
@@ -439,6 +455,11 @@
 	int error = 0;
 	int reclen;
 	u_short namelen;
+	off_t *cookies = NULL;
+	int ncookies = 0;
+
+	if (vdp->v_type != VDIR)
+		return (ENOTDIR);
 
 	dp = VTOI(vdp);
 	imp = dp->i_mnt;
@@ -453,9 +474,16 @@
 	idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
 	    DT_UNKNOWN;
 	idp->uio = uio;
+	if (ap->a_ncookies == NULL)
+		idp->cookies = NULL;
+	else {
+		ncookies = uio->uio_resid / 16;
+		MALLOC(cookies, off_t *, ncookies * sizeof(off_t), M_TEMP,
+		    M_WAITOK);
+		idp->cookies = cookies;
+		idp->ncookies = ncookies;
+	}
 	idp->eofflag = 1;
-	idp->cookies = ap->a_cookies;
-	idp->ncookies = ap->a_ncookies;
 	idp->curroff = uio->uio_offset;
 
 	if ((entryoffsetinblock = idp->curroff & bmask) &&
@@ -567,6 +595,18 @@
 	if (error < 0)
 		error = 0;
 
+	if (ap->a_ncookies != NULL) {
+		if (error)
+			FREE(cookies, M_TEMP);
+		else {
+			/*
+			 * Work out the number of cookies actually used.
+			 */
+			*ap->a_ncookies = ncookies - idp->ncookies;
+			*ap->a_cookies = cookies;
+		}
+	}
+
 	if (bp)
 		brelse (bp);
 
@@ -717,47 +757,12 @@
 {
 	struct vop_lock_args /* {
 		struct vnode *a_vp;
+		int a_flags;
+		struct proc *a_p;
 	} */ *ap = v;
 	register struct vnode *vp = ap->a_vp;
-	register struct iso_node *ip;
-#ifdef DIAGNOSTIC
-	struct proc *p = curproc;	/* XXX */
-#endif
 
-start:
-	while (vp->v_flag & VXLOCK) {
-		vp->v_flag |= VXWANT;
-		sleep((caddr_t)vp, PINOD);
-	}
-	if (vp->v_tag == VT_NON)
-		return (ENOENT);
-	ip = VTOI(vp);
-	if (ip->i_flag & IN_LOCKED) {
-		ip->i_flag |= IN_WANTED;
-#ifdef DIAGNOSTIC
-		if (p) {
-			if (p->p_pid == ip->i_lockholder)
-				panic("locking against myself");
-			ip->i_lockwaiter = p->p_pid;
-		} else
-			ip->i_lockwaiter = -1;
-#endif
-		(void) sleep((caddr_t)ip, PINOD);
-		goto start;
-	}
-#ifdef DIAGNOSTIC
-	ip->i_lockwaiter = 0;
-	if (ip->i_lockholder != 0)
-		panic("lockholder (%d) != 0", ip->i_lockholder);
-	if (p && p->p_pid == 0)
-		printf("locking by process 0\n");
-	if (p)
-		ip->i_lockholder = p->p_pid;
-	else
-		ip->i_lockholder = -1;
-#endif
-	ip->i_flag |= IN_LOCKED;
-	return (0);
+	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock));
 }
 
 /*
@@ -769,28 +774,13 @@
 {
 	struct vop_unlock_args /* {
 		struct vnode *a_vp;
+		int a_flags;
+		struct proc *a_p;
 	} */ *ap = v;
-	register struct iso_node *ip = VTOI(ap->a_vp);
-
-#ifdef DIAGNOSTIC
-	struct proc *p = curproc;	/* XXX */
+	struct vnode *vp = ap->a_vp;
 
-	if ((ip->i_flag & IN_LOCKED) == 0) {
-		vprint("cd9660_unlock: unlocked inode", ap->a_vp);
-		panic("cd9660_unlock NOT LOCKED");
-	}
-	if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 &&
-	    ip->i_lockholder > -1/* && lockcount++ < 100*/)
-		panic("unlocker (%d) != lock holder (%d)",
-		    p->p_pid, ip->i_lockholder);
-	ip->i_lockholder = 0;
-#endif
-	ip->i_flag &= ~IN_LOCKED;
-	if (ip->i_flag & IN_WANTED) {
-		ip->i_flag &= ~IN_WANTED;
-		wakeup((caddr_t)ip);
-	}
-	return (0);
+	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
+		&vp->v_interlock));
 }
 
 /*
@@ -841,6 +831,7 @@
 cd9660_print(v)
 	void *v;
 {
+
 	printf("tag VT_ISOFS, isofs vnode\n");
 	return (0);
 }
@@ -856,9 +847,7 @@
 		struct vnode *a_vp;
 	} */ *ap = v;
 
-	if (VTOI(ap->a_vp)->i_flag & IN_LOCKED)
-		return (1);
-	return (0);
+	return (lockstatus(&VTOI(ap->a_vp)->i_lock));
 }
 
 /*
@@ -909,6 +898,7 @@
 	void *v;
 {
 	struct vop_setattr_args /* {
+		struct vnodeop_desc *a_desc;
 		struct vnode *a_vp;
 		struct vattr *a_vap;
 		struct ucred *a_cred;
@@ -971,6 +961,7 @@
 #define	cd9660_truncate	genfs_eopnotsupp
 #define	cd9660_update	genfs_nullop
 #define	cd9660_bwrite	genfs_eopnotsupp
+#define cd9660_revoke	genfs_revoke
 
 /*
  * Global vfs data structures for cd9660
@@ -991,6 +982,7 @@
 	{ &vop_lease_desc, cd9660_lease_check },	/* lease */
 	{ &vop_ioctl_desc, cd9660_ioctl },		/* ioctl */
 	{ &vop_poll_desc, cd9660_poll },		/* poll */
+	{ &vop_revoke_desc, cd9660_revoke },		/* revoke */
 	{ &vop_mmap_desc, cd9660_mmap },		/* mmap */
 	{ &vop_fsync_desc, cd9660_fsync },		/* fsync */
 	{ &vop_seek_desc, cd9660_seek },		/* seek */
@@ -1043,6 +1035,7 @@
 	{ &vop_lease_desc, spec_lease_check },		/* lease */
 	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */
 	{ &vop_poll_desc, spec_poll },			/* poll */
+	{ &vop_revoke_desc, spec_revoke },		/* revoke */
 	{ &vop_mmap_desc, spec_mmap },			/* mmap */
 	{ &vop_fsync_desc, spec_fsync },		/* fsync */
 	{ &vop_seek_desc, spec_seek },			/* seek */
@@ -1093,6 +1086,7 @@
 	{ &vop_lease_desc, fifo_lease_check },		/* lease */
 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
 	{ &vop_poll_desc, fifo_poll },			/* poll */
+	{ &vop_revoke_desc, fifo_revoke },		/* revoke */
 	{ &vop_mmap_desc, fifo_mmap },			/* mmap */
 	{ &vop_fsync_desc, fifo_fsync },		/* fsync */
 	{ &vop_seek_desc, fifo_seek },			/* seek */
--- a/sys/isofs/cd9660/iso.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/isofs/cd9660/iso.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: iso.h,v 1.20 1997/07/07 22:45:34 cgd Exp $	*/
+/*	$NetBSD: iso.h,v 1.21 1998/03/01 02:22:09 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1994
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)iso.h	8.4 (Berkeley) 12/5/94
+ *	@(#)iso.h	8.6 (Berkeley) 5/10/95
  */
 
 /*
--- a/sys/kern/exec_elf32.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/exec_elf32.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec_elf32.c,v 1.27 1998/02/09 01:29:10 scottb Exp $	*/
+/*	$NetBSD: exec_elf32.c,v 1.28 1998/03/01 02:22:27 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou
@@ -387,7 +387,7 @@
 #ifdef notyet /* XXX cgd 960926 */
 	XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
 #endif
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 
 	if ((error = ELFNAME(read_from)(p, vp, 0, (caddr_t) &eh,
 	    sizeof(eh))) != 0)
@@ -443,7 +443,7 @@
 	return 0;
 
 badunlock:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 
 bad:
 	if (ph != NULL)
--- a/sys/kern/exec_script.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/exec_script.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec_script.c,v 1.18 1997/07/08 02:32:02 christos Exp $	*/
+/*	$NetBSD: exec_script.c,v 1.19 1998/03/01 02:22:27 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
@@ -163,9 +163,9 @@
 	 * close all open fd's when the start.  That kills this
 	 * method of implementing "safe" set-id and x-only scripts.
 	 */
-	VOP_LOCK(epp->ep_vp);
+	vn_lock(epp->ep_vp, LK_EXCLUSIVE | LK_RETRY);
 	error = VOP_ACCESS(epp->ep_vp, VREAD, p->p_ucred, p);
-	VOP_UNLOCK(epp->ep_vp);
+	VOP_UNLOCK(epp->ep_vp, 0);
 	if (error == EACCES
 #ifdef SETUIDSCRIPTS
 	    || script_sbits
--- a/sys/kern/init_main.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/init_main.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: init_main.c,v 1.117 1998/02/19 00:49:27 thorpej Exp $	*/
+/*	$NetBSD: init_main.c,v 1.118 1998/03/01 02:22:27 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1995 Christopher G. Demetriou.  All rights reserved.
@@ -38,7 +38,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)init_main.c	8.9 (Berkeley) 1/21/94
+ *	@(#)init_main.c	8.16 (Berkeley) 5/14/95
  */
 
 #include "fs_nfs.h"
@@ -374,7 +374,7 @@
 		panic("cannot find root vnode");
 	filedesc0.fd_fd.fd_cdir = rootvnode;
 	VREF(filedesc0.fd_fd.fd_cdir);
-	VOP_UNLOCK(rootvnode);
+	VOP_UNLOCK(rootvnode, 0);
 	filedesc0.fd_fd.fd_rdir = NULL;
 #if defined(UVM)
 	uvm_swap_init();
--- a/sys/kern/kern_acct.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_acct.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_acct.c,v 1.43 1997/10/19 02:00:25 mycroft Exp $	*/
+/*	$NetBSD: kern_acct.c,v 1.44 1998/03/01 02:22:27 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1994 Christopher G. Demetriou
@@ -38,7 +38,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_acct.c	8.1 (Berkeley) 6/14/93
+ *	@(#)kern_acct.c	8.8 (Berkeley) 5/14/95
  */
 
 #include <sys/param.h>
@@ -119,7 +119,7 @@
 		    p);
 		if ((error = vn_open(&nd, FWRITE, 0)) != 0)
 			return (error);
-		VOP_UNLOCK(nd.ni_vp);
+		VOP_UNLOCK(nd.ni_vp, 0);
 		if (nd.ni_vp->v_type != VREG) {
 			vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
 			return (EACCES);
--- a/sys/kern/kern_descrip.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_descrip.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_descrip.c,v 1.50 1998/02/10 14:09:25 mrg Exp $	*/
+/*	$NetBSD: kern_descrip.c,v 1.51 1998/03/01 02:22:28 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_descrip.c	8.6 (Berkeley) 4/19/94
+ *	@(#)kern_descrip.c	8.8 (Berkeley) 2/14/95
  */
 
 #include "opt_uvm.h"
--- a/sys/kern/kern_exec.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_exec.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_exec.c,v 1.89 1998/02/10 14:09:27 mrg Exp $	*/
+/*	$NetBSD: kern_exec.c,v 1.90 1998/03/01 02:22:28 fvdl Exp $	*/
 
 /*-
  * Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@@ -133,7 +133,7 @@
 		goto bad1;
 
 	/* unlock vp, since we don't need it locked from here on out. */
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 
 	/* now we have the file, get the exec header */
 	error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0,
--- a/sys/kern/kern_exit.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_exit.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_exit.c,v 1.48 1998/02/10 14:09:28 mrg Exp $	*/
+/*	$NetBSD: kern_exit.c,v 1.49 1998/03/01 02:22:28 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_exit.c	8.7 (Berkeley) 2/12/94
+ *	@(#)kern_exit.c	8.10 (Berkeley) 2/23/95
  */
 
 #include "opt_uvm.h"
@@ -189,7 +189,7 @@
 				 * if we blocked.
 				 */
 				if (sp->s_ttyvp)
-					vgoneall(sp->s_ttyvp);
+					VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
 			}
 			if (sp->s_ttyvp)
 				vrele(sp->s_ttyvp);
--- a/sys/kern/kern_fork.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_fork.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_fork.c,v 1.39 1998/02/14 00:37:31 thorpej Exp $	*/
+/*	$NetBSD: kern_fork.c,v 1.40 1998/03/01 02:22:28 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_fork.c	8.6 (Berkeley) 4/8/94
+ *	@(#)kern_fork.c	8.8 (Berkeley) 2/14/95
  */
 
 #include "opt_uvm.h"
--- a/sys/kern/kern_ktrace.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_ktrace.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_ktrace.c,v 1.24 1997/10/19 02:00:28 mycroft Exp $	*/
+/*	$NetBSD: kern_ktrace.c,v 1.25 1998/03/01 02:22:28 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_ktrace.c	8.2 (Berkeley) 9/23/93
+ *	@(#)kern_ktrace.c	8.5 (Berkeley) 5/14/95
  */
 
 #ifdef KTRACE
@@ -292,7 +292,7 @@
 			return (error);
 		}
 		vp = nd.ni_vp;
-		VOP_UNLOCK(vp);
+		VOP_UNLOCK(vp, 0);
 		if (vp->v_type != VREG) {
 			(void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
 			curp->p_traceflag &= ~KTRFAC_ACTIVE;
@@ -447,7 +447,7 @@
 {
 	struct uio auio;
 	struct iovec aiov[2];
-	register struct proc *p = curproc;	/* XXX */
+	struct proc *p = curproc;
 	int error;
 
 	if (vp == NULL)
@@ -467,9 +467,9 @@
 		aiov[1].iov_len = kth->ktr_len;
 		auio.uio_resid += kth->ktr_len;
 	}
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred);
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	if (!error)
 		return;
 	/*
--- a/sys/kern/kern_lock.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_lock.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_lock.c,v 1.5 1998/02/07 02:14:04 chs Exp $	*/
+/*	$NetBSD: kern_lock.c,v 1.6 1998/03/01 02:22:29 fvdl Exp $	*/
 
 /* 
  * Copyright (c) 1995
@@ -155,15 +155,15 @@
  * accepted shared locks and shared-to-exclusive upgrades to go away.
  */
 int
-lockmgr(lkp, flags, interlkp, p)
+lockmgr(lkp, flags, interlkp)
 	__volatile struct lock *lkp;
 	u_int flags;
 	struct simplelock *interlkp;
-	struct proc *p;
 {
 	int error;
 	pid_t pid;
 	int extflags;
+	struct proc *p = curproc;
 
 	error = 0;
 	if (p)
--- a/sys/kern/kern_malloc.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_malloc.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_malloc.c,v 1.31 1998/02/10 14:09:34 mrg Exp $	*/
+/*	$NetBSD: kern_malloc.c,v 1.32 1998/03/01 02:22:29 fvdl Exp $	*/
 
 /*
  * Copyright 1996 Christopher G. Demetriou.  All rights reserved.
@@ -33,7 +33,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_malloc.c	8.3 (Berkeley) 1/4/94
+ *	@(#)kern_malloc.c	8.4 (Berkeley) 5/20/95
  */
 
 #include "opt_uvm.h"
@@ -198,6 +198,9 @@
 	int copysize;
 	const char *savedtype;
 #endif
+#ifdef LOCKDEBUG
+	extern int simplelockrecurse;
+#endif
 #ifdef KMEMSTATS
 	register struct kmemstats *ksp = &kmemstats[type];
 
@@ -222,6 +225,10 @@
 #ifdef DIAGNOSTIC
 	copysize = 1 << indx < MAX_COPY ? 1 << indx : MAX_COPY;
 #endif
+#ifdef LOCKDEBUG
+	if (flags & M_NOWAIT)
+		simplelockrecurse++;
+#endif
 	if (kbp->kb_next == NULL) {
 		kbp->kb_last = NULL;
 		if (size > MAXALLOCSAVE)
@@ -248,6 +255,9 @@
 			 */
 			if ((flags & M_NOWAIT) == 0)
 				panic("malloc: out of space in kmem_map");
+#ifdef LOCKDEBUG
+			simplelockrecurse--;
+#endif
 			splx(s);
 			return ((void *) NULL);
 		}
@@ -385,6 +395,10 @@
 	domlog(va, size, type, 1, file, line);
 #endif
 	splx(s);
+#ifdef LOCKDEBUG
+	if (flags & M_NOWAIT)
+		simplelockrecurse--;
+#endif
 	return ((void *) va);
 }
 
--- a/sys/kern/kern_proc.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_proc.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_proc.c,v 1.22 1998/02/14 19:34:12 kleink Exp $	*/
+/*	$NetBSD: kern_proc.c,v 1.23 1998/03/01 02:22:29 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_proc.c	8.4 (Berkeley) 1/4/94
+ *	@(#)kern_proc.c	8.7 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/kern_prot.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_prot.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_prot.c,v 1.43 1998/02/14 01:17:51 thorpej Exp $	*/
+/*	$NetBSD: kern_prot.c,v 1.44 1998/03/01 02:22:29 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
+ *	@(#)kern_prot.c	8.9 (Berkeley) 2/14/95
  */
 
 /*
--- a/sys/kern/kern_resource.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_resource.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_resource.c,v 1.44 1998/02/10 14:09:37 mrg Exp $	*/
+/*	$NetBSD: kern_resource.c,v 1.45 1998/03/01 02:22:29 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_resource.c	8.5 (Berkeley) 1/21/94
+ *	@(#)kern_resource.c	8.8 (Berkeley) 2/14/95
  */
 
 #include "opt_uvm.h"
@@ -96,7 +96,8 @@
 			pg = curp->p_pgrp;
 		else if ((pg = pgfind(SCARG(uap, who))) == NULL)
 			break;
-		for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
+		for (p = pg->pg_members.lh_first; p != 0;
+		     p = p->p_pglist.le_next) {
 			if (p->p_nice < low)
 				low = p->p_nice;
 		}
--- a/sys/kern/kern_sig.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_sig.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sig.c,v 1.70 1998/02/10 14:09:41 mrg Exp $	*/
+/*	$NetBSD: kern_sig.c,v 1.71 1998/03/01 02:22:30 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_sig.c	8.7 (Berkeley) 4/18/94
+ *	@(#)kern_sig.c	8.14 (Berkeley) 5/14/95
  */
 
 #include "opt_uvm.h"
@@ -489,7 +489,7 @@
 }
 
 /*
- * Send a signal to a process group.  If checktty is 1,
+ * Send a signal to a process group. If checktty is 1,
  * limit to members which have a controlling terminal.
  */
 void
@@ -539,6 +539,7 @@
 		}
 	} else {
 		ps->ps_code = code;	/* XXX for core dump/debugger */
+		ps->ps_sig = signum;	/* XXX to verify code */
 		psignal(p, signum);
 	}
 }
@@ -790,8 +791,17 @@
 			/*
 			 * If traced, always stop, and stay
 			 * stopped until released by the debugger.
+
+			 * Note that we must clear the pending signal
+			 * before we call trace_req since that routine
+			 * might cause a fault, calling tsleep and
+			 * leading us back here again with the same signal.
+			 * Then we would be deadlocked because the tracer
+			 * would still be blocked on the ipc struct from
+			 * the initial request.
 			 */
 			p->p_xstat = signum;
+			p->p_siglist &= ~mask;
 			if ((p->p_flag & P_FSTRACE) == 0)
 				psignal(p->p_pptr, SIGCHLD);
 			do {
@@ -814,7 +824,14 @@
 			mask = sigmask(signum);
 			if ((p->p_sigmask & mask) != 0)
 				continue;
-			p->p_siglist &= ~mask;		/* take the signal! */
+			p->p_siglist |= mask;
+			/*
+			 * If the traced bit got turned off, go back up
+			 * to the top to rescan signals.  This ensures  
+			 * that p_sig* and ps_sigact are consistent.
+			 */
+			if ((p->p_flag & P_TRACED) == 0)
+				continue;
 		}
 
 		prop = sigprop[signum];
@@ -981,6 +998,7 @@
 		} else {
 			code = ps->ps_code;
 			ps->ps_code = 0;
+			ps->ps_sig = 0;
 		}
 		(*p->p_emul->e_sendsig)(action, signum, returnmask, code);
 	}
@@ -1142,7 +1160,7 @@
 		    UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
 	}
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	error1 = vn_close(vp, FWRITE, cred, p);
 	if (error == 0)
 		error = error1;
--- a/sys/kern/kern_subr.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_subr.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_subr.c,v 1.37 1998/02/22 12:53:53 hannken Exp $	*/
+/*	$NetBSD: kern_subr.c,v 1.38 1998/03/01 02:22:30 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -86,7 +86,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_subr.c	8.3 (Berkeley) 1/21/94
+ *	@(#)kern_subr.c	8.4 (Berkeley) 2/14/95
  */
 
 #include "opt_uvm.h"
@@ -576,7 +576,7 @@
 		     vops = LIST_NEXT(vops, vfs_list)) {
 			if (vops->vfs_mountroot != NULL &&
 			    vops->vfs_mountroot == mountroot)
-				break;
+			break;
 		}
 
 		if (vops == NULL) {
--- a/sys/kern/kern_synch.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_synch.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_synch.c,v 1.49 1998/02/12 20:39:41 kleink Exp $	*/
+/*	$NetBSD: kern_synch.c,v 1.50 1998/03/01 02:22:30 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1990, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_synch.c	8.6 (Berkeley) 1/21/94
+ *	@(#)kern_synch.c	8.9 (Berkeley) 5/19/95
  */
 
 #include "opt_uvm.h"
@@ -579,6 +579,10 @@
 	register long s, u;
 	struct timeval tv;
 
+#ifdef DEBUG
+	if (p->p_simple_locks)
+		panic("sleep: holding simple lock");
+#endif
 	/*
 	 * Compute the amount of time during which the current
 	 * process was running, and add that to its total so far.
--- a/sys/kern/kern_sysctl.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_sysctl.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sysctl.c,v 1.33 1998/02/14 00:37:33 thorpej Exp $	*/
+/*	$NetBSD: kern_sysctl.c,v 1.34 1998/03/01 02:22:30 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
+ *	@(#)kern_sysctl.c	8.9 (Berkeley) 5/20/95
  */
 
 /*
@@ -133,11 +133,9 @@
 	case CTL_NET:
 		fn = net_sysctl;
 		break;
-#ifdef notyet
-	case CTL_FS:
-		fn = fs_sysctl;
+	case CTL_VFS:
+		fn = vfs_sysctl;
 		break;
-#endif
 	case CTL_MACHDEP:
 		fn = cpu_sysctl;
 		break;
@@ -292,7 +290,7 @@
 		return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
 		    sizeof(struct timeval)));
 	case KERN_VNODE:
-		return (sysctl_vnode(oldp, oldlenp));
+		return (sysctl_vnode(oldp, oldlenp, p));
 	case KERN_PROC:
 		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
 	case KERN_FILE:
@@ -434,7 +432,7 @@
 	if (namelen != 2)
 		return (ENOTDIR);		/* overloaded */
 	cdp = debugvars[name[0]];
-	if (cdp->debugname == 0)
+	if (name[0] >= CTL_DEBUG_MAXID || cdp->debugname == 0)
 		return (EOPNOTSUPP);
 	switch (name[1]) {
 	case CTL_DEBUG_NAME:
--- a/sys/kern/kern_time.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_time.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_time.c,v 1.32 1998/02/20 07:22:14 mycroft Exp $	*/
+/*	$NetBSD: kern_time.c,v 1.33 1998/03/01 02:22:31 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_time.c	8.1 (Berkeley) 6/10/93
+ *	@(#)kern_time.c	8.4 (Berkeley) 5/26/95
  */
 
 #include "fs_nfs.h"
--- a/sys/kern/kern_xxx.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/kern_xxx.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_xxx.c,v 1.41 1998/02/05 07:59:57 mrg Exp $	*/
+/*	$NetBSD: kern_xxx.c,v 1.42 1998/03/01 02:22:31 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kern_xxx.c	8.2 (Berkeley) 11/14/93
+ *	@(#)kern_xxx.c	8.3 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/subr_autoconf.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/subr_autoconf.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_autoconf.c,v 1.27 1997/09/20 14:16:43 drochner Exp $	*/
+/*	$NetBSD: subr_autoconf.c,v 1.28 1998/03/01 02:22:31 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -43,7 +43,7 @@
  *
  * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp  (LBL)
  *
- *	@(#)subr_autoconf.c	8.1 (Berkeley) 6/10/93
+ *	@(#)subr_autoconf.c	8.3 (Berkeley) 5/17/94
  */
 
 #include <sys/param.h>
--- a/sys/kern/subr_log.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/subr_log.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_log.c,v 1.14 1998/01/28 02:35:10 thorpej Exp $	*/
+/*	$NetBSD: subr_log.c,v 1.15 1998/03/01 02:22:31 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)subr_log.c	8.1 (Berkeley) 6/10/93
+ *	@(#)subr_log.c	8.3 (Berkeley) 2/14/95
  */
 
 /*
--- a/sys/kern/subr_prf.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/subr_prf.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_prf.c,v 1.47 1997/11/17 00:59:56 ross Exp $	*/
+/*	$NetBSD: subr_prf.c,v 1.48 1998/03/01 02:22:31 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1986, 1988, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
+ *	@(#)subr_prf.c	8.4 (Berkeley) 5/4/95
  */
 
 #include <sys/param.h>
@@ -311,6 +311,11 @@
 			mbp->msg_bufc[mbp->msg_bufx++] = c;
 			if (mbp->msg_bufx < 0 || mbp->msg_bufx >= mbp->msg_bufs)
 				mbp->msg_bufx = 0;
+			/* If the buffer is full, keep the most recent data. */
+			if (mbp->msg_bufr == mbp->msg_bufx) {
+				 if (++mbp->msg_bufr >= mbp->msg_bufs)
+					mbp->msg_bufr = 0;
+			}
 		}
 	}
 	if ((flags & TOCONS) && constty == NULL && c != '\0')
--- a/sys/kern/subr_prof.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/subr_prof.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_prof.c,v 1.16 1997/10/17 22:37:38 jonathan Exp $	*/
+/*	$NetBSD: subr_prof.c,v 1.17 1998/03/01 02:22:31 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)subr_prof.c	8.3 (Berkeley) 9/23/93
+ *	@(#)subr_prof.c	8.4 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/subr_xxx.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/subr_xxx.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_xxx.c,v 1.10 1996/02/04 02:16:51 christos Exp $	*/
+/*	$NetBSD: subr_xxx.c,v 1.11 1998/03/01 02:22:32 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)subr_xxx.c	8.1 (Berkeley) 6/10/93
+ *	@(#)subr_xxx.c	8.3 (Berkeley) 3/29/95
  */
 
 /*
--- a/sys/kern/sys_generic.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/sys_generic.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_generic.c,v 1.35 1997/11/04 21:24:17 thorpej Exp $	*/
+/*	$NetBSD: sys_generic.c,v 1.36 1998/03/01 02:22:32 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)sys_generic.c	8.5 (Berkeley) 1/21/94
+ *	@(#)sys_generic.c	8.9 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
@@ -177,13 +177,6 @@
 		goto done;
 	auio.uio_resid = 0;
 	for (i = 0; i < iovcnt; i++) {
-#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;
@@ -338,13 +331,6 @@
 		goto done;
 	auio.uio_resid = 0;
 	for (i = 0; i < iovcnt; i++) {
-#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;
--- a/sys/kern/sys_socket.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/sys_socket.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_socket.c,v 1.15 1996/09/07 12:41:00 mycroft Exp $	*/
+/*	$NetBSD: sys_socket.c,v 1.16 1998/03/01 02:22:32 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1990, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)sys_socket.c	8.1 (Berkeley) 6/10/93
+ *	@(#)sys_socket.c	8.3 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/tty.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/tty.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty.c,v 1.104 1998/02/14 01:26:50 thorpej Exp $	*/
+/*	$NetBSD: tty.c,v 1.105 1998/03/01 02:22:32 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1990, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)tty.c	8.8 (Berkeley) 1/21/94
+ *	@(#)tty.c	8.13 (Berkeley) 1/9/95
  */
 
 #include "opt_uconsole.h"
--- a/sys/kern/tty_conf.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/tty_conf.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty_conf.c,v 1.19 1997/04/03 00:54:19 kleink Exp $	*/
+/*	$NetBSD: tty_conf.c,v 1.20 1998/03/01 02:22:32 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1991, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)tty_conf.c	8.4 (Berkeley) 1/21/94
+ *	@(#)tty_conf.c	8.5 (Berkeley) 1/9/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/tty_pty.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/tty_pty.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty_pty.c,v 1.38 1996/09/07 12:41:03 mycroft Exp $	*/
+/*	$NetBSD: tty_pty.c,v 1.39 1998/03/01 02:22:33 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)tty_pty.c	8.2 (Berkeley) 9/23/93
+ *	@(#)tty_pty.c	8.4 (Berkeley) 2/20/95
  */
 
 /*
@@ -594,7 +594,7 @@
 			}
 			SET(tp->t_lflag, EXTPROC);
 		} else {
-			if (ISSET(tp->t_state, EXTPROC) &&
+			if (ISSET(tp->t_lflag, EXTPROC) &&
 			    (pti->pt_flags & PF_PKT)) {
 				pti->pt_send |= TIOCPKT_IOCTL;
 				ptcwakeup(tp, FREAD);
--- a/sys/kern/tty_tb.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/tty_tb.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty_tb.c,v 1.18 1996/02/04 02:17:36 christos Exp $	*/
+/*	$NetBSD: tty_tb.c,v 1.19 1998/03/01 02:22:33 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)tty_tb.c	8.1 (Berkeley) 6/10/93
+ *	@(#)tty_tb.c	8.2 (Berkeley) 1/9/95
  */
 
 #include "tb.h"
--- a/sys/kern/tty_tty.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/tty_tty.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: tty_tty.c,v 1.14 1996/09/07 12:41:04 mycroft Exp $	*/
+/*	$NetBSD: tty_tty.c,v 1.15 1998/03/01 02:22:33 fvdl Exp $	*/
 
 /*-
- * Copyright (c) 1982, 1986, 1991, 1993
+ * Copyright (c) 1982, 1986, 1991, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -62,7 +62,7 @@
 
 	if (ttyvp == NULL)
 		return (ENXIO);
-	VOP_LOCK(ttyvp);
+	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY);
 #ifdef PARANOID
 	/*
 	 * Since group is tty and mode is 620 on most terminal lines
@@ -77,7 +77,7 @@
 	if (!error)
 #endif /* PARANOID */
 		error = VOP_OPEN(ttyvp, flag, NOCRED, p);
-	VOP_UNLOCK(ttyvp);
+	VOP_UNLOCK(ttyvp, 0);
 	return (error);
 }
 
@@ -93,9 +93,9 @@
 
 	if (ttyvp == NULL)
 		return (EIO);
-	VOP_LOCK(ttyvp);
+	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY);
 	error = VOP_READ(ttyvp, uio, flag, NOCRED);
-	VOP_UNLOCK(ttyvp);
+	VOP_UNLOCK(ttyvp, 0);
 	return (error);
 }
 
@@ -111,9 +111,9 @@
 
 	if (ttyvp == NULL)
 		return (EIO);
-	VOP_LOCK(ttyvp);
+	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY);
 	error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
-	VOP_UNLOCK(ttyvp);
+	VOP_UNLOCK(ttyvp, 0);
 	return (error);
 }
 
--- a/sys/kern/uipc_domain.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/uipc_domain.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_domain.c,v 1.17 1997/04/04 14:22:21 christos Exp $	*/
+/*	$NetBSD: uipc_domain.c,v 1.18 1998/03/01 02:22:33 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)uipc_domain.c	8.2 (Berkeley) 10/18/93
+ *	@(#)uipc_domain.c	8.3 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/uipc_mbuf.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/uipc_mbuf.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_mbuf.c,v 1.25 1998/02/12 20:39:46 kleink Exp $	*/
+/*	$NetBSD: uipc_mbuf.c,v 1.26 1998/03/01 02:22:33 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)uipc_mbuf.c	8.2 (Berkeley) 1/4/94
+ *	@(#)uipc_mbuf.c	8.4 (Berkeley) 2/14/95
  */
 
 #include "opt_uvm.h"
--- a/sys/kern/uipc_proto.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/uipc_proto.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_proto.c,v 1.9 1998/01/07 22:50:42 thorpej Exp $	*/
+/*	$NetBSD: uipc_proto.c,v 1.10 1998/03/01 02:22:34 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)uipc_proto.c	8.1 (Berkeley) 6/10/93
+ *	@(#)uipc_proto.c	8.2 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/uipc_socket.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/uipc_socket.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_socket.c,v 1.31 1998/01/07 23:47:08 thorpej Exp $	*/
+/*	$NetBSD: uipc_socket.c,v 1.32 1998/03/01 02:22:34 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1990, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)uipc_socket.c	8.3 (Berkeley) 4/15/94
+ *	@(#)uipc_socket.c	8.6 (Berkeley) 5/2/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/uipc_socket2.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/uipc_socket2.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_socket2.c,v 1.22 1998/01/07 23:47:09 thorpej Exp $	*/
+/*	$NetBSD: uipc_socket2.c,v 1.23 1998/03/01 02:22:34 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1990, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)uipc_socket2.c	8.1 (Berkeley) 6/10/93
+ *	@(#)uipc_socket2.c	8.2 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/uipc_syscalls.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/uipc_syscalls.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_syscalls.c,v 1.28 1998/02/06 23:19:26 thorpej Exp $	*/
+/*	$NetBSD: uipc_syscalls.c,v 1.29 1998/03/01 02:22:34 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1990, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)uipc_syscalls.c	8.4 (Berkeley) 2/21/94
+ *	@(#)uipc_syscalls.c	8.6 (Berkeley) 2/14/95
  */
 
 #include <sys/param.h>
--- a/sys/kern/uipc_usrreq.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/uipc_usrreq.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: uipc_usrreq.c,v 1.30 1998/01/07 22:57:09 thorpej Exp $	*/
+/*	$NetBSD: uipc_usrreq.c,v 1.31 1998/03/01 02:22:34 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)uipc_usrreq.c	8.3 (Berkeley) 1/4/94
+ *	@(#)uipc_usrreq.c	8.9 (Berkeley) 5/14/95
  */
 
 #include <sys/param.h>
@@ -598,7 +598,7 @@
 	unp->unp_vnode = vp;
 	unp->unp_addrlen = addrlen;
 	unp->unp_addr = sun;
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	return (0);
 
  bad:
--- a/sys/kern/vfs_cache.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_cache.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_cache.c,v 1.14 1998/02/07 02:44:49 chs Exp $	*/
+/*	$NetBSD: vfs_cache.c,v 1.15 1998/03/01 02:22:35 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -135,7 +135,8 @@
 				TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
 			}
 			return (ENOENT);
-		}
+		} else
+			nchstats.ncs_badhits++;
 	} else if (ncp->nc_vpid != ncp->nc_vp->v_id) {
 		nchstats.ncs_falsehits++;
 	} else {
--- a/sys/kern/vfs_cluster.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_cluster.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_cluster.c,v 1.14 1996/10/13 02:32:49 christos Exp $	*/
+/*	$NetBSD: vfs_cluster.c,v 1.15 1998/03/01 02:22:35 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)vfs_cluster.c	8.8 (Berkeley) 7/28/94
+ *	@(#)vfs_cluster.c	8.10 (Berkeley) 3/28/95
  */
 
 #include <sys/param.h>
@@ -47,13 +47,11 @@
 
 #include <vm/vm.h>
 
+int doreallocblks = 0;
+
 #ifdef DEBUG
 #include <sys/sysctl.h>
-int doreallocblks = 0;
 struct ctldebug debug13 = { "doreallocblks", &doreallocblks };
-#else
-/* XXX for cluster_write */
-#define doreallocblks 0
 #endif
 
 /*
--- a/sys/kern/vfs_init.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_init.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_init.c,v 1.9 1998/02/18 07:15:30 thorpej Exp $	*/
+/*	$NetBSD: vfs_init.c,v 1.10 1998/03/01 02:22:35 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)vfs_init.c	8.3 (Berkeley) 1/4/94
+ *	@(#)vfs_init.c	8.5 (Berkeley) 5/11/95
  */
 
 
--- a/sys/kern/vfs_lockf.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_lockf.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_lockf.c,v 1.11 1997/04/10 23:46:18 jtk Exp $	*/
+/*	$NetBSD: vfs_lockf.c,v 1.12 1998/03/01 02:22:35 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)ufs_lockf.c	8.3 (Berkeley) 1/6/94
+ *	@(#)ufs_lockf.c	8.4 (Berkeley) 10/26/94
  */
 
 #include <sys/param.h>
@@ -125,7 +125,7 @@
 	lock->lf_head = head;
 	lock->lf_type = fl->l_type;
 	lock->lf_next = (struct lockf *)0;
-	lock->lf_block = (struct lockf *)0;
+	TAILQ_INIT(&lock->lf_blkhd);
 	lock->lf_flags = flags;
 	/*
 	 * Do the requested operation.
@@ -237,7 +237,7 @@
 		 * Remember who blocked us (for deadlock detection).
 		 */
 		lock->lf_next = block;
-		lf_addblock(block, lock);
+		TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block);
 #ifdef LOCKF_DEBUG
 		if (lockf_debug & 1) {
 			lf_print("lf_setlock: blocking on", block);
@@ -247,23 +247,16 @@
 		error = tsleep((caddr_t)lock, priority, lockstr, 0);
 		if (error) {
 			/*
-			 * Delete ourselves from the waiting to lock list.
+			 * We may have been awakened by a signal (in
+			 * which case we must remove ourselves from the
+			 * blocked list) and/or by another process
+			 * releasing a lock (in which case we have already
+			 * been removed from the blocked list and our
+			 * lf_next field set to NOLOCKF).
 			 */
-			for (block = lock->lf_next;
-			     block != NOLOCKF;
-			     block = block->lf_block) {
-				if (block->lf_block != lock)
-					continue;
-				block->lf_block = block->lf_block->lf_block;
-				break;
-			}
-			/*
-			 * If we did not find ourselves on the list, but
-			 * are still linked onto a lock list, then something
-			 * is very wrong.
-			 */
-			if (block == NOLOCKF && lock->lf_next != NOLOCKF)
-				panic("lf_setlock: lost lock");
+			if (lock->lf_next)
+				TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock,
+				    lf_block);
 			free(lock, M_LOCKF);
 			return (error);
 		}
@@ -340,9 +333,12 @@
 			    overlap->lf_type == F_WRLCK) {
 				lf_wakelock(overlap);
 			} else {
-				ltmp = lock->lf_block;
-				lock->lf_block = overlap->lf_block;
-				lf_addblock(lock, ltmp);
+				while ((ltmp = overlap->lf_blkhd.tqh_first)) {
+					TAILQ_REMOVE(&overlap->lf_blkhd, ltmp,
+					    lf_block);
+					TAILQ_INSERT_TAIL(&lock->lf_blkhd,
+					    ltmp, lf_block);
+				}
 			}
 			/*
 			 * Add the new lock if necessary and delete the overlap.
@@ -640,34 +636,6 @@
 }
 
 /*
- * Add a lock to the end of the blocked list.
- */
-void
-lf_addblock(lock, blocked)
-	struct lockf *lock;
-	struct lockf *blocked;
-{
-	register struct lockf *lf;
-
-	if (blocked == NOLOCKF)
-		return;
-#ifdef LOCKF_DEBUG
-	if (lockf_debug & 2) {
-		lf_print("addblock: adding", blocked);
-		lf_print("to blocked list of", lock);
-	}
-#endif /* LOCKF_DEBUG */
-	if ((lf = lock->lf_block) == NOLOCKF) {
-		lock->lf_block = blocked;
-		return;
-	}
-	while (lf->lf_block != NOLOCKF)
-		lf = lf->lf_block;
-	lf->lf_block = blocked;
-	return;
-}
-
-/*
  * Split a lock and a contained region into
  * two or three locks as necessary.
  */
@@ -705,7 +673,7 @@
 	MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK);
 	bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock);
 	splitlock->lf_start = lock2->lf_end + 1;
-	splitlock->lf_block = NOLOCKF;
+	TAILQ_INIT(&splitlock->lf_blkhd);
 	lock1->lf_end = lock2->lf_start - 1;
 	/*
 	 * OK, now link it in
@@ -722,19 +690,15 @@
 lf_wakelock(listhead)
 	struct lockf *listhead;
 {
-	register struct lockf *blocklist, *wakelock;
+	register struct lockf *wakelock;
 
-	blocklist = listhead->lf_block;
-	listhead->lf_block = NOLOCKF;
-	while (blocklist != NOLOCKF) {
-		wakelock = blocklist;
-		blocklist = blocklist->lf_block;
-		wakelock->lf_block = NOLOCKF;
+	while ((wakelock = listhead->lf_blkhd.tqh_first)) {
+		TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block);
 		wakelock->lf_next = NOLOCKF;
 #ifdef LOCKF_DEBUG
 		if (lockf_debug & 2)
 			lf_print("lf_wakelock: awakening", wakelock);
-#endif /* LOCKF_DEBUG */
+#endif
 		wakeup((caddr_t)wakelock);
 	}
 }
@@ -759,8 +723,8 @@
 		lock->lf_type == F_WRLCK ? "exclusive" :
 		lock->lf_type == F_UNLCK ? "unlock" :
 		"unknown", lock->lf_start, lock->lf_end);
-	if (lock->lf_block)
-		printf(" block %p\n", lock->lf_block);
+	if (lock->lf_blkhd.tqh_first)
+		printf(" block %p\n", lock->lf_blkhd.tqh_first);
 	else
 		printf("\n");
 }
@@ -770,10 +734,10 @@
 	char *tag;
 	struct lockf *lock;
 {
-	register struct lockf *lf;
+	register struct lockf *lf, *blk;
 
 	printf("%s: Lock list:\n", tag);
-	for (lf = lock; lf; lf = lf->lf_block) {
+	for (lf = *lock->lf_head; lf; lf = lf->lf_next) {
 		printf("\tlock %p for ", lf);
 		if (lf->lf_flags & F_POSIX)
 			printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid);
@@ -784,10 +748,22 @@
 			lf->lf_type == F_WRLCK ? "exclusive" :
 			lf->lf_type == F_UNLCK ? "unlock" :
 			"unknown", lf->lf_start, lf->lf_end);
-		if (lf->lf_block)
-			printf(" block %p\n", lf->lf_block);
-		else
-			printf("\n");
+		for (blk = lf->lf_blkhd.tqh_first; blk;
+		     blk = blk->lf_block.tqe_next) {
+			if (blk->lf_flags & F_POSIX)
+				printf("proc %d",
+				    ((struct proc *)(blk->lf_id))->p_pid);
+			else
+				printf("id 0x%p", blk->lf_id);
+			printf(", %s, start %qx, end %qx",
+				blk->lf_type == F_RDLCK ? "shared" :
+				blk->lf_type == F_WRLCK ? "exclusive" :
+				blk->lf_type == F_UNLCK ? "unlock" :
+				"unknown", blk->lf_start, blk->lf_end);
+			if (blk->lf_blkhd.tqh_first)
+				 panic("lf_printlist: bad list");
+		}
+		printf("\n");
 	}
 }
 #endif /* LOCKF_DEBUG */
--- a/sys/kern/vfs_lookup.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_lookup.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_lookup.c,v 1.25 1997/10/30 22:47:06 enami Exp $	*/
+/*	$NetBSD: vfs_lookup.c,v 1.26 1998/03/01 02:22:35 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)vfs_lookup.c	8.6 (Berkeley) 11/21/94
+ *	@(#)vfs_lookup.c	8.10 (Berkeley) 5/27/95
  */
 
 #include <sys/param.h>
@@ -163,7 +163,7 @@
 			return (0);
 		}
 		if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
-			VOP_UNLOCK(ndp->ni_dvp);
+			VOP_UNLOCK(ndp->ni_dvp, 0);
 		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
 			error = ELOOP;
 			break;
@@ -294,7 +294,7 @@
 	cnp->cn_flags &= ~ISSYMLINK;
 	dp = ndp->ni_startdir;
 	ndp->ni_startdir = NULLVP;
-	VOP_LOCK(dp);
+	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
 
 	/*
 	 * If we have a leading string of slashes, remove them, and just make
@@ -419,7 +419,7 @@
 			dp = dp->v_mount->mnt_vnodecovered;
 			vput(tdp);
 			VREF(dp);
-			VOP_LOCK(dp);
+			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
 		}
 	}
 
@@ -428,6 +428,7 @@
 	 */
 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)
@@ -443,7 +444,7 @@
 			dp = dp->v_mount->mnt_vnodecovered;
 			vput(tdp);
 			VREF(dp);
-			VOP_LOCK(dp);
+			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
 			goto unionlookup;
 		}
 
@@ -461,7 +462,7 @@
 		 * If creating and at end of pathname, then can consider
 		 * allowing file to be created.
 		 */
-		if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) {
+		if (rdonly) {
 			error = EROFS;
 			goto bad;
 		}
@@ -500,12 +501,11 @@
 	 */
 	while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
 	       (cnp->cn_flags & NOCROSSMOUNT) == 0) {
-		if (mp->mnt_flag & MNT_MLOCK) {
-			mp->mnt_flag |= MNT_MWAIT;
-			sleep((caddr_t)mp, PVFS);
+		if (vfs_busy(mp, 0, 0))
 			continue;
-		}
-		if ((error = VFS_ROOT(dp->v_mountedhere, &tdp)) != 0)
+		error = VFS_ROOT(mp, &tdp);
+		vfs_unbusy(mp);
+		if (error)
 			goto bad2;
 		vput(dp);
 		ndp->ni_vp = dp = tdp;
@@ -544,19 +544,16 @@
 
 terminal:
 	/*
-	 * Check for read-only file systems.
+	 * Disallow directory write attempts on read-only file systems.
 	 */
-	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
+	if (rdonly &&
+	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
 		/*
 		 * Disallow directory write attempts on read-only
 		 * file systems.
 		 */
-		if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) ||
-		    (wantparent &&
-		     (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) {
-			error = EROFS;
-			goto bad2;
-		}
+		error = EROFS;
+		goto bad2;
 	}
 	if (ndp->ni_dvp != NULL) {
 		if (cnp->cn_flags & SAVESTART) {
@@ -567,12 +564,12 @@
 			vrele(ndp->ni_dvp);
 	}
 	if ((cnp->cn_flags & LOCKLEAF) == 0)
-		VOP_UNLOCK(dp);
+		VOP_UNLOCK(dp, 0);
 	return (0);
 
 bad2:
 	if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
-		VOP_UNLOCK(ndp->ni_dvp);
+		VOP_UNLOCK(ndp->ni_dvp, 0);
 	vrele(ndp->ni_dvp);
 bad:
 	vput(dp);
@@ -588,7 +585,7 @@
 	struct vnode *dvp, **vpp;
 	struct componentname *cnp;
 {
-	register struct vnode *dp = 0;	/* the directory we are searching */
+	struct vnode *dp = 0;		/* the directory we are searching */
 	int docache;			/* == 0 do not cache last component */
 	int wantparent;			/* 1 => wantparent or lockparent flag */
 	int rdonly;			/* lookup read-only flag bit */
@@ -609,7 +606,7 @@
 	rdonly = cnp->cn_flags & RDONLY;
 	cnp->cn_flags &= ~ISSYMLINK;
 	dp = dvp;
-	VOP_LOCK(dp);
+	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
 
 /* dirloop: */
 	/*
@@ -658,7 +655,7 @@
 		 * If creating and at end of pathname, then can consider
 		 * allowing file to be created.
 		 */
-		if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) {
+		if (rdonly) {
 			error = EROFS;
 			goto bad;
 		}
@@ -685,17 +682,10 @@
 	/*
 	 * Check for read-only file systems.
 	 */
-	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
-		/*
-		 * Disallow directory write attempts on read-only
-		 * file systems.
-		 */
-		if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) ||
-		    (wantparent &&
-		     (dvp->v_mount->mnt_flag & MNT_RDONLY))) {
-			error = EROFS;
-			goto bad2;
-		}
+	if (rdonly &&
+	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
+		error = EROFS;
+		goto bad2;
 	}
 	/* ASSERT(dvp == ndp->ni_startdir) */
 	if (cnp->cn_flags & SAVESTART)
@@ -703,12 +693,12 @@
 	if (!wantparent)
 		vrele(dvp);
 	if ((cnp->cn_flags & LOCKLEAF) == 0)
-		VOP_UNLOCK(dp);
+		VOP_UNLOCK(dp, 0);
 	return (0);
 
 bad2:
 	if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
-		VOP_UNLOCK(dvp);
+		VOP_UNLOCK(dvp, 0);
 	vrele(dvp);
 bad:
 	vput(dp);
--- a/sys/kern/vfs_subr.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_subr.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_subr.c,v 1.79 1998/02/18 07:16:41 thorpej Exp $	*/
+/*	$NetBSD: vfs_subr.c,v 1.80 1998/03/01 02:22:36 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -135,23 +135,25 @@
     TAILQ_HEAD_INITIALIZER(vnode_free_list);
 struct mntlist mountlist =			/* mounted filesystem list */
     CIRCLEQ_HEAD_INITIALIZER(mountlist);
-
 struct vfs_list_head vfs_list =			/* vfs list */
-    LIST_HEAD_INITIALIZER(vfs_list);
+	 LIST_HEAD_INITIALIZER(vfs_list);
 
 struct nfs_public nfs_pub;			/* publicly exported FS */
 
+struct simplelock mountlist_slock;
+static struct simplelock mntid_slock;
+struct simplelock mntvnode_slock;
+struct simplelock vnode_free_list_slock;
+static struct simplelock spechash_slock;
+
 /*
  * These define the root filesystem and device.
  */
 struct mount *rootfs;
 struct vnode *rootvnode;
-struct device *root_device;
+struct device *root_device;			/* root device */
 
-int vfs_lock __P((struct mount *));
-void vfs_unlock __P((struct mount *));
-struct mount *getvfs __P((fsid_t *));
-long makefstype __P((char *));
+struct mount *vfs_getvfs __P((fsid_t *));
 void vattr_null __P((struct vattr *));
 int getnewvnode __P((enum vtagtype, struct mount *, int (**)(void *),
 		     struct vnode **));
@@ -164,7 +166,6 @@
 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 *));
@@ -173,6 +174,7 @@
 int vflush __P((struct mount *, struct vnode *, int));
 void vgoneall __P((struct vnode *));
 void vgone __P((struct vnode *));
+void vgonel __P((struct vnode *vp, struct proc *p));
 int vcount __P((struct vnode *));
 void vprint __P((char *, struct vnode *));
 int vfs_mountedon __P((struct vnode *));
@@ -199,99 +201,117 @@
 vntblinit()
 {
 
-	/*
-	 * Nothing to do here anymore; vnode_free_list and mountlist
-	 * are now initialized data.
-	 */
-}
-
-/*
- * Lock a filesystem.
- * Used to prevent access to it while mounting and unmounting.
- */
-int
-vfs_lock(mp)
-	register struct mount *mp;
-{
-
-	while (mp->mnt_flag & MNT_MLOCK) {
-		mp->mnt_flag |= MNT_MWAIT;
-		tsleep((caddr_t)mp, PVFS, "vfslock", 0);
-	}
-	mp->mnt_flag |= MNT_MLOCK;
-	return (0);
+	simple_lock_init(&mntvnode_slock);
+	simple_lock_init(&mntid_slock);
+	simple_lock_init(&spechash_slock);
+	simple_lock_init(&vnode_free_list_slock);
 }
 
 /*
- * Unlock a locked filesystem.
- * Panic if filesystem is not locked.
- */
-void
-vfs_unlock(mp)
-	register struct mount *mp;
-{
-
-	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);
-	}
-}
-
-/*
- * Mark a mount point as busy.
- * Used to synchronize access and to delay unmounting.
+ * Mark a mount point as busy. Used to synchronize access and to delay
+ * unmounting. Interlock is not released on failure.
  */
 int
-vfs_busy(mp)
-	register struct mount *mp;
+vfs_busy(mp, flags, interlkp)
+	struct mount *mp;
+	int flags;
+	struct simplelock *interlkp;
 {
-	int unmounting = mp->mnt_flag & MNT_UNMOUNT;
+	int lkflags;
 
-	while(mp->mnt_flag & MNT_MPBUSY) {
-		mp->mnt_flag |= MNT_MPWANT;
-		tsleep((caddr_t)&mp->mnt_flag, PVFS, "vfsbusy", 0);
-		if (unmounting)
-			return (1);
+	if (mp->mnt_flag & MNT_UNMOUNT) {
+		if (flags & LK_NOWAIT)
+			return (ENOENT);
+		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);
 	}
-	mp->mnt_flag |= MNT_MPBUSY;
+	lkflags = LK_SHARED;
+	if (interlkp)
+		lkflags |= LK_INTERLOCK;
+	if (lockmgr(&mp->mnt_lock, lkflags, interlkp))
+		panic("vfs_busy: unexpected lock failure");
 	return (0);
 }
 
 /*
  * Free a busy filesystem.
- * Panic if filesystem is not busy.
  */
 void
 vfs_unbusy(mp)
-	register struct mount *mp;
+	struct mount *mp;
 {
 
-	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);
-	}
+	lockmgr(&mp->mnt_lock, LK_RELEASE, NULL);
+}
+
+/*
+ * Lookup a filesystem type, and if found allocate and initialize
+ * a mount structure for it.
+ *
+ * Devname is usually updated by mount(8) after booting.
+ */
+int
+vfs_rootmountalloc(fstypename, devname, mpp)
+	char *fstypename;
+	char *devname;
+	struct mount **mpp;
+{
+	struct vfsops *vfsp = NULL;
+	struct mount *mp;
+
+	for (vfsp = LIST_FIRST(&vfs_list); vfsp != NULL;
+	     vfsp = LIST_NEXT(vfsp, vfs_list))
+		if (!strncmp(vfsp->vfs_name, fstypename, MFSNAMELEN))
+			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);
+	LIST_INIT(&mp->mnt_vnodelist);
+	mp->mnt_op = vfsp;
+	mp->mnt_flag = MNT_RDONLY;
+	mp->mnt_vnodecovered = NULLVP;
+	vfsp->vfs_refcount++;
+	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfs_name, MFSNAMELEN);
+	mp->mnt_stat.f_mntonname[0] = '/';
+	(void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0);
+	*mpp = mp;
+	return (0);
 }
 
 /*
  * Lookup a mount point by filesystem identifier.
  */
 struct mount *
-getvfs(fsid)
+vfs_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])
+		    mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
+			simple_unlock(&mountlist_slock);
 			return (mp);
+		}
+	}
+	simple_unlock(&mountlist_slock);
 	return ((struct mount *)0);
 }
 
@@ -299,27 +319,30 @@
  * Get a new unique fsid
  */
 void
-getnewfsid(mp, mtype)
+vfs_getnewfsid(mp, fstypename)
 	struct mount *mp;
-	int mtype;
+	char *fstypename;
 {
 	static u_short xxxfs_mntid;
+	fsid_t tfsid;
+	int mtype;
 
-	fsid_t tfsid;
-
-	mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + 11, 0);	/* XXX */
+	simple_lock(&mntid_slock);
+	mtype = makefstype(fstypename);
+	mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
 	mp->mnt_stat.f_fsid.val[1] = mtype;
 	if (xxxfs_mntid == 0)
 		++xxxfs_mntid;
 	tfsid.val[0] = makedev((nblkdev + mtype) & 0xff, xxxfs_mntid);
 	tfsid.val[1] = mtype;
 	if (mountlist.cqh_first != (void *)&mountlist) {
-		while (getvfs(&tfsid)) {
+		while (vfs_getvfs(&tfsid)) {
 			tfsid.val[0]++;
 			xxxfs_mntid++;
 		}
 	}
 	mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
+	simple_unlock(&mntid_slock);
 }
 
 /*
@@ -338,6 +361,7 @@
 	return rv;
 }
 
+
 /*
  * Set vnode attributes to VNOVAL
  */
@@ -389,39 +413,50 @@
 	int (**vops) __P((void *));
 	struct vnode **vpp;
 {
-	register struct vnode *vp;
-#ifdef DIAGNOSTIC
+	struct proc *p = curproc;	/* XXX */
+	struct vnode *vp;
 	int s;
-#endif
 
+	simple_lock(&vnode_free_list_slock);
 	if ((vnode_free_list.tqh_first == NULL &&
 	     numvnodes < 2 * desiredvnodes) ||
 	    numvnodes < desiredvnodes) {
+		simple_unlock(&vnode_free_list_slock);
 		vp = (struct vnode *)malloc((u_long)sizeof *vp,
 		    M_VNODE, M_WAITOK);
 		bzero((char *)vp, sizeof *vp);
 		numvnodes++;
 	} else {
-		if ((vp = vnode_free_list.tqh_first) == NULL) {
+		for (vp = vnode_free_list.tqh_first;
+				vp != NULLVP; vp = vp->v_freelist.tqe_next) {
+			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);
 			tablefull("vnode");
 			*vpp = 0;
 			return (ENFILE);
 		}
-		if (vp->v_usecount) {
-			vprint("free vnode", vp);
+		if (vp->v_usecount)
 			panic("free vnode isn't");
-		}
 		TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
 		/* see comment on why 0xdeadb is set at end of vgone (below) */
 		vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb;
+		simple_unlock(&vnode_free_list_slock);
 		vp->v_lease = NULL;
 		if (vp->v_type != VBAD)
-			vgone(vp);
+			vgonel(vp, p);
+		else
+			simple_unlock(&vp->v_interlock);
 #ifdef DIAGNOSTIC
-		if (vp->v_data) {
-			vprint("cleaned vnode", vp);
+		if (vp->v_data)
 			panic("cleaned vnode isn't");
-		}
 		s = splbio();
 		if (vp->v_numoutput)
 			panic("Clean vnode has pending I/O's");
@@ -460,6 +495,7 @@
 	register struct mount *mp;
 {
 
+	simple_lock(&mntvnode_slock);
 	/*
 	 * Delete from old mount point vnode list, if on one.
 	 */
@@ -468,9 +504,9 @@
 	/*
 	 * Insert into list of vnodes for the new mount point, if available.
 	 */
-	if ((vp->v_mount = mp) == NULL)
-		return;
-	LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
+	if ((vp->v_mount = mp) != NULL)
+		LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
+	simple_unlock(&mntvnode_slock);
 }
 
 /*
@@ -723,8 +759,10 @@
 	struct vnode *nvp;
 	int error;
 
-	if (dev == NODEV)
+	if (dev == NODEV) {
+		*vpp = NULLVP;
 		return (0);
+	}
 	error = getnewvnode(VT_NON, NULL, spec_vnodeop_p, &nvp);
 	if (error) {
 		*vpp = NULLVP;
@@ -754,6 +792,7 @@
 	dev_t nvp_rdev;
 	struct mount *mp;
 {
+	struct proc *p = curproc;       /* XXX */
 	register struct vnode *vp;
 	struct vnode **vpp;
 
@@ -762,18 +801,23 @@
 
 	vpp = &speclisth[SPECHASH(nvp_rdev)];
 loop:
+	simple_lock(&spechash_slock);
 	for (vp = *vpp; vp; vp = vp->v_specnext) {
 		if (nvp_rdev != vp->v_rdev || nvp->v_type != vp->v_type)
 			continue;
 		/*
 		 * Alias, but not in use, so flush it out.
 		 */
+		simple_lock(&vp->v_interlock);
 		if (vp->v_usecount == 0) {
-			vgone(vp);
+			simple_unlock(&spechash_slock);
+			vgonel(vp, p);
 			goto loop;
 		}
-		if (vget(vp, 1))
+		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) {
+			simple_unlock(&spechash_slock);
 			goto loop;
+		}
 		break;
 	}
 	if (vp == NULL || vp->v_tag != VT_NON || vp->v_type != VBLK) {
@@ -783,17 +827,20 @@
 		nvp->v_hashchain = vpp;
 		nvp->v_specnext = *vpp;
 		nvp->v_specflags = 0;
+		simple_unlock(&spechash_slock);
 		nvp->v_speclockf = NULL;
 		*vpp = nvp;
-		if (vp != NULL) {
+		if (vp != NULLVP) {
 			nvp->v_flag |= VALIASED;
 			vp->v_flag |= VALIASED;
 			vput(vp);
 		}
 		return (NULLVP);
 	}
-	VOP_UNLOCK(vp);
-	vclean(vp, 0);
+	simple_unlock(&spechash_slock);
+	VOP_UNLOCK(vp, 0);
+	simple_lock(&vp->v_interlock);
+	vclean(vp, 0, p);
 	vp->v_op = nvp->v_op;
 	vp->v_tag = nvp->v_tag;
 	nvp->v_type = VNON;
@@ -810,47 +857,54 @@
  * been changed to a new file system type).
  */
 int
-vget(vp, lockflag)
-	register struct vnode *vp;
-	int lockflag;
+vget(vp, flags)
+	struct vnode *vp;
+	int flags;
 {
+	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 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.
+	 * return failure. Cleaning is determined by checking that
+	 * the VXLOCK flag is set.
 	 */
-	if ((vp->v_flag & VXLOCK) ||
-	    (vp->v_usecount == 0 &&
-	     vp->v_freelist.tqe_prev == (struct vnode **)0xdeadb)) {
+	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, "vget", 0);
-		return (1);
+		return (ENOENT);
 	}
-	if (vp->v_usecount == 0)
+	if (vp->v_usecount == 0) {
+		simple_lock(&vnode_free_list_slock);
 		TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
+		simple_unlock(&vnode_free_list_slock);
+	}
 	vp->v_usecount++;
-	if (lockflag)
-		VOP_LOCK(vp);
+	if (flags & LK_TYPE_MASK) {
+		if ((error = vn_lock(vp, flags | LK_INTERLOCK)))
+			vrele(vp);
+		return (error);
+	}
+	simple_unlock(&vp->v_interlock);
 	return (0);
 }
 
 /*
- * Vnode reference, just increment the count
+ * Vnode reference.
  */
 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);
 }
 
 /*
@@ -858,11 +912,35 @@
  */
 void
 vput(vp)
-	register struct vnode *vp;
+	struct vnode *vp;
 {
+	struct proc *p = curproc;	/* XXX */
 
-	VOP_UNLOCK(vp);
-	vrele(vp);
+#ifdef DIGANOSTIC
+	if (vp == NULL)
+		panic("vput: 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);
+		return;
+	}
+#ifdef DIAGNOSTIC
+	if (vp->v_usecount < 0 || vp->v_writecount != 0) {
+		vprint("vput: bad ref count", vp);
+		panic("vput: ref cnt");
+	}
+#endif
+	/*
+	 * insert at tail of LRU list
+	 */
+	simple_lock(&vnode_free_list_slock);
+	TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+	simple_unlock(&vnode_free_list_slock);
+	simple_unlock(&vp->v_interlock);
+	VOP_INACTIVE(vp, p);
 }
 
 /*
@@ -871,18 +949,22 @@
  */
 void
 vrele(vp)
-	register struct vnode *vp;
+	struct vnode *vp;
 {
+	struct proc *p = curproc;	/* XXX */
 
 #ifdef DIAGNOSTIC
 	if (vp == NULL)
 		panic("vrele: null vp");
 #endif
+	simple_lock(&vp->v_interlock);
 	vp->v_usecount--;
-	if (vp->v_usecount > 0)
+	if (vp->v_usecount > 0) {
+		simple_unlock(&vp->v_interlock);
 		return;
+	}
 #ifdef DIAGNOSTIC
-	if (vp->v_usecount != 0 || vp->v_writecount != 0) {
+	if (vp->v_usecount < 0 || vp->v_writecount != 0) {
 		vprint("vrele: bad ref count", vp);
 		panic("vrele: ref cnt");
 	}
@@ -890,10 +972,14 @@
 	/*
 	 * insert at tail of LRU list
 	 */
+	simple_lock(&vnode_free_list_slock);
 	TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
-	VOP_INACTIVE(vp);
+	simple_unlock(&vnode_free_list_slock);
+	if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK) == 0)
+		VOP_INACTIVE(vp, p);
 }
 
+#ifdef DIAGNOSTIC
 /*
  * Page or buffer structure gets a reference.
  */
@@ -902,7 +988,9 @@
 	register struct vnode *vp;
 {
 
+	simple_lock(&vp->v_interlock);
 	vp->v_holdcnt++;
+	simple_unlock(&vp->v_interlock);
 }
 
 /*
@@ -913,10 +1001,13 @@
 	register struct vnode *vp;
 {
 
+	simple_lock(&vp->v_interlock);
 	if (vp->v_holdcnt <= 0)
 		panic("holdrele: holdcnt");
 	vp->v_holdcnt--;
+	simple_unlock(&vp->v_interlock);
 }
+#endif /* DIAGNOSTIC */
 
 /*
  * Remove any vnodes in the vnode table belonging to mount point mp.
@@ -937,11 +1028,11 @@
 	struct vnode *skipvp;
 	int flags;
 {
+	struct proc *p = curproc;	/* XXX */
 	register struct vnode *vp, *nvp;
 	int busy = 0;
 
-	if ((mp->mnt_flag & MNT_MPBUSY) == 0)
-		panic("vflush: not busy");
+	simple_lock(&mntvnode_slock);
 loop:
 	for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
 		if (vp->v_mount != mp)
@@ -952,11 +1043,14 @@
 		 */
 		if (vp == skipvp)
 			continue;
+		simple_lock(&vp->v_interlock);
 		/*
 		 * Skip over a vnodes marked VSYSTEM.
 		 */
-		if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM))
+		if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
+			simple_unlock(&vp->v_interlock);
 			continue;
+		}
 		/*
 		 * If WRITECLOSE is set, only flush out regular file
 		 * vnodes open for writing.
@@ -969,7 +1063,9 @@
 		 * out the vnode data structures and we are done.
 		 */
 		if (vp->v_usecount == 0) {
-			vgone(vp);
+			simple_unlock(&mntvnode_slock);
+			vgonel(vp, p);
+			simple_lock(&mntvnode_slock);
 			continue;
 		}
 		/*
@@ -978,21 +1074,25 @@
 		 * 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) {
-				vgone(vp);
+				vgonel(vp, p);
 			} else {
-				vclean(vp, 0);
+				vclean(vp, 0, p);
 				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);
@@ -1002,9 +1102,10 @@
  * Disassociate the underlying file system from a vnode.
  */
 void
-vclean(vp, flags)
+vclean(vp, flags, p)
 	register struct vnode *vp;
 	int flags;
+	struct proc *p;
 {
 	int active;
 
@@ -1017,14 +1118,6 @@
 	if ((active = vp->v_usecount) != 0)
 		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
-	 * ensures that the VOP_INACTIVE routine is done with its work.
-	 * For active vnodes, it ensures that no other activity can
-	 * occur while the underlying object is being cleaned out.
-	 */
-	VOP_LOCK(vp);
-	/*
 	 * Prevent the vnode from being recycled or
 	 * brought into use while we clean it out.
 	 */
@@ -1038,32 +1131,52 @@
 	uvm_vnp_terminate(vp);
 #endif
 	/*
+	 * Even if the count is zero, the VOP_INACTIVE routine may still
+	 * have the object locked while it cleans it out. The VOP_LOCK
+	 * ensures that the VOP_INACTIVE routine is done with its work.
+	 * 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);
+
+	/*
 	 * Clean out any buffers associated with the vnode.
 	 */
 	if (flags & DOCLOSE)
-		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);
+		vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
+
 	/*
 	 * If purging an active vnode, it must be closed and
-	 * deactivated before being reclaimed.
+	 * deactivated before being reclaimed. Note that the
+	 * VOP_INACTIVE will unlock the vnode.
 	 */
 	if (active) {
 		if (flags & DOCLOSE)
-			VOP_CLOSE(vp, FNONBLOCK, NOCRED, NULL);
-		VOP_INACTIVE(vp);
+			VOP_CLOSE(vp, IO_NDELAY, NOCRED, NULL);
+		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);
 	}
 	/*
 	 * Reclaim the vnode.
 	 */
-	if (VOP_RECLAIM(vp))
+	if (VOP_RECLAIM(vp, p))
 		panic("vclean: cannot reclaim");
 	if (active)
 		vrele(vp);
 
+	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;
+	}
+
 	/*
 	 * Done with purge, notify sleepers of the grim news.
 	 */
@@ -1077,47 +1190,25 @@
 }
 
 /*
- * Eliminate all activity associated with  the requested vnode
- * and with all vnodes aliased to the requested vnode.
+ * Recycle an unused vnode to the front of the free list.
+ * Release the passed interlock if the vnode will be recycled.
  */
-void
-vgoneall(vp)
-	register struct vnode *vp;
-{
-	register struct vnode *vq;
-
-	if (vp->v_flag & VALIASED) {
-		/*
-		 * If a vgone (or vclean) is already in progress,
-		 * wait until it is done and return.
-		 */
-		if (vp->v_flag & VXLOCK) {
-			vp->v_flag |= VXWANT;
-			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;
-		while (vp->v_flag & VALIASED) {
-			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;
-				vgone(vq);
-				break;
-			}
-		}
-		/*
-		 * Remove the lock so that vgone below will
-		 * really eliminate the vnode after which time
-		 * vgone will awaken any sleepers.
-		 */
-		vp->v_flag &= ~VXLOCK;
+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);
 	}
-	vgone(vp);
+	simple_unlock(&vp->v_interlock);
+	return (0);
 }
 
 /*
@@ -1126,9 +1217,23 @@
  */
 void
 vgone(vp)
-	register struct vnode *vp;
+	struct vnode *vp;
 {
-	register struct vnode *vq;
+	struct proc *p = curproc;	/* XXX */
+
+	simple_lock(&vp->v_interlock);
+	vgonel(vp, p);
+}
+
+/*
+ * vgone, with the vp interlock held.
+ */
+void
+vgonel(vp, p)
+	register struct vnode *vp;
+	struct proc *p;
+{
+	struct vnode *vq;
 	struct vnode *vx;
 
 	/*
@@ -1137,21 +1242,25 @@
 	 */
 	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);
+	vclean(vp, DOCLOSE, p);
 	/*
 	 * Delete from old mount point vnode list, if on one.
 	 */
-	insmntque(vp, (struct mount *)0);
+	if (vp->v_mount != NULL)
+		insmntque(vp, (struct mount *)0);
 	/*
 	 * If special device, remove it from special device alias list.
+	 * if it is on one.
 	 */
-	if (vp->v_type == VBLK || vp->v_type == VCHR) {
+	if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) {
+		simple_lock(&spechash_slock);
 		if (*vp->v_hashchain == vp) {
 			*vp->v_hashchain = vp->v_specnext;
 		} else {
@@ -1180,6 +1289,7 @@
 				vx->v_flag &= ~VALIASED;
 			vp->v_flag &= ~VALIASED;
 		}
+		simple_unlock(&spechash_slock);
 		FREE(vp->v_specinfo, M_VNODE);
 		vp->v_specinfo = NULL;
 	}
@@ -1196,11 +1306,14 @@
 	 * getnewvnode after removing it from the freelist to ensure
 	 * that we do not try to move it here.
 	 */
-	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);
+	if (vp->v_usecount == 0) {
+		simple_lock(&vnode_free_list_slock);
+		if (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);
+		}
+		simple_unlock(&vnode_free_list_slock);
 	}
 	vp->v_type = VBAD;
 }
@@ -1214,15 +1327,19 @@
 	enum vtype type;
 	struct vnode **vpp;
 {
-	register struct vnode *vp;
+	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;
-		return (1);
+		rc = 1;
+		break;
 	}
-	return (0);
+	simple_unlock(&spechash_slock);
+	return (rc);
 }
 
 /*
@@ -1238,6 +1355,7 @@
 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)
@@ -1246,11 +1364,13 @@
 		 * 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);
 }
 
@@ -1305,21 +1425,93 @@
 void
 printlockedvnodes()
 {
-	register struct mount *mp;
-	register struct vnode *vp;
+	struct mount *mp, *nmp;
+	struct vnode *vp;
 
 	printf("Locked vnodes\n");
-	for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
-	     mp = mp->mnt_list.cqe_next) {
+	simple_lock(&mountlist_slock);
+	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
+			nmp = mp->mnt_list.cqe_next;
+			continue;
+		}
 		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);
 	}
+	simple_unlock(&mountlist_slock);
 }
 #endif
 
+extern const char *mountcompatnames[];
+extern const int nmountcompatnames;
+
+/*
+ * 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;
+{
+/*
+ * XXX needs work. Old interface (Lite2) used fs type numbers, can't
+ * do that anymore. It should work with names. Provide some compat
+ * code.
+ */
+#ifdef COMPAT_44
+	struct vfsconf vfc;
+	struct vfsops *vfsp;
+
+	/* all sysctl names at this level are at least name and field */
+	if (namelen < 2)
+		return (ENOTDIR);		/* overloaded */
+	if (name[0] != VFS_GENERIC) {
+		if (name[0] >= nmountcompatnames || name[0] < 0 ||
+		    mountcompatnames[name[0]] == NULL)
+			return (EOPNOTSUPP);
+		vfsp = vfs_getopsbyname(mountcompatnames[name[0]]);
+		if (vfsp == NULL)
+			return (EINVAL);
+		return ((*vfsp->vfs_sysctl)(&name[1], namelen - 1,
+		    oldp, oldlenp, newp, newlen, p));
+	}
+	switch (name[1]) {
+	case VFS_MAXTYPENUM:
+		return (sysctl_rdint(oldp, oldlenp, newp, nmountcompatnames));
+	case VFS_CONF:
+		if (namelen < 3)
+			return (ENOTDIR);	/* overloaded */
+		if (name[2] >= nmountcompatnames || name[2] < 0 ||
+		    mountcompatnames[name[2]] == NULL)
+			return (EOPNOTSUPP);
+		vfsp = vfs_getopsbyname(mountcompatnames[name[2]]);
+		if (vfsp == NULL)
+			return (EINVAL);
+		vfc.vfc_vfsops = NULL;	/* XXX point to vfsops->vfs_mount? */
+		strncpy(vfc.vfc_name, vfsp->vfs_name, MFSNAMELEN);
+		vfc.vfc_typenum = name[2];
+		vfc.vfc_flags = 0;
+		vfc.vfc_mountroot = vfsp->vfs_mountroot;
+		vfc.vfc_next = NULL;
+		return (sysctl_rdstruct(oldp, oldlenp, newp, &vfc,
+		    sizeof(struct vfsconf)));
+	}
+#endif
+	return (EOPNOTSUPP);
+}
+
 int kinfo_vdebug = 1;
 int kinfo_vgetfailed;
 #define KINFO_VNODESLOP	10
@@ -1329,13 +1521,14 @@
  */
 /* ARGSUSED */
 int
-sysctl_vnode(where, sizep)
+sysctl_vnode(where, sizep, p)
 	char *where;
 	size_t *sizep;
+	struct proc *p;
 {
-	register struct mount *mp, *nmp;
-	struct vnode *vp;
-	register char *bp = where, *savebp;
+	struct mount *mp, *nmp;
+	struct vnode *nvp, *vp;
+	char *bp = where, *savebp;
 	char *ewhere;
 	int error;
 
@@ -1346,38 +1539,50 @@
 		return (0);
 	}
 	ewhere = where + *sizep;
-		
+
+	simple_lock(&mountlist_slock);
 	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
-		nmp = mp->mnt_list.cqe_next;
-		if (vfs_busy(mp))
+		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
+			nmp = mp->mnt_list.cqe_next;
 			continue;
+		}
 		savebp = bp;
 again:
+		simple_lock(&mntvnode_slock);
 		for (vp = mp->mnt_vnodelist.lh_first;
 		     vp != NULL;
-		     vp = vp->v_mntvnodes.le_next) {
+		     vp = nvp) {
 			/*
 			 * 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);
 			}
+			simple_unlock(&mntvnode_slock);
 			if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
 			   (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);
 	}
+	simple_unlock(&mountlist_slock);
 
 	*sizep = bp - where;
 	return (0);
@@ -1388,22 +1593,27 @@
  */
 int
 vfs_mountedon(vp)
-	register struct vnode *vp;
+	struct vnode *vp;
 {
-	register struct vnode *vq;
+	struct vnode *vq;
+	int error = 0;
 
 	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_specflags & SI_MOUNTEDON)
-				return (EBUSY);
+			if (vq->v_specflags & SI_MOUNTEDON) {
+				error = EBUSY;
+				break;
+			}
 		}
+		simple_unlock(&spechash_slock);
 	}
-	return (0);
+	return (error);
 }
 
 /*
@@ -1747,6 +1957,7 @@
 {
 	register struct mount *mp, *nmp;
 	int allerror, error;
+	struct proc *p = curproc;	/* XXX */
 
 	for (allerror = 0,
 	     mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
@@ -1755,9 +1966,9 @@
 		printf("unmounting %s (%s)...\n",
 		    mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname);
 #endif
-		if (vfs_busy(mp))
+		if (vfs_busy(mp, 0, 0))
 			continue;
-		if ((error = dounmount(mp, MNT_FORCE, &proc0)) != 0) {
+		if ((error = dounmount(mp, MNT_FORCE, p)) != 0) {
 			printf("unmount of %s failed with error %d\n",
 			    mp->mnt_stat.f_mntonname, error);
 			allerror = 1;
--- a/sys/kern/vfs_syscalls.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_syscalls.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_syscalls.c,v 1.112 1998/02/14 19:49:43 kleink Exp $	*/
+/*	$NetBSD: vfs_syscalls.c,v 1.113 1998/03/01 02:22:36 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)vfs_syscalls.c	8.28 (Berkeley) 12/10/94
+ *	@(#)vfs_syscalls.c	8.42 (Berkeley) 7/31/95
  */
 
 #include "opt_uvm.h"
@@ -84,12 +84,12 @@
  * Mount a file system.
  */
 
-#if defined(COMPAT_09) || defined(COMPAT_43)
+#if defined(COMPAT_09) || defined(COMPAT_43) || defined(COMPAT_44)
 /*
  * This table is used to maintain compatibility with 4.3BSD
  * and NetBSD 0.9 mount syscalls.  Note, the order is important!
  */
-static const char *mountcompatnames[] = {
+const char *mountcompatnames[] = {
 	NULL,		/* 0 = MOUNT_NONE */
 	MOUNT_FFS,	/* 1 */
 	MOUNT_NFS,	/* 2 */
@@ -109,7 +109,7 @@
 	MOUNT_ADOSFS,	/* 16 */
 	MOUNT_EXT2FS,	/* 17 */
 };
-static const int nmountcompatnames = sizeof(mountcompatnames) /
+const int nmountcompatnames = sizeof(mountcompatnames) /
     sizeof(mountcompatnames[0]);
 #endif /* COMPAT_09 || COMPAT_43 */
 
@@ -126,8 +126,8 @@
 		syscallarg(int) flags;
 		syscallarg(void *) data;
 	} */ *uap = v;
-	register struct vnode *vp;
-	register struct mount *mp;
+	struct vnode *vp;
+	struct mount *mp;
 	int error, flag = 0;
 	char fstypename[MFSNAMELEN];
 	struct vattr va;
@@ -137,11 +137,16 @@
 	/*
 	 * Get vnode to be covered
 	 */
-	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+	NDINIT(&nd, LOOKUP, FOLLOW , UIO_USERSPACE,
 	    SCARG(uap, path), p);
 	if ((error = namei(&nd)) != 0)
 		return (error);
 	vp = nd.ni_vp;
+	/*
+	 * A lookup in VFS_MOUNT might result in an attempt to
+	 * lock this vnode again, so make the lock resursive.
+	 */
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);
 	if (SCARG(uap, flags) & MNT_UPDATE) {
 		if ((vp->v_flag & VROOT) == 0) {
 			vput(vp);
@@ -181,7 +186,11 @@
 			}
 			SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
 		}
-		VOP_UNLOCK(vp);
+		if (vfs_busy(mp, LK_NOWAIT, 0)) {
+			vput(vp);
+			return (EPERM);
+		}                     
+		VOP_UNLOCK(vp, 0);
 		goto update;
 	}
 	/*
@@ -252,13 +261,9 @@
 	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);
+	(void)vfs_busy(mp, LK_NOWAIT, 0);
 	mp->mnt_op = vfs;
-	if ((error = vfs_lock(mp)) != 0) {
-		free((caddr_t)mp, M_MOUNT);
-		vput(vp);
-		return (error);
-	}
-	/* Do this early in case we block later. */
 	vfs->vfs_refcount++;
 	vp->v_mountedhere = mp;
 	mp->mnt_vnodecovered = vp;
@@ -289,6 +294,7 @@
 		    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
 		if (error)
 			mp->mnt_flag = flag;
+		vfs_unbusy(mp);
 		return (error);
 	}
 	/*
@@ -296,16 +302,19 @@
 	 */
 	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);
-		vfs_unlock(mp);
+		VOP_UNLOCK(vp, 0);
+		vfs_unbusy(mp);
 		(void) VFS_STATFS(mp, &mp->mnt_stat, p);
-		error = VFS_START(mp, 0, p);
+		if ((error = VFS_START(mp, 0, p)))
+			vrele(vp);
 	} else {
 		mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
 		vfs->vfs_refcount--;
-		vfs_unlock(mp);
+		vfs_unbusy(mp);
 		free((caddr_t)mp, M_MOUNT);
 		vput(vp);
 	}
@@ -406,7 +415,7 @@
 	}
 	vput(vp);
 
-	if (vfs_busy(mp))
+	if (vfs_busy(mp, 0, 0))
 		return (EBUSY);
 
 	return (dounmount(mp, SCARG(uap, flags), p));
@@ -425,41 +434,43 @@
 	struct vnode *coveredvp;
 	int error;
 
-	coveredvp = mp->mnt_vnodecovered;
+	simple_lock(&mountlist_slock);
 	mp->mnt_flag |= MNT_UNMOUNT;
-	if ((error = vfs_lock(mp)) != 0) {
-		vfs_unbusy(mp);
-		return (error);
-	}
-
+	vfs_unbusy(mp);
+	lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock);
 	if (mp->mnt_flag & MNT_EXPUBLIC)
 		vfs_setpublicfs(NULL, NULL, NULL);
-
 	mp->mnt_flag &=~ MNT_ASYNC;
 #if !defined(UVM)
 	vnode_pager_umount(mp);	/* release cached vnodes */
 #endif
 	cache_purgevfs(mp);	/* remove cache entries for this file sys */
-	if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
+	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);
-	mp->mnt_flag &= ~MNT_UNMOUNT;
-	vfs_unbusy(mp);
+	simple_lock(&mountlist_slock);
 	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);
+		mp->mnt_flag &= ~MNT_UNMOUNT;
+		lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
+		    &mountlist_slock);
+		if (mp->mnt_flag & MNT_MWAIT)
+			wakeup((caddr_t)mp);
+		 return (error);
 	}
-	return (error);
+	CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
+	if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
+		coveredvp->v_mountedhere = NULL;
+		vrele(coveredvp);
+	}
+	mp->mnt_op->vfs_refcount--;
+	if (mp->mnt_vnodelist.lh_first != NULL)
+		panic("unmount: dangling vnode");
+	lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock);
+	if (mp->mnt_flag & MNT_MWAIT)
+		wakeup((caddr_t)mp);
+	free((caddr_t)mp, M_MOUNT);
+	return (0);
 }
 
 /*
@@ -480,18 +491,13 @@
 	register struct mount *mp, *nmp;
 	int asyncflag;
 
+	simple_lock(&mountlist_slock);
 	for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
-		/*
-		 * Get the prev 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)) {
+		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
+			nmp = mp->mnt_list.cqe_prev;
+			continue;
+		}
+		if ((mp->mnt_flag & MNT_RDONLY) == 0) {
 			asyncflag = mp->mnt_flag & MNT_ASYNC;
 			mp->mnt_flag &= ~MNT_ASYNC;
 #if defined(UVM)
@@ -501,15 +507,14 @@
 #endif
 			VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
 			if (asyncflag)
-				mp->mnt_flag |= MNT_ASYNC;
-			/*
-			 * Get the prev pointer again, as the prior filesystem
-			 * might have been unmounted while we were sync'ing.
-			 */
-			nmp = mp->mnt_list.cqe_prev;
-			vfs_unbusy(mp);
+				 mp->mnt_flag |= MNT_ASYNC;
 		}
+		simple_lock(&mountlist_slock);
+		nmp = mp->mnt_list.cqe_prev;
+		vfs_unbusy(mp);
+		
 	}
+	simple_unlock(&mountlist_slock);
 #ifdef DEBUG
 	if (syncprt)
 		vfs_bufstats();
@@ -627,11 +632,14 @@
 
 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
 	sfsp = (caddr_t)SCARG(uap, buf);
-	for (count = 0,
-	     mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
-		nmp = mp->mnt_list.cqe_next;
-		if (sfsp && count < maxcount &&
-		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {
+	simple_lock(&mountlist_slock);
+	count = 0;
+	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
+			nmp = mp->mnt_list.cqe_next;
+			continue;
+		}
+		if (sfsp && count < maxcount) {
 			sp = &mp->mnt_stat;
 			/*
 			 * If MNT_NOWAIT is specified, do not refresh the
@@ -639,8 +647,12 @@
 			 */
 			if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
 			    (SCARG(uap, flags) & MNT_WAIT)) &&
-			    (error = VFS_STATFS(mp, sp, p)) != 0)
+			    (error = VFS_STATFS(mp, sp, p)) != 0) {
+				simple_lock(&mountlist_slock);
+				nmp = mp->mnt_list.cqe_next;
+				vfs_unbusy(mp);
 				continue;
+			}
 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 			error = copyout(sp, sfsp, sizeof(*sp));
 			if (error)
@@ -648,7 +660,11 @@
 			sfsp += sizeof(*sp);
 		}
 		count++;
+		simple_lock(&mountlist_slock);
+		nmp = mp->mnt_list.cqe_next;
+		vfs_unbusy(mp);
 	}
+	simple_unlock(&mountlist_slock);
 	if (sfsp && count > maxcount)
 		*retval = maxcount;
 	else
@@ -679,27 +695,26 @@
 		return (error);
 	vp = (struct vnode *)fp->f_data;
 	VREF(vp);
-	VOP_LOCK(vp);
+	vn_lock(vp,  LK_EXCLUSIVE | LK_RETRY);
 	if (vp->v_type != VDIR)
 		error = ENOTDIR;
 	else
 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
 	while (!error && (mp = vp->v_mountedhere) != NULL) {
-		if (mp->mnt_flag & MNT_MLOCK) {
-			mp->mnt_flag |= MNT_MWAIT;
-			sleep((caddr_t)mp, PVFS);
+		if (vfs_busy(mp, 0, 0))
 			continue;
-		}
-		if ((error = VFS_ROOT(mp, &tdp)) != 0)
+		error = VFS_ROOT(mp, &tdp);
+		vfs_unbusy(mp);
+		if (error)
 			break;
 		vput(vp);
 		vp = tdp;
 	}
-	VOP_UNLOCK(vp);
 	if (error) {
-		vrele(vp);
+		vput(vp);
 		return (error);
 	}
+	VOP_UNLOCK(vp, 0);
 	vrele(fdp->fd_cdir);
 	fdp->fd_cdir = vp;
 	return (0);
@@ -778,9 +793,11 @@
 		error = ENOTDIR;
 	else
 		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
-	VOP_UNLOCK(vp);
+	
 	if (error)
-		vrele(vp);
+		vput(vp);
+	else
+		VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -849,7 +866,7 @@
 		type = F_FLOCK;
 		if ((flags & FNONBLOCK) == 0)
 			type |= F_WAIT;
-		VOP_UNLOCK(vp);
+		VOP_UNLOCK(vp, 0);
 		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
 		if (error) {
 			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
@@ -857,10 +874,10 @@
 			fdp->fd_ofiles[indx] = NULL;
 			return (error);
 		}
-		VOP_LOCK(vp);
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 		fp->f_flag |= FHASLOCK;
 	}
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	*retval = indx;
 	return (0);
 }
@@ -1422,14 +1439,10 @@
 		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_NULL(&vattr);
-		vattr.va_flags = SCARG(uap, flags);
-		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
-	}
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	VATTR_NULL(&vattr);
+	vattr.va_flags = SCARG(uap, flags);
+	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
 	vput(vp);
 	return (error);
 }
@@ -1457,15 +1470,11 @@
 		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 {
-		VATTR_NULL(&vattr);
-		vattr.va_flags = SCARG(uap, flags);
-		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
-	}
-	VOP_UNLOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	VATTR_NULL(&vattr);
+	vattr.va_flags = SCARG(uap, flags);
+	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -1559,15 +1568,11 @@
 	int error;
 
 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
-	VOP_LOCK(vp);
-	if (vp->v_mount->mnt_flag & MNT_RDONLY)
-		error = EROFS;
-	else {
-		VATTR_NULL(&vattr);
-		vattr.va_mode = mode & ALLPERMS;
-		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
-	}
-	VOP_UNLOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	VATTR_NULL(&vattr);
+	vattr.va_mode = mode & ALLPERMS;
+	error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -1751,11 +1756,7 @@
 	int error;
 
 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
-	VOP_LOCK(vp);
-	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
-		error = EROFS;
-		goto out;
-	}
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
 		goto out;
 
@@ -1801,7 +1802,7 @@
 #undef CHANGED
 	
 out:
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -1909,17 +1910,13 @@
 			return (error);
 	}
 	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);
-	}
-	VOP_UNLOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	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);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -1948,7 +1945,7 @@
 		return (error);
 	vp = nd.ni_vp;
 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	if (vp->v_type == VDIR)
 		error = EISDIR;
 	else if ((error = vn_writechk(vp)) == 0 &&
@@ -1987,7 +1984,7 @@
 		return (EINVAL);
 	vp = (struct vnode *)fp->f_data;
 	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	if (vp->v_type == VDIR)
 		error = EISDIR;
 	else if ((error = vn_writechk(vp)) == 0) {
@@ -1995,7 +1992,7 @@
 		vattr.va_size = SCARG(uap, length);
 		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
 	}
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -2019,9 +2016,9 @@
 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 		return (error);
 	vp = (struct vnode *)fp->f_data;
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -2326,17 +2323,13 @@
 	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)) != 0)
 		goto out;
 	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
-		vgoneall(vp);
+		VOP_REVOKE(vp, REVOKEALL);
 out:
 	vrele(vp);
 	return (error);
--- a/sys/kern/vfs_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vfs_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_vnops.c,v 1.27 1998/02/19 00:53:46 thorpej Exp $	*/
+/*	$NetBSD: vfs_vnops.c,v 1.28 1998/03/01 02:22:36 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)vfs_vnops.c	8.5 (Berkeley) 12/8/94
+ *	@(#)vfs_vnops.c	8.14 (Berkeley) 6/15/95
  */
 
 #include "fs_union.h"
@@ -63,6 +63,10 @@
 #include <uvm/uvm_extern.h>
 #endif
 
+#ifdef UNION
+#include <miscfs/union/union.h>
+#endif
+
 struct 	fileops vnops =
 	{ vn_read, vn_write, vn_ioctl, vn_poll, vn_closefile };
 
@@ -92,6 +96,8 @@
 			VATTR_NULL(&va);
 			va.va_type = VREG;
 			va.va_mode = cmode;
+			if (fmode & O_EXCL)
+				 va.va_vaflags |= VA_EXCLUSIVE;
 			VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
 			error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
 					   &ndp->ni_cnd, &va);
@@ -140,9 +146,9 @@
 		}
 	}
 	if (fmode & O_TRUNC) {
-		VOP_UNLOCK(vp);				/* XXX */
+		VOP_UNLOCK(vp, 0);			/* XXX */
 		VOP_LEASE(vp, p, cred, LEASE_WRITE);
-		VOP_LOCK(vp);				/* XXX */
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);	/* XXX */
 		VATTR_NULL(&va);
 		va.va_size = 0;
 		if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
@@ -160,8 +166,7 @@
 
 /*
  * Check for write permissions on the specified vnode.
- * The read-only status of the file system is checked.
- * Also, prototype text segments cannot be written.
+ * Prototype text segments cannot be written.
  */
 int
 vn_writechk(vp)
@@ -169,20 +174,6 @@
 {
 
 	/*
-	 * Disallow write attempts on read-only file systems;
-	 * unless the file is a socket or a block or character
-	 * device resident on the file system.
-	 */
-	if (vp->v_mount->mnt_flag & MNT_RDONLY) {
-		switch (vp->v_type) {
-		case VREG: case VDIR: case VLNK:
-			return (EROFS);
-		case VNON: case VCHR: case VSOCK:
-		case VFIFO: case VBAD: case VBLK:
-			break;
-		}
-	}
-	/*
 	 * If there's shared text associated with
 	 * the vnode, try to free it up once.  If
 	 * we fail, we can't allow writing.
@@ -237,7 +228,7 @@
 	int error;
 
 	if ((ioflg & IO_NODELOCKED) == 0)
-		VOP_LOCK(vp);
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	auio.uio_iov = &aiov;
 	auio.uio_iovcnt = 1;
 	aiov.iov_base = base;
@@ -258,7 +249,7 @@
 		if (auio.uio_resid && error == 0)
 			error = EIO;
 	if ((ioflg & IO_NODELOCKED) == 0)
-		VOP_UNLOCK(vp);
+		VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -266,10 +257,10 @@
 vn_readdir(fp, buf, segflg, count, done, p, cookies, ncookies)
 	struct file *fp;
 	char *buf;
-	int segflg, *done, ncookies;
+	int segflg, *done, *ncookies;
 	u_int count;
 	struct proc *p;
-	off_t *cookies;
+	off_t **cookies;
 {
 	struct vnode *vp = (struct vnode *)fp->f_data;
 	struct iovec aiov;
@@ -287,12 +278,12 @@
 	auio.uio_segflg = segflg;
 	auio.uio_procp = p;
 	auio.uio_resid = count;
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	auio.uio_offset = fp->f_offset;
-	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (off_t *)cookies,
+	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookies,
 		    ncookies);
 	fp->f_offset = auio.uio_offset;
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	if (error)
 		return (error);
 
@@ -321,12 +312,11 @@
 		
 		if (lvp != NULLVP) {
 			error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
-			VOP_UNLOCK(lvp);
-
 			if (error) {
-				vrele(lvp);
+				vput(lvp);
 				return (error);
 			}
+			VOP_UNLOCK(lvp, 0);
 			fp->f_data = (caddr_t) lvp;
 			fp->f_offset = 0;
 			error = vn_close(vp, FREAD, fp->f_cred, p);
@@ -362,17 +352,17 @@
 	struct uio *uio;
 	struct ucred *cred;
 {
-	register struct vnode *vp = (struct vnode *)fp->f_data;
+	struct vnode *vp = (struct vnode *)fp->f_data;
 	int count, error;
 
 	VOP_LEASE(vp, uio->uio_procp, cred, LEASE_READ);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	uio->uio_offset = fp->f_offset;
 	count = uio->uio_resid;
 	error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0,
 		cred);
 	fp->f_offset += count - uio->uio_resid;
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -385,7 +375,7 @@
 	struct uio *uio;
 	struct ucred *cred;
 {
-	register struct vnode *vp = (struct vnode *)fp->f_data;
+	struct vnode *vp = (struct vnode *)fp->f_data;
 	int count, error, ioflag = IO_UNIT;
 
 	if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
@@ -396,7 +386,7 @@
 	    (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
 		ioflag |= IO_SYNC;
 	VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	uio->uio_offset = fp->f_offset;
 	count = uio->uio_resid;
 	error = VOP_WRITE(vp, uio, ioflag, cred);
@@ -404,7 +394,7 @@
 		fp->f_offset = uio->uio_offset;
 	else
 		fp->f_offset += count - uio->uio_resid;
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	return (error);
 }
 
@@ -531,6 +521,35 @@
 }
 
 /*
+ * Check that the vnode is still valid, and if so
+ * acquire requested lock.
+ */
+int
+vn_lock(vp, flags)
+	struct vnode *vp;
+	int flags;
+{
+	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);
+			if (error == 0)
+				return (error);
+		}
+		flags &= ~LK_INTERLOCK;
+	} while (flags & LK_RETRY);
+	return (error);
+}
+
+/*
  * File table vnode close routine.
  */
 int
--- a/sys/kern/vnode_if.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vnode_if.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnode_if.c,v 1.9 1998/01/09 06:41:17 thorpej Exp $	*/
+/*	$NetBSD: vnode_if.c,v 1.10 1998/03/01 02:22:36 fvdl Exp $	*/
 
 /*
  * Warning: This file is generated automatically.
@@ -11,7 +11,7 @@
  */
 
 /*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1994, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -252,6 +252,22 @@
 	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
@@ -461,7 +477,7 @@
 	vop_inactive_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
-	VDESC_NO_OFFSET,
+	VOPARG_OFFSETOF(struct vop_inactive_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
@@ -477,7 +493,7 @@
 	vop_reclaim_vp_offsets,
 	VDESC_NO_OFFSET,
 	VDESC_NO_OFFSET,
-	VDESC_NO_OFFSET,
+	VOPARG_OFFSETOF(struct vop_reclaim_args, a_p),
 	VDESC_NO_OFFSET,
 	NULL,
 };
@@ -773,6 +789,7 @@
 	&vop_write_desc,
 	&vop_ioctl_desc,
 	&vop_poll_desc,
+	&vop_revoke_desc,
 	&vop_mmap_desc,
 	&vop_fsync_desc,
 	&vop_seek_desc,
--- a/sys/kern/vnode_if.sh	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vnode_if.sh	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,7 @@
 #!/bin/sh -
 copyright="\
 /*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1994, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,7 @@
  * SUCH DAMAGE.
  */
 "
-SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.15 1998/01/09 06:40:43 thorpej Exp $'
+SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.16 1998/03/01 02:22:37 fvdl Exp $'
 
 # Script to produce VFS front-end sugar.
 #
--- a/sys/kern/vnode_if.src	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/kern/vnode_if.src	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-#	$NetBSD: vnode_if.src,v 1.12 1997/10/10 02:07:00 fvdl Exp $
+#	$NetBSD: vnode_if.src,v 1.13 1998/03/01 02:22:37 fvdl Exp $
 #
 # Copyright (c) 1992, 1993
 #	The Regents of the University of California.  All rights reserved.
@@ -31,7 +31,33 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-#	@(#)vnode_if.src	8.3 (Berkeley) 2/3/94
+#	@(#)vnode_if.src	8.14 (Berkeley) 8/6/95
+#
+#
+
+# 
+# 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;
@@ -39,6 +65,10 @@
 	IN struct componentname *cnp;
 };
 
+#
+#% create     dvp     L U U
+#% create     vpp     - L -
+#
 vop_create {
 	IN WILLRELE struct vnode *dvp;
 	OUT struct vnode **vpp;
@@ -46,6 +76,10 @@
 	IN struct vattr *vap;
 };
 
+#
+#% mknod      dvp     L U U
+#% mknod      vpp     - X -
+#
 vop_mknod {
 	IN WILLRELE struct vnode *dvp;
 	OUT WILLRELE struct vnode **vpp;
@@ -53,6 +87,9 @@
 	IN struct vattr *vap;
 };
 
+#
+#% open               vp      L L L
+#
 vop_open {
 	IN struct vnode *vp;
 	IN int mode;
@@ -60,6 +97,9 @@
 	IN struct proc *p;
 };
 
+#
+#% close      vp      U U U
+#
 vop_close {
 	IN struct vnode *vp;
 	IN int fflag;
@@ -67,6 +107,9 @@
 	IN struct proc *p;
 };
 
+#
+#% access     vp      L L L
+#
 vop_access {
 	IN struct vnode *vp;
 	IN int mode;
@@ -74,6 +117,9 @@
 	IN struct proc *p;
 };
 
+#
+#% getattr    vp      = = =
+#
 vop_getattr {
 	IN struct vnode *vp;
 	IN struct vattr *vap;
@@ -81,6 +127,9 @@
 	IN struct proc *p;
 };
 
+#
+#% setattr    vp      L L L
+#
 vop_setattr {
 	IN struct vnode *vp;
 	IN struct vattr *vap;
@@ -88,6 +137,9 @@
 	IN struct proc *p;
 };
 
+#
+#% read               vp      L L L
+#
 vop_read {
 	IN struct vnode *vp;
 	INOUT struct uio *uio;
@@ -95,6 +147,9 @@
 	IN struct ucred *cred;
 };
 
+#
+#% write      vp      L L L
+#
 vop_write {
 	IN struct vnode *vp;
 	INOUT struct uio *uio;
@@ -102,6 +157,9 @@
 	IN struct ucred *cred;
 };
 
+#
+#% ioctl      vp      U U U
+#
 vop_ioctl {
 	IN struct vnode *vp;
 	IN u_long command;
@@ -111,12 +169,26 @@
 	IN struct proc *p;
 };
 
+#
+#% poll     vp      U U U
+#
 vop_poll {
 	IN struct vnode *vp;
 	IN int events;
 	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;
@@ -124,6 +196,9 @@
 	IN struct proc *p;
 };
 
+#
+#% fsync      vp      L L L
+#
 vop_fsync {
 	IN struct vnode *vp;
 	IN struct ucred *cred;
@@ -131,7 +206,9 @@
 	IN struct proc *p;
 };
 
-# Needs word: Is newoff right?  What's it mean?
+#
+# Needs work: Is newoff right?  What's it mean?
+#
 vop_seek {
 	IN struct vnode *vp;
 	IN off_t oldoff;
@@ -139,18 +216,32 @@
 	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;
@@ -160,6 +251,10 @@
 	IN struct componentname *tcnp;
 };
 
+#
+#% mkdir      dvp     L U U
+#% mkdir      vpp     - L - 
+#
 vop_mkdir {
 	IN WILLRELE struct vnode *dvp;
 	OUT struct vnode **vpp;
@@ -167,12 +262,24 @@
 	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;
@@ -181,42 +288,71 @@
 	IN char *target;
 };
 
+#
+#% readdir    vp      L L L   
+#
 vop_readdir {
 	IN struct vnode *vp;
 	INOUT struct uio *uio;
 	IN struct ucred *cred;
 	OUT int *eofflag;
-	OUT off_t *cookies;
-	IN int ncookies;
+	OUT off_t **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;
 };
 
+#
+#% unlock     vp      L U L
+#
 vop_unlock {
 	IN struct vnode *vp;
+	IN int flags;
 };
 
+#
+#% bmap               vp      L L L
+#% bmap               vpp     - U -
+#
 vop_bmap {
 	IN struct vnode *vp;
 	IN daddr_t bn;
@@ -225,24 +361,39 @@
 	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;
@@ -251,6 +402,9 @@
 	IN int flags;
 };
 
+#
+#% blkatoff   vp      L L L
+#
 vop_blkatoff {
 	IN struct vnode *vp;
 	IN off_t offset;
@@ -258,6 +412,9 @@
 	OUT struct buf **bpp;
 };
 
+#
+#% valloc     pvp     L L L
+#
 vop_valloc {
 	IN struct vnode *pvp;
 	IN int mode;
@@ -265,17 +422,26 @@
 	OUT struct vnode **vpp;
 };
 
+#
+#% 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;
@@ -284,6 +450,9 @@
 	IN struct proc *p;
 };
 
+#
+#% update     vp      L L L
+#
 vop_update {
 	IN struct vnode *vp;
 	IN struct timespec *access;
@@ -291,6 +460,9 @@
 	IN int waitfor;
 };
 
+# 
+#% lease      vp      = = =
+# 
 vop_lease {
 	IN struct vnode *vp;
 	IN struct proc *p;
@@ -298,13 +470,20 @@
 	IN int flag;
 };
 
+#
+#% whiteout   dvp     L L L
+#% whiteout   cnp     - - -
+#% whiteout   flag    - - -
+# 
 vop_whiteout {
 	IN struct vnode *dvp;
 	IN struct componentname *cnp;
 	IN int flags;
 };
 
+#
 # Needs work: no vp?
+#
 #vop_bwrite {
 #	IN struct buf *bp;
 #};
--- a/sys/lib/libkern/libkern.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/lib/libkern/libkern.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: libkern.h,v 1.20 1998/02/22 09:18:38 mycroft Exp $	*/
+/*	$NetBSD: libkern.h,v 1.21 1998/03/01 02:23:53 fvdl Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)libkern.h	8.1 (Berkeley) 6/10/93
+ *	@(#)libkern.h	8.2 (Berkeley) 8/5/94
  */
 
 #include <sys/types.h>
--- a/sys/lkm/netinet/if_ipl/mln_ipl.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/lkm/netinet/if_ipl/mln_ipl.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: mln_ipl.c,v 1.17 1997/10/30 15:39:56 mrg Exp $	*/
+/*	$NetBSD: mln_ipl.c,v 1.18 1998/03/01 02:25:22 fvdl Exp $	*/
 
 /*
  * Copyright (C) 1993-1997 by Darren Reed.
@@ -50,6 +50,10 @@
 #include <netinet/ip_compat.h>
 #include <netinet/ip_fil.h>
 
+#if !defined(__NetBSD_Version__) || __NetBSD_Version__ < 103050000
+#define vn_lock(v,f) VOP_LOCK(v)
+#endif
+
 
 #if !defined(VOP_LEASE) && defined(LEASE_CHECK)
 #define	VOP_LEASE	LEASE_CHECK
@@ -181,7 +185,7 @@
 		if ((error = namei(&nd)))
 			return (error);
 		VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
-		VOP_LOCK(nd.ni_vp);
+		vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY);
 		VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
 		(void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
 	}
--- a/sys/miscfs/deadfs/dead_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/deadfs/dead_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: dead_vnops.c,v 1.21 1996/10/13 02:21:25 christos Exp $	*/
+/*	$NetBSD: dead_vnops.c,v 1.22 1998/03/01 02:21:24 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -89,6 +89,7 @@
 #define dead_truncate	genfs_nullop
 #define dead_update	genfs_nullop
 #define dead_bwrite	genfs_nullop
+#define dead_revoke	genfs_nullop
 
 int	chkvnlock __P((struct vnode *));
 
@@ -108,6 +109,7 @@
 	{ &vop_write_desc, dead_write },		/* write */
 	{ &vop_ioctl_desc, dead_ioctl },		/* ioctl */
 	{ &vop_poll_desc, dead_poll },			/* poll */
+	{ &vop_revoke_desc, dead_revoke },		/* revoke */
 	{ &vop_mmap_desc, dead_mmap },			/* mmap */
 	{ &vop_fsync_desc, dead_fsync },		/* fsync */
 	{ &vop_seek_desc, dead_seek },			/* seek */
--- a/sys/miscfs/fdesc/fdesc.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/fdesc/fdesc.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: fdesc.h,v 1.9 1996/02/09 22:40:03 christos Exp $	*/
+/*	$NetBSD: fdesc.h,v 1.10 1998/03/01 02:21:08 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)fdesc.h	8.6 (Berkeley) 8/20/94
+ *	@(#)fdesc.h	8.8 (Berkeley) 4/3/95
  *
  * #Id: fdesc.h,v 1.8 1993/04/06 15:28:33 jsp Exp #
  */
--- a/sys/miscfs/fdesc/fdesc_vfsops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/fdesc/fdesc_vfsops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: fdesc_vfsops.c,v 1.23 1998/02/18 07:26:57 thorpej Exp $	*/
+/*	$NetBSD: fdesc_vfsops.c,v 1.24 1998/03/01 02:21:08 fvdl Exp $	*/
 
 /*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)fdesc_vfsops.c	8.4 (Berkeley) 1/21/94
+ *	@(#)fdesc_vfsops.c	8.10 (Berkeley) 5/14/95
  *
  * #Id: fdesc_vfsops.c,v 1.9 1993/04/06 15:28:33 jsp Exp #
  */
@@ -70,6 +70,8 @@
 int	fdesc_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
 			  struct vnode **, int *, struct ucred **));
 int	fdesc_vptofh __P((struct vnode *, struct fid *));
+int	fdesc_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+			  struct proc *));
 
 /*
  * Mount the per-process file descriptors (/dev/fd)
@@ -104,7 +106,7 @@
 	fmp->f_root = rvp;
 	mp->mnt_flag |= MNT_LOCAL;
 	mp->mnt_data = (qaddr_t)fmp;
-	getnewfsid(mp, makefstype(MOUNT_FDESC));
+	vfs_getnewfsid(mp, MOUNT_FDESC);
 
 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -130,15 +132,10 @@
 {
 	int error;
 	int flags = 0;
-	extern int doforce;
 	struct vnode *rootvp = VFSTOFDESC(mp)->f_root;
 
-	if (mntflags & MNT_FORCE) {
-		/* fdesc can never be rootfs so don't check for it */
-		if (!doforce)
-			return (EINVAL);
+	if (mntflags & MNT_FORCE)
 		flags |= FORCECLOSE;
-	}
 
 	/*
 	 * Clear out buffer cache.  I don't think we
@@ -179,7 +176,7 @@
 	 */
 	vp = VFSTOFDESC(mp)->f_root;
 	VREF(vp);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	*vpp = vp;
 	return (0);
 }
@@ -229,11 +226,6 @@
 	if (fdp->fd_nfiles < lim)
 		freefd += (lim - fdp->fd_nfiles);
 
-#ifdef COMPAT_09
-	sbp->f_type = 6;
-#else
-	sbp->f_type = 0;
-#endif
 	sbp->f_bsize = DEV_BSIZE;
 	sbp->f_iosize = DEV_BSIZE;
 	sbp->f_blocks = 2;		/* 1K to keep df happy */
@@ -241,6 +233,11 @@
 	sbp->f_bavail = 0;
 	sbp->f_files = lim + 1;		/* Allow for "." */
 	sbp->f_ffree = freefd;		/* See comments above */
+#ifdef COMPAT_09
+	sbp->f_type = 6;
+#else
+	sbp->f_type = 0;
+#endif
 	if (sbp != &mp->mnt_stat) {
 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
@@ -300,6 +297,19 @@
 	return (EOPNOTSUPP);
 }
 
+int
+fdesc_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;
+{
+	return (EOPNOTSUPP);
+}
+
 extern struct vnodeopv_desc fdesc_vnodeop_opv_desc;
 
 struct vnodeopv_desc *fdesc_vnodeopv_descs[] = {
@@ -320,6 +330,7 @@
 	fdesc_fhtovp,
 	fdesc_vptofh,
 	fdesc_init,
+	fdesc_sysctl,
 	NULL,				/* vfs_mountroot */
 	fdesc_vnodeopv_descs,
 };
--- a/sys/miscfs/fdesc/fdesc_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/fdesc/fdesc_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: fdesc_vnops.c,v 1.43 1998/02/07 02:44:50 chs Exp $	*/
+/*	$NetBSD: fdesc_vnops.c,v 1.44 1998/03/01 02:21:08 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)fdesc_vnops.c	8.12 (Berkeley) 8/20/94
+ *	@(#)fdesc_vnops.c	8.17 (Berkeley) 5/22/95
  *
  * #Id: fdesc_vnops.c,v 1.12 1993/04/06 16:17:17 jsp Exp #
  */
@@ -112,13 +112,13 @@
 #define	fdesc_abortop	genfs_abortop
 int	fdesc_inactive	__P((void *));
 int	fdesc_reclaim	__P((void *));
-#define	fdesc_lock	genfs_nullop
-#define	fdesc_unlock	genfs_nullop
+#define	fdesc_lock	genfs_nolock
+#define	fdesc_unlock	genfs_nounlock
 #define	fdesc_bmap	genfs_badop
 #define	fdesc_strategy	genfs_badop
 int	fdesc_print	__P((void *));
 int	fdesc_pathconf	__P((void *));
-#define	fdesc_islocked	genfs_nullop
+#define	fdesc_islocked	genfs_noislocked
 #define	fdesc_advlock	genfs_eopnotsupp
 #define	fdesc_blkatoff	genfs_eopnotsupp
 #define	fdesc_valloc	genfs_eopnotsupp
@@ -126,6 +126,7 @@
 #define	fdesc_truncate	genfs_eopnotsupp
 #define	fdesc_update	genfs_nullop
 #define	fdesc_bwrite	genfs_eopnotsupp
+#define fdesc_revoke	genfs_revoke
 
 static int fdesc_attr __P((int, struct vattr *, struct ucred *, struct proc *));
 
@@ -144,6 +145,7 @@
 	{ &vop_write_desc, fdesc_write },		/* write */
 	{ &vop_ioctl_desc, fdesc_ioctl },		/* ioctl */
 	{ &vop_poll_desc, fdesc_poll },			/* poll */
+	{ &vop_revoke_desc, fdesc_revoke },		/* revoke */
 	{ &vop_mmap_desc, fdesc_mmap },			/* mmap */
 	{ &vop_fsync_desc, fdesc_fsync },		/* fsync */
 	{ &vop_seek_desc, fdesc_seek },			/* seek */
@@ -265,25 +267,22 @@
 	} */ *ap = v;
 	struct vnode **vpp = ap->a_vpp;
 	struct vnode *dvp = ap->a_dvp;
-	const char *pname;
-	struct proc *p;
-	int nfiles;
+	struct componentname *cnp = ap->a_cnp;
+	struct proc *p = cnp->cn_proc;
+	const char *pname = cnp->cn_nameptr;
+	int nfiles = p->p_fd->fd_nfiles;
 	unsigned fd = 0;
 	int error;
 	struct vnode *fvp;
 	char *ln;
 
-	pname = ap->a_cnp->cn_nameptr;
-	if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
+	if (cnp->cn_namelen == 1 && *pname == '.') {
 		*vpp = dvp;
-		VREF(dvp);	
-		VOP_LOCK(dvp);
+		VREF(dvp);
+		vn_lock(dvp, LK_SHARED | LK_RETRY);
 		return (0);
 	}
 
-	p = ap->a_cnp->cn_proc;
-	nfiles = p->p_fd->fd_nfiles;
-
 	switch (VTOFDESC(dvp)->fd_type) {
 	default:
 	case Flink:
@@ -293,17 +292,17 @@
 		goto bad;
 
 	case Froot:
-		if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
+		if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
 			error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
 			if (error)
 				goto bad;
 			*vpp = fvp;
 			fvp->v_type = VDIR;
-			VOP_LOCK(fvp);
+			vn_lock(dvp, LK_SHARED | LK_RETRY);
 			return (0);
 		}
 
-		if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
+		if (cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
 			struct vnode *ttyvp = cttyvp(p);
 			if (ttyvp == NULL) {
 				error = ENXIO;
@@ -314,12 +313,12 @@
 				goto bad;
 			*vpp = fvp;
 			fvp->v_type = VCHR;
-			VOP_LOCK(fvp);
+			vn_lock(dvp, LK_SHARED | LK_RETRY);
 			return (0);
 		}
 
 		ln = 0;
-		switch (ap->a_cnp->cn_namelen) {
+		switch (cnp->cn_namelen) {
 		case 5:
 			if (bcmp(pname, "stdin", 5) == 0) {
 				ln = "fd/0";
@@ -345,7 +344,7 @@
 			VTOFDESC(fvp)->fd_link = ln;
 			*vpp = fvp;
 			fvp->v_type = VLNK;
-			VOP_LOCK(fvp);
+			vn_lock(fvp, LK_SHARED | LK_RETRY);
 			return (0);
 		} else {
 			error = ENOENT;
@@ -355,9 +354,11 @@
 		/* FALL THROUGH */
 
 	case Fdevfd:
-		if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
+		if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
 			error = fdesc_root(dvp->v_mount, vpp);
-			return (error);
+			if (error)
+				goto bad;
+			return (0);
 		}
 
 		fd = 0;
@@ -381,11 +382,13 @@
 		if (error)
 			goto bad;
 		VTOFDESC(fvp)->fd_fd = fd;
+		vn_lock(dvp, LK_SHARED | LK_RETRY);
 		*vpp = fvp;
 		return (0);
 	}
 
 bad:;
+	vn_lock(dvp, LK_SHARED | LK_RETRY);
 	*vpp = NULL;
 	return (error);
 }
@@ -647,16 +650,16 @@
 		struct uio *a_uio;
 		struct ucred *a_cred;
 		int *a_eofflag;
-		off_t *a_cookies;
-		int a_ncookies;
+		off_t **a_cookies;
+		int *a_ncookies;
 	} */ *ap = v;
 	struct uio *uio = ap->a_uio;
 	struct dirent d;
 	struct filedesc *fdp;
 	int i;
 	int error;
-	off_t *cookies = ap->a_cookies;
-	int ncookies = ap->a_ncookies;
+	off_t *cookies = NULL;
+	int ncookies = 0;
 
 	switch (VTOFDESC(ap->a_vp)->fd_type) {
 	case Fctty:
@@ -680,10 +683,20 @@
 	i = uio->uio_offset;
 	bzero((caddr_t)&d, UIO_MX);
 	d.d_reclen = UIO_MX;
+	if (ap->a_ncookies)
+		ncookies = (uio->uio_resid / UIO_MX);
 
 	if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
 		struct fdesc_target *ft;
 
+		if (ap->a_ncookies) {
+			ncookies = min(ncookies, (nfdesc_targets - i));
+			MALLOC(cookies, off_t *, ncookies * sizeof(off_t),
+			    M_TEMP, M_WAITOK);
+			*ap->a_cookies = cookies;
+			*ap->a_ncookies = ncookies;
+		}
+
 		for (ft = &fdesc_targets[i];
 		     uio->uio_resid >= UIO_MX && i < nfdesc_targets; ft++, i++) {
 			switch (ft->ft_fileno) {
@@ -709,10 +722,16 @@
 
 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
 				break;
-			if (ncookies-- > 0)
+			if (cookies)
 				*cookies++ = i + 1;
 		}
 	} else {
+		if (ap->a_ncookies) {
+			ncookies = min(ncookies, (fdp->fd_nfiles + 2));
+			MALLOC(cookies, off_t *, ncookies * sizeof(off_t),				    M_TEMP, M_WAITOK);
+			*ap->a_cookies = cookies;
+			*ap->a_ncookies = ncookies;
+		}
 		for (; i - 2 < fdp->fd_nfiles && uio->uio_resid >= UIO_MX;
 		     i++) {
 			switch (i) {
@@ -736,11 +755,17 @@
 
 			if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
 				break;
-			if (ncookies-- > 0)
+			if (cookies)
 				*cookies++ = i + 1;
 		}
 	}
 
+	if (ap->a_ncookies && error) {
+		FREE(*ap->a_cookies, M_TEMP);
+		*ap->a_ncookies = 0;
+		*ap->a_cookies = NULL;
+	}
+
 	uio->uio_offset = i;
 	return (error);
 }
@@ -878,6 +903,7 @@
 {
 	struct vop_inactive_args /* {
 		struct vnode *a_vp;
+		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 
@@ -885,6 +911,7 @@
 	 * Clear out the v_type field to avoid
 	 * nasty things happening in vgone().
 	 */
+	VOP_UNLOCK(vp, 0);
 	vp->v_type = VNON;
 	return (0);
 }
--- a/sys/miscfs/fifofs/fifo.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/fifofs/fifo.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: fifo.h,v 1.12 1996/09/07 12:41:10 mycroft Exp $	*/
+/*	$NetBSD: fifo.h,v 1.13 1998/03/01 02:21:30 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993
@@ -32,7 +32,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)fifo.h	8.3 (Berkeley) 8/10/94
+ *	@(#)fifo.h	8.6 (Berkeley) 5/21/95
  */
 #ifdef FIFO
 
@@ -52,6 +52,7 @@
 #define fifo_lease_check genfs_nullop
 int	fifo_ioctl	__P((void *));
 int	fifo_poll	__P((void *));
+#define fifo_revoke	genfs_revoke
 #define fifo_mmap	genfs_badop
 #define fifo_fsync	genfs_nullop
 #define fifo_seek	genfs_badop
@@ -64,14 +65,14 @@
 #define fifo_readdir	genfs_badop
 #define fifo_readlink	genfs_badop
 #define fifo_abortop	genfs_badop
-#define fifo_inactive	genfs_nullop
 #define fifo_reclaim	genfs_nullop
-int	fifo_lock	__P((void *));
-int	fifo_unlock	__P((void *));
+#define	fifo_lock	genfs_nolock
+#define	fifo_unlock	genfs_nounlock
+int	fifo_inactive	__P((void *));
 int	fifo_bmap	__P((void *));
 #define fifo_strategy	genfs_badop
 int	fifo_print	__P((void *));
-#define fifo_islocked	genfs_nullop
+#define fifo_islocked	genfs_noislocked
 int	fifo_pathconf	__P((void *));
 #define	fifo_advlock	genfs_eopnotsupp
 #define fifo_blkatoff	genfs_badop
--- a/sys/miscfs/fifofs/fifo_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/fifofs/fifo_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: fifo_vnops.c,v 1.24 1997/10/09 13:12:01 mycroft Exp $	*/
+/*	$NetBSD: fifo_vnops.c,v 1.25 1998/03/01 02:21:30 fvdl Exp $	*/
 
 /*
- * Copyright (c) 1990, 1993
+ * Copyright (c) 1990, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,10 +32,11 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)fifo_vnops.c	8.4 (Berkeley) 8/10/94
+ *	@(#)fifo_vnops.c	8.10 (Berkeley) 5/27/95
  */
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/time.h>
 #include <sys/namei.h>
@@ -43,7 +44,6 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/stat.h>
-#include <sys/systm.h>
 #include <sys/ioctl.h>
 #include <sys/file.h>
 #include <sys/errno.h>
@@ -81,6 +81,7 @@
 	{ &vop_lease_desc, fifo_lease_check },		/* lease */
 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
 	{ &vop_poll_desc, fifo_poll },			/* poll */
+	{ &vop_revoke_desc, fifo_revoke },		/* revoke */
 	{ &vop_mmap_desc, fifo_mmap },			/* mmap */
 	{ &vop_fsync_desc, fifo_fsync },		/* fsync */
 	{ &vop_seek_desc, fifo_seek },			/* seek */
@@ -147,8 +148,9 @@
 		struct ucred *a_cred;
 		struct proc *a_p;
 	} */ *ap = v;
-	register struct vnode *vp = ap->a_vp;
-	register struct fifoinfo *fip;
+	struct vnode *vp = ap->a_vp;
+	struct fifoinfo *fip;
+	struct proc *p = ap->a_p;
 	struct socket *rso, *wso;
 	int error;
 	static const char openstr[] = "fifo";
@@ -198,10 +200,10 @@
 		if (ap->a_mode & O_NONBLOCK) {
 		} else {
 			while (fip->fi_writers == 0) {
-				VOP_UNLOCK(vp);
+				VOP_UNLOCK(vp, 0);
 				error = tsleep((caddr_t)&fip->fi_readers,
 				    PCATCH | PSOCK, openstr, 0);
-				VOP_LOCK(vp);
+				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 				if (error)
 					goto bad;
 			}
@@ -215,10 +217,10 @@
 			}
 		} else {
 			while (fip->fi_readers == 0) {
-				VOP_UNLOCK(vp);
+				VOP_UNLOCK(vp, 0);
 				error = tsleep((caddr_t)&fip->fi_writers,
 				    PCATCH | PSOCK, openstr, 0);
-				VOP_LOCK(vp);
+				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 				if (error)
 					goto bad;
 			}
@@ -226,7 +228,7 @@
 	}
 	return (0);
 bad:
-	VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
+	VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p);
 	return (error);
 }
 
@@ -244,8 +246,8 @@
 		int  a_ioflag;
 		struct ucred *a_cred;
 	} */ *ap = v;
-	register struct uio *uio = ap->a_uio;
-	register struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
+	struct uio *uio = ap->a_uio;
+	struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock;
 	int error, startresid;
 
 #ifdef DIAGNOSTIC
@@ -257,10 +259,10 @@
 	if (ap->a_ioflag & IO_NDELAY)
 		rso->so_state |= SS_NBIO;
 	startresid = uio->uio_resid;
-	VOP_UNLOCK(ap->a_vp);
+	VOP_UNLOCK(ap->a_vp, 0);
 	error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
 	    (struct mbuf **)0, (int *)0);
-	VOP_LOCK(ap->a_vp);
+	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
 	/*
 	 * Clear EOF indication after first such return.
 	 */
@@ -298,9 +300,9 @@
 #endif
 	if (ap->a_ioflag & IO_NDELAY)
 		wso->so_state |= SS_NBIO;
-	VOP_UNLOCK(ap->a_vp);
+	VOP_UNLOCK(ap->a_vp, 0);
 	error = sosend(wso, (struct mbuf *)0, ap->a_uio, 0, (struct mbuf *)0, 0);
-	VOP_LOCK(ap->a_vp);
+	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
 	if (ap->a_ioflag & IO_NDELAY)
 		wso->so_state &= ~SS_NBIO;
 	return (error);
@@ -369,6 +371,19 @@
 	return (revents);
 }
 
+int
+fifo_inactive(v)
+	void *v;
+{
+	struct vop_inactive_args /* {
+		struct vnode *a_vp;
+		struct proc *a_p;
+	} */ *ap = v;
+
+	VOP_UNLOCK(ap->a_vp, 0);
+	return (0);
+}
+
 /*
  * This is a noop, simply returning what one has been given.
  */
@@ -381,32 +396,15 @@
 		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;
-	return (0);
-}
-
-/*
- * At the moment we do not do any locking.
- */
-/* ARGSUSED */
-int
-fifo_lock(v)
-	void *v;
-{
-	return (0);
-}
-
-/* ARGSUSED */
-int
-fifo_unlock(v)
-	void *v;
-{
-
+	if (ap->a_runp != NULL)
+		*ap->a_runp = 0;
 	return (0);
 }
 
--- a/sys/miscfs/genfs/genfs.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/genfs/genfs.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,11 +1,15 @@
-/*	$NetBSD: genfs.h,v 1.4 1998/01/05 19:20:10 perry Exp $	*/
+/*	$NetBSD: genfs.h,v 1.5 1998/03/01 02:22:03 fvdl Exp $	*/
 
 int	genfs_badop	__P((void *));
 int	genfs_nullop	__P((void *));
 int	genfs_eopnotsupp __P((void *));
 int	genfs_ebadf	__P((void *));
+int	genfs_nolock	__P((void *));
+int	genfs_noislocked __P((void *));
+int	genfs_nounlock	__P((void *));
 
 int	genfs_poll	__P((void *));
 int	genfs_fsync	__P((void *));
 int	genfs_seek	__P((void *));
 int	genfs_abortop	__P((void *));
+int	genfs_revoke	__P((void *));
--- a/sys/miscfs/genfs/genfs_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/genfs/genfs_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,42 @@
-/*	$NetBSD: genfs_vnops.c,v 1.5 1998/01/05 19:20:11 perry Exp $	*/
+/*	$NetBSD: genfs_vnops.c,v 1.6 1998/03/01 02:22:04 fvdl Exp $	*/
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
@@ -10,6 +45,7 @@
 #include <sys/poll.h>
 
 #include <miscfs/genfs/genfs.h>
+#include <miscfs/specfs/specdev.h>
 
 int
 genfs_poll(v)
@@ -108,3 +144,177 @@
 
 	return (EBADF);
 }
+
+
+/*
+ * Eliminate all activity associated with  the requested vnode
+ * and with all vnodes aliased to the requested vnode.
+ */
+int
+genfs_revoke(v)
+	void *v;
+{
+	struct vop_revoke_args /* {
+		struct vnode *a_vp;
+		int a_flags;
+	} */ *ap = v;
+	struct vnode *vp, *vq;
+	struct proc *p = curproc;	/* XXX */
+
+#ifdef DIAGNOSTIC
+	if ((ap->a_flags & REVOKEALL) == 0)
+		panic("genfs_revoke: not revokeall");
+#endif
+
+	vp = ap->a_vp;
+	simple_lock(&vp->v_interlock);
+
+	if (vp->v_flag & VALIASED) {
+		/*
+		 * If a vgone (or vclean) is already in progress,
+		 * wait until it is done and return.
+		 */
+		if (vp->v_flag & VXLOCK) {
+			vp->v_flag |= VXWANT;
+			simple_unlock(&vp->v_interlock);
+			tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
+			return (0);
+		}
+		/*
+		 * Ensure that vp will not be vgone'd while we
+		 * are eliminating its aliases.
+		 */
+		vp->v_flag |= VXLOCK;
+		simple_unlock(&vp->v_interlock);
+		while (vp->v_flag & VALIASED) {
+			simple_lock(&spechash_slock);
+			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
+				if (vq->v_rdev != vp->v_rdev ||
+				    vq->v_type != vp->v_type || vp == vq)
+					continue;
+				simple_unlock(&spechash_slock);
+				vgone(vq);
+				break;
+			}
+			if (vq == NULLVP)
+				simple_unlock(&spechash_slock);
+		}
+		/*
+		 * Remove the lock so that vgone below will
+		 * really eliminate the vnode after which time
+		 * vgone will awaken any sleepers.
+		 */
+		simple_lock(&vp->v_interlock);
+		vp->v_flag &= ~VXLOCK;
+	}
+	vgonel(vp, p);
+	return (0);
+}
+
+
+/*
+ * 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
+genfs_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));
+#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
+genfs_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));
+}
+
+/*
+ * Return whether or not the node is in use.
+ */
+int
+genfs_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));
+}
--- a/sys/miscfs/kernfs/kernfs.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/kernfs/kernfs.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kernfs.h,v 1.11 1997/05/10 22:04:13 pk Exp $	*/
+/*	$NetBSD: kernfs.h,v 1.12 1998/03/01 02:21:04 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kernfs.h	8.5 (Berkeley) 6/15/94
+ *	@(#)kernfs.h	8.6 (Berkeley) 3/29/95
  */
 
 #define	_PATH_KERNFS	"/kern"		/* Default mountpoint */
--- a/sys/miscfs/kernfs/kernfs_vfsops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/kernfs/kernfs_vfsops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: kernfs_vfsops.c,v 1.31 1998/02/18 07:05:48 thorpej Exp $	*/
+/*	$NetBSD: kernfs_vfsops.c,v 1.32 1998/03/01 02:21:04 fvdl Exp $	*/
 
 /*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kernfs_vfsops.c	8.5 (Berkeley) 6/15/94
+ *	@(#)kernfs_vfsops.c	8.10 (Berkeley) 5/14/95
  */
 
 /*
@@ -72,8 +72,9 @@
 int	kernfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
 			   struct vnode **, int *, struct ucred **));
 int	kernfs_vptofh __P((struct vnode *, struct fid *));
+int	kernfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+			   struct proc *));
 
-/*ARGSUSED*/
 void
 kernfs_init()
 {
@@ -142,7 +143,7 @@
 	fmp->kf_root = rvp;
 	mp->mnt_flag |= MNT_LOCAL;
 	mp->mnt_data = (qaddr_t)fmp;
-	getnewfsid(mp, makefstype(MOUNT_KERNFS));
+	vfs_getnewfsid(mp, MOUNT_KERNFS);
 
 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -174,19 +175,14 @@
 {
 	int error;
 	int flags = 0;
-	extern int doforce;
 	struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
 
 #ifdef KERNFS_DIAGNOSTIC
 	printf("kernfs_unmount(mp = %p)\n", mp);
 #endif
 
-	if (mntflags & MNT_FORCE) {
-		/* kernfs can never be rootfs so don't check for it */
-		if (!doforce)
-			return (EINVAL);
+	 if (mntflags & MNT_FORCE)
 		flags |= FORCECLOSE;
-	}
 
 	/*
 	 * Clear out buffer cache.  I don't think we
@@ -233,7 +229,7 @@
 	 */
 	vp = VFSTOKERNFS(mp)->kf_root;
 	VREF(vp);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	*vpp = vp;
 	return (0);
 }
@@ -261,11 +257,6 @@
 	printf("kernfs_statfs(mp = %p)\n", mp);
 #endif
 
-#ifdef COMPAT_09
-	sbp->f_type = 7;
-#else
-	sbp->f_type = 0;
-#endif
 	sbp->f_bsize = DEV_BSIZE;
 	sbp->f_iosize = DEV_BSIZE;
 	sbp->f_blocks = 2;		/* 1K to keep df happy */
@@ -273,6 +264,11 @@
 	sbp->f_bavail = 0;
 	sbp->f_files = 0;
 	sbp->f_ffree = 0;
+#ifdef COMPAT_09
+	sbp->f_type = 7;
+#else
+	sbp->f_type = 0;
+#endif
 	if (sbp != &mp->mnt_stat) {
 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
@@ -332,6 +328,19 @@
 	return (EOPNOTSUPP);
 }
 
+int
+kernfs_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;
+{
+	return (EOPNOTSUPP);
+}
+
 extern struct vnodeopv_desc kernfs_vnodeop_opv_desc;
 
 struct vnodeopv_desc *kernfs_vnodeopv_descs[] = {
@@ -352,6 +361,7 @@
 	kernfs_fhtovp,
 	kernfs_vptofh,
 	kernfs_init,
+	kernfs_sysctl,
 	NULL,				/* vfs_mountroot */
 	kernfs_vnodeopv_descs,
 };
--- a/sys/miscfs/kernfs/kernfs_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/kernfs/kernfs_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kernfs_vnops.c,v 1.56 1998/02/12 20:38:45 thorpej Exp $	*/
+/*	$NetBSD: kernfs_vnops.c,v 1.57 1998/03/01 02:21:04 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -35,7 +35,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)kernfs_vnops.c	8.9 (Berkeley) 6/15/94
+ *	@(#)kernfs_vnops.c	8.15 (Berkeley) 5/21/95
  */
 
 /*
@@ -119,6 +119,7 @@
 int	kernfs_write	__P((void *));
 #define	kernfs_ioctl	genfs_eopnotsupp
 #define	kernfs_poll	genfs_poll
+#define kernfs_revoke	genfs_revoke
 #define	kernfs_mmap	genfs_eopnotsupp
 #define	kernfs_fsync	genfs_nullop
 #define	kernfs_seek	genfs_nullop
@@ -133,12 +134,12 @@
 #define	kernfs_abortop	genfs_abortop
 int	kernfs_inactive	__P((void *));
 int	kernfs_reclaim	__P((void *));
-#define	kernfs_lock	genfs_nullop
-#define	kernfs_unlock	genfs_nullop
+#define	kernfs_lock	genfs_nolock
+#define	kernfs_unlock	genfs_nounlock
 #define	kernfs_bmap	genfs_badop
 #define	kernfs_strategy	genfs_badop
 int	kernfs_print	__P((void *));
-#define	kernfs_islocked	genfs_nullop
+#define	kernfs_islocked	genfs_noislocked
 int	kernfs_pathconf	__P((void *));
 #define	kernfs_advlock	genfs_eopnotsupp
 #define	kernfs_blkatoff	genfs_eopnotsupp
@@ -166,6 +167,7 @@
 	{ &vop_write_desc, kernfs_write },		/* write */
 	{ &vop_ioctl_desc, kernfs_ioctl },		/* ioctl */
 	{ &vop_poll_desc, kernfs_poll },		/* poll */
+	{ &vop_revoke_desc, kernfs_revoke },		/* revoke */
 	{ &vop_mmap_desc, kernfs_mmap },		/* mmap */
 	{ &vop_fsync_desc, kernfs_fsync },		/* fsync */
 	{ &vop_seek_desc, kernfs_seek },		/* seek */
@@ -346,10 +348,11 @@
 	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
 		return (EROFS);
 
+	VOP_UNLOCK(dvp, 0);
 	if (cnp->cn_namelen == 1 && *pname == '.') {
 		*vpp = dvp;
 		VREF(dvp);
-		/*VOP_LOCK(dvp);*/
+		vn_lock(dvp, LK_SHARED | LK_RETRY);
 		return (0);
 	}
 
@@ -357,7 +360,7 @@
 	if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
 		*vpp = rootdir;
 		VREF(rootdir);
-		VOP_LOCK(rootdir);
+		vn_lock(rootdir, LK_SHARED | LK_RETRY);
 		return (0);
 	}
 #endif
@@ -372,16 +375,19 @@
 	printf("kernfs_lookup: i = %d, failed", i);
 #endif
 
+	vn_lock(dvp, LK_SHARED | LK_RETRY);
 	return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
 
 found:
 	if (kt->kt_tag == KTT_DEVICE) {
 		dev_t *dp = kt->kt_data;
 	loop:
-		if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
+		if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
+			vn_lock(dvp, LK_SHARED | LK_RETRY);
 			return (ENOENT);
+		}
 		*vpp = fvp;
-		if (vget(fvp, 1))
+		if (vget(fvp, LK_EXCLUSIVE))
 			goto loop;
 		return (0);
 	}
@@ -390,13 +396,16 @@
 	printf("kernfs_lookup: allocate new vnode\n");
 #endif
 	error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
-	if (error)
+	if (error) {
+		vn_lock(dvp, LK_SHARED | LK_RETRY);
 		return (error);
+	}
 
 	MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP,
 	    M_WAITOK);
 	VTOKERN(fvp)->kf_kt = kt;
 	fvp->v_type = kt->kt_vtype;
+	vn_lock(fvp, LK_SHARED | LK_RETRY);
 	*vpp = fvp;
 
 #ifdef KERNFS_DIAGNOSTIC
@@ -479,7 +488,7 @@
 		vap->va_type = kt->kt_vtype;
 		vap->va_mode = kt->kt_mode;
 		vap->va_nlink = 1;
-		vap->va_fileid = 3 + (kt - kern_targets);
+		vap->va_fileid = 1 + (kt - kern_targets);
 		total = 0;
 		while (buf = strbuf,
 		       nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf)))
@@ -592,16 +601,16 @@
 		struct uio *a_uio;
 		struct ucred *a_cred;
 		int *a_eofflag;
-		off_t *a_cookies;
-		int a_ncookies;
+		off_t **a_cookies;
+		int a_*ncookies;
 	} */ *ap = v;
 	struct uio *uio = ap->a_uio;
 	struct dirent d;
 	struct kern_target *kt;
 	int i;
 	int error;
-	off_t *cookies = ap->a_cookies;
-	int ncookies = ap->a_ncookies;
+	off_t *cookies = NULL;
+	int ncookies = 0, nc = 0;
 
 	if (ap->a_vp->v_type != VDIR)
 		return (ENOTDIR);
@@ -616,6 +625,14 @@
 	bzero((caddr_t)&d, UIO_MX);
 	d.d_reclen = UIO_MX;
 
+	if (ap->a_ncookies) {
+		nc = uio->uio_resid / UIO_MX;
+		nc = min(nc, (nkern_targets - i));
+		MALLOC(cookies, off_t *, nc * sizeof(off_t), M_TEMP,
+		    M_WAITOK);
+		*ap->a_cookies = cookies;
+	}
+
 	for (kt = &kern_targets[i];
 	     uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
 #ifdef KERNFS_DIAGNOSTIC
@@ -637,8 +654,19 @@
 
 		if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0)
 			break;
-		if (ncookies-- > 0)
+		if (cookies) {
 			*cookies++ = i + 1;
+			ncookies++;
+		}
+	}
+
+	if (ap->a_ncookies) {
+		if (error) {
+			FREE(*ap->a_cookies, M_TEMP);
+			*ap->a_ncookies = 0;
+			*ap->a_cookies = NULL;
+		} else
+			*ap->a_ncookies = ncookies;
 	}
 
 	uio->uio_offset = i;
@@ -651,6 +679,7 @@
 {
 	struct vop_inactive_args /* {
 		struct vnode *a_vp;
+		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 
@@ -661,6 +690,7 @@
 	 * Clear out the v_type field to avoid
 	 * nasty things happening in vgone().
 	 */
+	VOP_UNLOCK(vp, 0);
 	vp->v_type = VNON;
 	return (0);
 }
--- a/sys/miscfs/nullfs/null_subr.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/nullfs/null_subr.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: null_subr.c,v 1.10 1998/02/07 02:44:51 chs Exp $	*/
+/*	$NetBSD: null_subr.c,v 1.11 1998/03/01 02:21:43 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -36,11 +36,12 @@
  * SUCH DAMAGE.
  *
  *	from: Id: lofs_subr.c,v 1.11 1992/05/30 10:05:43 jsp Exp
- *	@(#)null_subr.c	8.4 (Berkeley) 1/21/94
+ *	@(#)null_subr.c	8.7 (Berkeley) 5/14/95
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/proc.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/vnode.h>
@@ -205,7 +206,8 @@
 				vgone(cvp);
 				goto loop;
 			}
-			if (vget(cvp, 0))	/* can't lock; will die! */
+			if (vget(cvp, LK_EXCLUSIVE))
+				/* can't lock; will die! */
 				goto loop;
 			break;
 		}
@@ -285,6 +287,7 @@
 	if (lowervp->v_usecount < 1) {
 		/* Should never happen... */
 		vprint("null_node_create: alias", aliasvp);
+		vprint("null_node_create: lower", lowervp);
 		panic("null_node_create: lower has 0 usecount.");
 	};
 #endif
@@ -296,7 +299,7 @@
 	   upper layer lock */
 	VTONULL(aliasvp)->null_flags |= NULL_LLOCK;
 	if (takelock)
-		VOP_LOCK(aliasvp);
+		vn_lock(aliasvp, LK_EXCLUSIVE | LK_RETRY);
 
 	*newvpp = aliasvp;
 	return (0);
--- a/sys/miscfs/nullfs/null_vfsops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/nullfs/null_vfsops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: null_vfsops.c,v 1.18 1998/02/18 07:05:48 thorpej Exp $	*/
+/*	$NetBSD: null_vfsops.c,v 1.19 1998/03/01 02:21:43 fvdl Exp $	*/
 
 /*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
@@ -37,7 +37,7 @@
  *
  *	from: Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp
  *	from: @(#)lofs_vfsops.c	1.2 (Berkeley) 6/18/92
- *	@(#)null_vfsops.c	8.2 (Berkeley) 1/21/94
+ *	@(#)null_vfsops.c	8.7 (Berkeley) 5/14/95
  */
 
 /*
@@ -48,6 +48,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/time.h>
+#include <sys/proc.h>
 #include <sys/types.h>
 #include <sys/vnode.h>
 #include <sys/mount.h>
@@ -68,6 +69,8 @@
 int	nullfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
 			   struct vnode **, int *, struct ucred **));
 int	nullfs_vptofh __P((struct vnode *, struct fid *));
+int	nullfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+			   struct proc *));
 /*
  * Mount null layer
  */
@@ -137,7 +140,7 @@
 	/*
 	 * Unlock the node (either the lower or the alias)
 	 */
-	VOP_UNLOCK(vp);
+	VOP_UNLOCK(vp, 0);
 	/*
 	 * Make sure the node alias worked
 	 */
@@ -157,7 +160,7 @@
 	if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
 		mp->mnt_flag |= MNT_LOCAL;
 	mp->mnt_data = (qaddr_t) xmp;
-	getnewfsid(mp, makefstype(MOUNT_NULL));
+	vfs_getnewfsid(mp, MOUNT_NULL);
 
 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -199,18 +202,13 @@
 	struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
 	int error;
 	int flags = 0;
-	extern int doforce;
 
 #ifdef NULLFS_DIAGNOSTIC
 	printf("nullfs_unmount(mp = %p)\n", mp);
 #endif
 
-	if (mntflags & MNT_FORCE) {
-		/* lofs can never be rootfs so don't check for it */
-		if (!doforce)
-			return (EINVAL);
+	if (mntflags & MNT_FORCE)
 		flags |= FORCECLOSE;
-	}
 
 	/*
 	 * Clear out buffer cache.  I don't think we
@@ -264,7 +262,7 @@
 	 */
 	vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
 	VREF(vp);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	*vpp = vp;
 	return 0;
 }
@@ -367,10 +365,23 @@
 	return (EOPNOTSUPP);
 }
 
-extern struct vnodeopv_desc nullfs_vnodeop_opv_desc;
+int
+nullfs_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;
+{
+	return (EOPNOTSUPP);
+}
+
+extern struct vnodeopv_desc null_vnodeop_opv_desc;
 
 struct vnodeopv_desc *nullfs_vnodeopv_descs[] = {
-	&nullfs_vnodeop_opv_desc,
+	&null_vnodeop_opv_desc,
 	NULL,
 };
 
@@ -387,6 +398,7 @@
 	nullfs_fhtovp,
 	nullfs_vptofh,
 	nullfs_init,
+	nullfs_sysctl,
 	NULL,				/* vfs_mountroot */
 	nullfs_vnodeopv_descs,
 };
--- a/sys/miscfs/nullfs/null_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/nullfs/null_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: null_vnops.c,v 1.12 1997/10/06 09:32:33 thorpej Exp $	*/
+/*	$NetBSD: null_vnops.c,v 1.13 1998/03/01 02:21:43 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -35,11 +35,11 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)null_vnops.c	8.1 (Berkeley) 6/10/93
+ *	@(#)null_vnops.c	8.6 (Berkeley) 5/27/95
  *
  * Ancestors:
  *	@(#)lofs_vnops.c	1.2 (Berkeley) 6/18/92
- *	Id: lofs_vnops.c,v 1.11 1992/05/30 10:05:43 jsp Exp
+ *	$Id: null_vnops.c,v 1.13 1998/03/01 02:21:43 fvdl Exp $
  *	...and...
  *	@(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
  */
@@ -94,13 +94,21 @@
  * in the arguments and, if a vnode is return by the operation,
  * stacks a null-node on top of the returned vnode.
  *
- * Although bypass handles most operations, 
- * vop_getattr, _inactive, _reclaim, and _print are not bypassed.
- * Vop_getattr must change the fsid being returned.
+ * Although bypass handles most operations, vop_getattr, vop_lock,
+ * vop_unlock, vop_inactive, vop_reclaim, and vop_print are not
+ * bypassed. Vop_getattr must change the fsid being returned.
+ * Vop_lock and vop_unlock must handle any locking for the
+ * current vnode as well as pass the lock request down.
  * Vop_inactive and vop_reclaim are not bypassed so that
- * they can handle freeing null-layer specific data.
- * Vop_print is not bypassed to avoid excessive debugging
- * information.
+ * they can handle freeing null-layer specific data. Vop_print
+ * is not bypassed to avoid excessive debugging information.
+ * 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.
  *
  *
  * INSTANTIATING VNODE STACKS
@@ -177,6 +185,7 @@
 #include <sys/malloc.h>
 #include <sys/buf.h>
 #include <miscfs/nullfs/null.h>
+#include <miscfs/genfs/genfs.h>
 
 
 int null_bug_bypass = 0;   /* for debugging: enables bypass printf'ing */
@@ -192,6 +201,9 @@
 int	null_unlock __P((void *));
 int	null_islocked __P((void *));
 int	null_lookup __P((void *));
+int	null_setattr __P((void *));
+int	null_access __P((void *));
+
 
 /*
  * This is the 10-Apr-92 bypass routine.
@@ -226,6 +238,7 @@
 		struct vnodeop_desc *a_desc;
 		<other random data follows, presumably>
 	} */ *ap = v;
+	extern int (**null_vnodeop_p) __P((void *)); 
 	register struct vnode **this_vp_p;
 	int error;
 	struct vnode *old_vps[VDESC_MAX_VPS];
@@ -262,9 +275,9 @@
 		 * are of our type.  Check for and don't map any
 		 * that aren't.  (We must always map first vp or vclean fails.)
 		 */
-		if (i && (*this_vp_p == NULLVP ||
+		if (i && (*this_vp_p == NULL ||
 		    (*this_vp_p)->v_op != null_vnodeop_p)) {
-			old_vps[i] = NULLVP;
+			old_vps[i] = NULL;
 		} else {
 			old_vps[i] = *this_vp_p;
 			*(vps_p[i]) = NULLVPTOLOWERVP(*this_vp_p);
@@ -294,21 +307,10 @@
 	for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
 		if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
 			break;   /* bail out at end of list */
-		if (old_vps[i] != NULLVP) {
+		if (old_vps[i]) {
 			*(vps_p[i]) = old_vps[i];
-			if (reles & 1) {
-				/* they really vput them, so we must drop
-				   our locks (but mark underneath as
-				   unlocked first).
-				   Beware of vnode duplication--put it once,
-				   and rele the rest.  Check this 
-				   by looking at our upper flag. */
-			    if (VTONULL(*(vps_p[i]))->null_flags & NULL_LOCKED) {
-				    VTONULL(*(vps_p[i]))->null_flags &= ~NULL_LLOCK;
-				    vput(*(vps_p[i]));
-			    } else
-				    vrele(*(vps_p[i]));
-			}
+			if (reles & 1)
+				vrele(*(vps_p[i]));
 		}
 	}
 
@@ -330,15 +332,6 @@
 			goto out;
 		vppp = VOPARG_OFFSETTO(struct vnode***,
 				 descp->vdesc_vpp_offset,ap);
-		/*
-		 * This assumes that **vppp is a locked vnode (it is always
-		 * so as of this writing, NetBSD-current 1995/02/16)
-		 */
-		/*
-		 * (don't want to lock it if being called on behalf
-		 * of lookup--it plays weird locking games depending
-		 * on whether or not it's looking up ".", "..", etc.
-		 */
 		error = null_node_create(old_vps[0]->v_mount, **vppp, *vppp,
 					 descp == &vop_lookup_desc ? 0 : 1);
 	}
@@ -347,6 +340,104 @@
 	return (error);
 }
 
+/*
+ * We have to carry on the locking protocol on the null layer vnodes
+ * as we progress through the tree. We also have to enforce read-only
+ * if this layer is mounted read-only.
+ */
+int
+null_lookup(v)
+	void *v;
+{
+	struct vop_lookup_args /* {
+		struct vnode * a_dvp;
+		struct vnode ** a_vpp;
+		struct componentname * a_cnp;
+	} */ *ap = v;
+	struct componentname *cnp = ap->a_cnp;
+	int flags = cnp->cn_flags;
+	struct vop_lock_args lockargs;
+	struct vop_unlock_args unlockargs;
+	struct vnode *dvp, *vp;
+	int error;
+
+	if ((flags & ISLASTCN) && (ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+		return (EROFS);
+	error = null_bypass(ap);
+	if (error == EJUSTRETURN && (flags & ISLASTCN) &&
+	    (ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+	    (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
+		error = EROFS;
+	/*
+	 * We must do the same locking and unlocking at this layer as 
+	 * is done in the layers below us. We could figure this out 
+	 * based on the error return and the LASTCN, LOCKPARENT, and
+	 * LOCKLEAF flags. However, it is more expidient to just find 
+	 * out the state of the lower level vnodes and set ours to the
+	 * same state.
+	 */
+	dvp = ap->a_dvp;
+	vp = *ap->a_vpp;
+	if (dvp == vp)
+		return (error);
+	if (!VOP_ISLOCKED(dvp)) {
+		unlockargs.a_vp = dvp;
+		unlockargs.a_flags = 0;
+		genfs_nounlock(&unlockargs);
+	}
+	if (vp != NULL && VOP_ISLOCKED(vp)) {
+		lockargs.a_vp = vp;
+		lockargs.a_flags = LK_SHARED;
+		genfs_nolock(&lockargs);
+	}
+	return (error);
+}
+
+/*
+ * Setattr call. Disallow write attempts if the layer is mounted read-only.
+ */
+int
+null_setattr(v)
+	void *v;
+{
+	struct vop_setattr_args /* {
+		struct vnodeop_desc *a_desc;
+		struct vnode *a_vp;
+		struct vattr *a_vap;
+		struct ucred *a_cred;
+		struct proc *a_p;
+	} */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	struct vattr *vap = ap->a_vap;
+
+  	if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
+	    vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
+	    vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
+	    (vp->v_mount->mnt_flag & MNT_RDONLY))
+		return (EROFS);
+	if (vap->va_size != VNOVAL) {
+ 		switch (vp->v_type) {
+ 		case VDIR:
+ 			return (EISDIR);
+ 		case VCHR:
+ 		case VBLK:
+ 		case VSOCK:
+ 		case VFIFO:
+			return (0);
+		case VREG:
+		case VLNK:
+ 		default:
+			/*
+			 * Disallow write attempts if the filesystem is
+			 * mounted read-only.
+			 */
+			if (vp->v_mount->mnt_flag & MNT_RDONLY)
+				return (EROFS);
+		}
+	}
+	return (null_bypass(ap));
+}
 
 /*
  *  We handle getattr only to change the fsid.
@@ -362,6 +453,7 @@
 		struct proc *a_p;
 	} */ *ap = v;
 	int error;
+
 	if ((error = null_bypass(ap)) != 0)
 		return (error);
 	/* Requires that arguments be restored. */
@@ -369,11 +461,90 @@
 	return (0);
 }
 
+int
+null_access(v)
+	void *v;
+{
+	struct vop_access_args /* {
+		struct vnode *a_vp;
+		int  a_mode;
+		struct ucred *a_cred;
+		struct proc *a_p;
+	} */ *ap = v;
+	struct vnode *vp = ap->a_vp;
+	mode_t mode = ap->a_mode;
+
+	/*
+	 * Disallow write attempts on read-only layers;
+	 * unless the file is a socket, fifo, or a block or
+	 * character device resident on the file system.
+	 */
+	if (mode & VWRITE) {
+		switch (vp->v_type) {
+		case VDIR:
+		case VLNK:
+		case VREG:
+			if (vp->v_mount->mnt_flag & MNT_RDONLY)
+				return (EROFS);
+			break;
+		default:
+			break;
+		}
+	}
+	return (null_bypass(ap));
+}
+
+/*
+ * We need to process our own vnode lock and then clear the
+ * interlock flag as it applies only to our vnode, not the
+ * vnodes below us on the stack.
+ */
+int
+null_lock(v)
+	void *v;
+{
+	struct vop_lock_args /* {
+		struct vnode *a_vp;
+		int a_flags;
+		struct proc *a_p;
+	} */ *ap = v;
+
+	genfs_nolock(ap);
+	if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
+		return (0);
+	ap->a_flags &= ~LK_INTERLOCK;
+	return (null_bypass(ap));
+}
+
+/*
+ * We need to process our own vnode unlock and then clear the
+ * interlock flag as it applies only to our vnode, not the
+ * vnodes below us on the stack.
+ */
+int
+null_unlock(v)
+	void *v;
+{
+	struct vop_unlock_args /* {
+		struct vnode *a_vp;
+		int a_flags;
+		struct proc *a_p;
+	} */ *ap = v;
+
+	genfs_nounlock(ap);
+	ap->a_flags &= ~LK_INTERLOCK;
+	return (null_bypass(ap));
+}
 
 int
 null_inactive(v)
 	void *v;
 {
+	struct vop_inactive_args /* {
+		struct vnode *a_vp;
+		struct proc *a_p;
+	} */ *ap = v;
+
 	/*
 	 * Do nothing (and _don't_ bypass).
 	 * Wait to vrele lowervp until reclaim,
@@ -386,6 +557,7 @@
 	 * like they do in the name lookup cache code.
 	 * That's too much work for now.
 	 */
+	VOP_UNLOCK(ap->a_vp, 0);
 	return (0);
 }
 
@@ -395,6 +567,7 @@
 {
 	struct vop_reclaim_args /* {
 		struct vnode *a_vp;
+		struct proc *a_p;
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 	struct null_node *xp = VTONULL(vp);
@@ -413,7 +586,6 @@
 	return (0);
 }
 
-
 int
 null_print(v)
 	void *v;
@@ -422,24 +594,10 @@
 		struct vnode *a_vp;
 	} */ *ap = v;
 	register struct vnode *vp = ap->a_vp;
-	register struct null_node *nn = VTONULL(vp);
-
 	printf ("\ttag VT_NULLFS, vp=%p, lowervp=%p\n", vp, NULLVPTOLOWERVP(vp));
-#ifdef DIAGNOSTIC
-	printf("%s%s owner pid %d retpc %p retret %p\n",
-	    (nn->null_flags & NULL_LOCKED) ? "(LOCKED) " : "",
-	    (nn->null_flags & NULL_LLOCK) ? "(LLOCK) " : "",
-	    nn->null_pid, nn->null_lockpc, nn->null_lockpc2);
-#else
-	printf("%s%s\n",
-	    (nn->null_flags & NULL_LOCKED) ? "(LOCKED) " : "",
-	    (nn->null_flags & NULL_LLOCK) ? "(LLOCK) " : "");
-#endif
-	vprint("nullfs lowervp", NULLVPTOLOWERVP(vp));
 	return (0);
 }
 
-
 /*
  * XXX - vop_strategy must be hand coded because it has no
  * vnode in its arguments.
@@ -466,7 +624,6 @@
 	return (error);
 }
 
-
 /*
  * XXX - like vop_strategy, vop_bwrite must be hand coded because it has no
  * vnode in its arguments.
@@ -494,276 +651,26 @@
 }
 
 /*
- * We need a separate null lock routine, to avoid deadlocks at reclaim time.
- * If a process holds the lower-vnode locked when it tries to reclaim
- * the null upper-vnode, _and_ null_bypass is used as the locking operation,
- * then a process can end up locking against itself.
- * This has been observed when a null mount is set up to "tunnel" beneath a
- * union mount (that setup is useful if you still wish to be able to access
- * the non-union version of either the above or below union layer)
- */
-int
-null_lock(v)
-	void *v;
-{
-	struct vop_lock_args *ap = v;
-	struct vnode *vp = ap->a_vp;
-	struct null_node *nn;
-
-#ifdef NULLFS_DIAGNOSTIC
-	vprint("null_lock_e", ap->a_vp);
-	printf("retpc=%p, retretpc=%p\n", RETURN_PC(0), RETURN_PC(1));
-#endif
-start:
-	while (vp->v_flag & VXLOCK) {
-		vp->v_flag |= VXWANT;
-		tsleep((caddr_t)vp, PINOD, "nulllock1", 0);
-	}
-
-	nn = VTONULL(vp);
-
-	if ((nn->null_flags & NULL_LLOCK) == 0 &&
-	    (vp->v_usecount != 0)) {
-		/*
-		 * only lock underlying node if we haven't locked it yet
-		 * for null ops, and our refcount is nonzero.  If usecount
-		 * is zero, we are probably being reclaimed so we need to
-		 * keep our hands off the lower node.
-		 */
-		VOP_LOCK(nn->null_lowervp);
-		nn->null_flags |= NULL_LLOCK;
-	}
-
-	if (nn->null_flags & NULL_LOCKED) {
-#ifdef DIAGNOSTIC
-		if (curproc && nn->null_pid == curproc->p_pid &&
-		    nn->null_pid > -1 && curproc->p_pid > -1) {
-			vprint("self-lock", vp);
-			panic("null: locking against myself");
-		}
-#endif
-		nn->null_flags |= NULL_WANTED;
-		tsleep((caddr_t)nn, PINOD, "nulllock2", 0);
-		goto start;
-	}
-
-#ifdef DIAGNOSTIC
-	if (curproc)
-		nn->null_pid = curproc->p_pid;
-	else
-		nn->null_pid = -1;
-	nn->null_lockpc = RETURN_PC(0);
-	nn->null_lockpc2 = RETURN_PC(1);
-#endif
-
-	nn->null_flags |= NULL_LOCKED;
-	return (0);
-}
-
-int
-null_unlock(v)
-	void *v;
-{
-	struct vop_lock_args *ap = v;
-	struct null_node *nn = VTONULL(ap->a_vp);
-
-#ifdef NULLFS_DIAGNOSTIC
-	vprint("null_unlock_e", ap->a_vp);
-#endif
-#ifdef DIAGNOSTIC
-	if ((nn->null_flags & NULL_LOCKED) == 0) {
-		vprint("null_unlock", ap->a_vp);
-		panic("null: unlocking unlocked node");
-	}
-	if (curproc && nn->null_pid != curproc->p_pid &&
-	    curproc->p_pid > -1 && nn->null_pid > -1) {
-		vprint("null_unlock", ap->a_vp);
-		panic("null: unlocking other process's null node");
-	}
-#endif
-	nn->null_flags &= ~NULL_LOCKED;
-
-	if ((nn->null_flags & NULL_LLOCK) != 0)
-		VOP_UNLOCK(nn->null_lowervp);
-
-	nn->null_flags &= ~NULL_LLOCK;
-    
-	if (nn->null_flags & NULL_WANTED) {
-		nn->null_flags &= ~NULL_WANTED;
-		wakeup((caddr_t)nn);
-	}
-#ifdef DIAGNOSTIC
-	nn->null_pid = 0;
-	nn->null_lockpc = nn->null_lockpc2 = 0;
-#endif
-	return (0);
-}
-
-int
-null_islocked(v)
-	void *v;
-{
-	struct vop_islocked_args *ap = v;
-	return ((VTONULL(ap->a_vp)->null_flags & NULL_LOCKED) ? 1 : 0);
-}
-
-int
-null_lookup(v)
-	void *v;
-{
-	register struct vop_lookup_args /* {
-		struct vnodeop_desc *a_desc;
-		struct vnode *a_dvp;
-		struct vnode **a_vpp;
-		struct componentname *a_cnp;
-	} */ *ap = v;
-	register int error;
-	register struct vnode *dvp;
-	int flags = ap->a_cnp->cn_flags;
-
-#ifdef NULLFS_DIAGNOSTIC
-	printf("null_lookup: dvp=%p, name='%s'\n",
-	    ap->a_dvp, ap->a_cnp->cn_nameptr);
-#endif
-	/*
-	 * the starting dir (ap->a_dvp) comes in locked.
-	 */
-
-	/* set LOCKPARENT to hold on to it until done below */
-	ap->a_cnp->cn_flags |= LOCKPARENT;
-	error = null_bypass(ap);
-	if (!(flags & LOCKPARENT))
-		ap->a_cnp->cn_flags &= ~LOCKPARENT;
-
-	if (error)
-		/*
-		 * starting dir is still locked/has been relocked
-		 * on error return.
-		 */
-		return error;
-
-	if (ap->a_dvp != *ap->a_vpp) {
-		/*
-		 * Lookup returns node locked; we mark both lower and
-		 * upper nodes as locked by setting the lower lock
-		 * flag (it came back locked), and then call lock to
-		 * set upper lock flag & record pid, etc.  see
-		 * null_node_create()
-		 */
-		VTONULL(*ap->a_vpp)->null_flags |= NULL_LLOCK;
-
-		dvp = ap->a_dvp;
-		if (flags & ISDOTDOT) {
-			/*
-			 * If we're looking up `..' and this isn't the
-			 * last component, then the starting directory
-			 * ("parent") is _unlocked_ as a side-effect
-			 * of lookups.  This is to avoid deadlocks:
-			 * lock order is always parent, child, so
-			 * looking up `..'  requires dropping the lock
-			 * on the starting directory.
-			 */
-			/* see ufs_lookup() for hairy ugly locking protocol
-			   examples */
-			/*
-			 * underlying starting dir comes back locked if flags &
-			 * LOCKPARENT (which we artificially set above) and
-			 * ISLASTCN.
-			 */
-			if (flags & ISLASTCN) {
-				VTONULL(dvp)->null_flags |= NULL_LLOCK;	/* no-op, right? */
-#ifdef NULLFS_DIAGNOSTIC
-				if (!VOP_ISLOCKED(VTONULL(dvp)->null_lowervp)) {
-					vprint("lowerdvp not locked after lookup\n", dvp);
-					panic("null_lookup not locked");
-				}
-#endif
-			} else {
-				VTONULL(dvp)->null_flags &= ~NULL_LLOCK;
-#ifdef NULLFS_DIAGNOSTIC
-				if (VOP_ISLOCKED(VTONULL(dvp)->null_lowervp)) {
-					vprint("lowerdvp locked after lookup?\n", dvp);
-					panic("null_lookup locked");
-				}
-#endif
-			}
-			/*
-			 * locking order: drop lock on lower-in-tree
-			 * element, then get lock on higher-in-tree
-			 * element, then (if needed) re-fetch lower
-			 * lock.  No need for vget() since we hold a
-			 * refcount to the starting directory
-			 */
-			VOP_UNLOCK(dvp);
-			VOP_LOCK(*ap->a_vpp);
-			/*
-			 * we should return our directory locked if
-			 * (flags & LOCKPARENT) and (flags & ISLASTCN)
-			 */
-			if ((flags & LOCKPARENT) && (flags & ISLASTCN))
-				VOP_LOCK(dvp);
-		} else {
-			/*
-			 * Normal directory locking order: we hold the starting
-			 * directory locked; now lock our layer of the target.
-			 */
-			VOP_LOCK(*ap->a_vpp);
-			/*
-			 * underlying starting dir comes back locked
-			 * if lockparent (we set it) and no error
-			 * (this leg) and ISLASTCN
-			 */
-			if (flags & ISLASTCN) {
-				VTONULL(dvp)->null_flags |= NULL_LLOCK;	/* no op, right? */
-#ifdef NULLFS_DIAGNOSTIC
-				if (!VOP_ISLOCKED(VTONULL(dvp)->null_lowervp)) {
-					vprint("lowerdvp not locked after lookup\n", dvp);
-					panic("null_lookup not locked");
-				}
-#endif
-			} else {
-				VTONULL(dvp)->null_flags &= ~NULL_LLOCK;
-#ifdef NULLFS_DIAGNOSTIC
-				if (VOP_ISLOCKED(VTONULL(dvp)->null_lowervp)) {
-					vprint("lowerdvp locked after lookup?\n", dvp);
-					panic("null_lookup locked");
-				}
-#endif
-			}
-			/*
-			 * we should return our directory unlocked if
-			 * our caller didn't want the parent locked,
-			 * !(flags & LOCKPARENT), or we're not at the
-			 * end yet, !(flags & ISLASTCN)
-			 */
-			if (!(flags & LOCKPARENT) || !(flags & ISLASTCN))
-				VOP_UNLOCK(dvp);
-		}
-	}
-	return error;
-}
-
-/*
  * Global vfs data structures
  */
 int (**null_vnodeop_p) __P((void *));
 struct vnodeopv_entry_desc null_vnodeop_entries[] = {
-	{ &vop_default_desc,	null_bypass },
-
-	{ &vop_getattr_desc,	null_getattr },
-	{ &vop_inactive_desc,	null_inactive },
-	{ &vop_reclaim_desc,	null_reclaim },
-	{ &vop_print_desc,	null_print },
+	{ &vop_default_desc, null_bypass },
 
-	{ &vop_lock_desc,	null_lock },
-	{ &vop_unlock_desc,	null_unlock },
-	{ &vop_islocked_desc,	null_islocked },
-	{ &vop_lookup_desc,	null_lookup }, /* special locking frob */
+	{ &vop_lookup_desc,   null_lookup },
+	{ &vop_setattr_desc,  null_setattr },
+	{ &vop_getattr_desc,  null_getattr },
+	{ &vop_access_desc,   null_access },
+	{ &vop_lock_desc,     null_lock },
+	{ &vop_unlock_desc,   null_unlock },
+	{ &vop_inactive_desc, null_inactive },
+	{ &vop_reclaim_desc,  null_reclaim },
+	{ &vop_print_desc,    null_print },
 
-	{ &vop_strategy_desc,	null_strategy },
-	{ &vop_bwrite_desc,	null_bwrite },
+	{ &vop_strategy_desc, null_strategy },
+	{ &vop_bwrite_desc,   null_bwrite },
 
-	{ (struct vnodeop_desc*)NULL,	(int(*) __P((void *)))NULL }
+	{ (struct vnodeop_desc*)NULL, (int(*)__P((void *)))NULL }
 };
-struct vnodeopv_desc nullfs_vnodeop_opv_desc =
+struct vnodeopv_desc null_vnodeop_opv_desc =
 	{ &null_vnodeop_p, null_vnodeop_entries };
--- a/sys/miscfs/portal/portal_vfsops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/portal/portal_vfsops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: portal_vfsops.c,v 1.16 1998/02/18 07:05:48 thorpej Exp $	*/
+/*	$NetBSD: portal_vfsops.c,v 1.17 1998/03/01 02:21:38 fvdl Exp $	*/
 
 /*
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1995
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  *	from: Id: portal_vfsops.c,v 1.5 1992/05/30 10:25:27 jsp Exp
- *	@(#)portal_vfsops.c	8.6 (Berkeley) 1/21/94
+ *	@(#)portal_vfsops.c	8.11 (Berkeley) 5/14/95
  */
 
 /*
@@ -76,6 +76,8 @@
 int	portal_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
 			   struct vnode **, int *, struct ucred **));
 int	portal_vptofh __P((struct vnode *, struct fid *));
+int	portal_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+			   struct proc *));
 
 void
 portal_init()
@@ -135,7 +137,7 @@
 
 	mp->mnt_flag |= MNT_LOCAL;
 	mp->mnt_data = (qaddr_t)fmp;
-	getnewfsid(mp, makefstype(MOUNT_PORTAL));
+	vfs_getnewfsid(mp, MOUNT_PORTAL);
 
 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -161,16 +163,11 @@
 	int mntflags;
 	struct proc *p;
 {
-	extern int doforce;
 	struct vnode *rootvp = VFSTOPORTAL(mp)->pm_root;
 	int error, flags = 0;
 
-	if (mntflags & MNT_FORCE) {
-		/* portal can never be rootfs so don't check for it */
-		if (!doforce)
-			return (EINVAL);
+	if (mntflags & MNT_FORCE)
 		flags |= FORCECLOSE;
-	}
 
 	/*
 	 * Clear out buffer cache.  I don't think we
@@ -226,7 +223,7 @@
 	 */
 	vp = VFSTOPORTAL(mp)->pm_root;
 	VREF(vp);
-	VOP_LOCK(vp);
+	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	*vpp = vp;
 	return (0);
 }
@@ -250,11 +247,6 @@
 	struct proc *p;
 {
 
-#ifdef COMPAT_09
-	sbp->f_type = 12;
-#else
-	sbp->f_type = 0;
-#endif
 	sbp->f_bsize = DEV_BSIZE;
 	sbp->f_iosize = DEV_BSIZE;
 	sbp->f_blocks = 2;		/* 1K to keep df happy */
@@ -262,6 +254,11 @@
 	sbp->f_bavail = 0;
 	sbp->f_files = 1;		/* Allow for "." */
 	sbp->f_ffree = 0;		/* See comments above */
+#ifdef COMPAT_09
+	sbp->f_type = 12;
+#else
+	sbp->f_type = 0;
+#endif
 	if (sbp != &mp->mnt_stat) {
 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
@@ -315,6 +312,19 @@
 	return (EOPNOTSUPP);
 }
 
+int
+portal_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;
+{
+	return (EOPNOTSUPP);
+}
+
 extern struct vnodeopv_desc portal_vnodeop_opv_desc;
 
 struct vnodeopv_desc *portal_vnodeopv_descs[] = {
@@ -335,6 +345,7 @@
 	portal_fhtovp,
 	portal_vptofh,
 	portal_init,
+	portal_sysctl,
 	NULL,				/* vfs_mountroot */
 	portal_vnodeopv_descs,
 };
--- a/sys/miscfs/portal/portal_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/portal/portal_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: portal_vnops.c,v 1.27 1997/11/27 20:36:05 fvdl Exp $	*/
+/*	$NetBSD: portal_vnops.c,v 1.28 1998/03/01 02:21:39 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  *	from: Id: portal_vnops.c,v 1.4 1992/05/30 10:05:24 jsp Exp
- *	@(#)portal_vnops.c	8.8 (Berkeley) 1/21/94
+ *	@(#)portal_vnops.c	8.14 (Berkeley) 5/21/95
  */
 
 /*
@@ -84,6 +84,7 @@
 #define	portal_ioctl	genfs_eopnotsupp
 #define	portal_poll	genfs_eopnotsupp
 #define	portal_mmap	genfs_eopnotsupp
+#define portal_revoke	genfs_revoke
 #define	portal_fsync	genfs_nullop
 #define	portal_seek	genfs_seek
 #define	portal_remove	genfs_eopnotsupp
@@ -97,12 +98,12 @@
 #define	portal_abortop	genfs_abortop
 int	portal_inactive	__P((void *));
 int	portal_reclaim	__P((void *));
-#define	portal_lock	genfs_nullop
-#define	portal_unlock	genfs_nullop
+#define	portal_lock	genfs_nolock
+#define	portal_unlock	genfs_nounlock
 #define	portal_bmap	genfs_badop
 #define	portal_strategy	genfs_badop
 int	portal_print	__P((void *));
-#define	portal_islocked	genfs_nullop
+#define	portal_islocked	genfs_noislocked
 int	portal_pathconf	__P((void *));
 #define	portal_advlock	genfs_badop
 #define	portal_blkatoff	genfs_badop
@@ -127,6 +128,7 @@
 	{ &vop_write_desc, portal_write },		/* write */
 	{ &vop_ioctl_desc, portal_ioctl },		/* ioctl */
 	{ &vop_poll_desc, portal_poll },		/* poll */
+	{ &vop_revoke_desc, portal_revoke },		/* revoke */
 	{ &vop_mmap_desc, portal_mmap },		/* mmap */
 	{ &vop_fsync_desc, portal_fsync },		/* fsync */
 	{ &vop_seek_desc, portal_seek },		/* seek */
@@ -607,7 +609,12 @@
 portal_inactive(v)
 	void *v;
 {
+	struct vop_inactive_args /* {
+		struct vnode *a_vp;
+		struct proc *a_p;
+	} */ *ap = v;
 
+	VOP_UNLOCK(ap->a_vp, 0);
 	return (0);
 }
 
--- a/sys/miscfs/procfs/procfs.h	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/procfs/procfs.h	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs.h,v 1.20 1997/08/27 08:52:51 thorpej Exp $	*/
+/*	$NetBSD: procfs.h,v 1.21 1998/03/01 02:21:16 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1993 Jan-Simon Pendry
@@ -36,7 +36,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)procfs.h	8.7 (Berkeley) 6/15/94
+ *	@(#)procfs.h	8.9 (Berkeley) 5/14/95
  */
 
 /*
@@ -128,7 +128,6 @@
 extern int (**procfs_vnodeop_p) __P((void *));
 extern struct vfsops procfs_vfsops;
 
-void	procfs_init __P((void));
 int	procfs_root __P((struct mount *, struct vnode **));
 
 #endif /* _KERNEL */
--- a/sys/miscfs/procfs/procfs_subr.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/procfs/procfs_subr.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_subr.c,v 1.22 1997/10/30 09:14:07 mycroft Exp $	*/
+/*	$NetBSD: procfs_subr.c,v 1.23 1998/03/01 02:21:16 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)procfs_subr.c	8.5 (Berkeley) 6/15/94
+ *	@(#)procfs_subr.c	8.6 (Berkeley) 5/14/95
  */
 
 #include <sys/param.h>
--- a/sys/miscfs/procfs/procfs_vfsops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/procfs/procfs_vfsops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_vfsops.c,v 1.27 1998/02/18 07:05:48 thorpej Exp $	*/
+/*	$NetBSD: procfs_vfsops.c,v 1.28 1998/03/01 02:21:16 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1993 Jan-Simon Pendry
@@ -36,7 +36,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	@(#)procfs_vfsops.c	8.5 (Berkeley) 6/15/94
+ *	@(#)procfs_vfsops.c	8.7 (Berkeley) 5/10/95
  */
 
 /*
@@ -56,6 +56,7 @@
 #include <miscfs/procfs/procfs.h>
 #include <vm/vm.h>			/* for PAGE_SIZE */
 
+void	procfs_init __P((void));
 int	procfs_mount __P((struct mount *, const char *, void *,
 			  struct nameidata *, struct proc *));
 int	procfs_start __P((struct mount *, int, struct proc *));
@@ -68,6 +69,8 @@
 int	procfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
 			   struct vnode **, int *, struct ucred **));
 int	procfs_vptofh __P((struct vnode *, struct fid *));
+int	procfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+			   struct proc *));
 /*
  * VFS Operations.
  *
@@ -94,7 +97,7 @@
 
 	mp->mnt_flag |= MNT_LOCAL;
 	mp->mnt_data = 0;
-	getnewfsid(mp, makefstype(MOUNT_PROCFS));
+	vfs_getnewfsid(mp, MOUNT_PROCFS);
 
 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN, &size);
 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -113,15 +116,10 @@
 	struct proc *p;
 {
 	int error;
-	extern int doforce;
 	int flags = 0;
 
-	if (mntflags & MNT_FORCE) {
-		/* procfs can never be rootfs so don't check for it */
-		if (!doforce)
-			return (EINVAL);
+	if (mntflags & MNT_FORCE)
 		flags |= FORCECLOSE;
-	}
 
 	if ((error = vflush(mp, 0, flags)) != 0)
 		return (error);
@@ -159,11 +157,6 @@
 	struct proc *p;
 {
 
-#ifdef COMPAT_09
-	sbp->f_type = 10;
-#else
-	sbp->f_type = 0;
-#endif
 	sbp->f_bsize = PAGE_SIZE;
 	sbp->f_iosize = PAGE_SIZE;
 	sbp->f_blocks = 1;	/* avoid divide by zero in some df's */
@@ -171,6 +164,11 @@
 	sbp->f_bavail = 0;
 	sbp->f_files = maxproc;			/* approx */
 	sbp->f_ffree = maxproc - nprocs;	/* approx */
+#ifdef COMPAT_09
+	sbp->f_type = 10;
+#else
+	sbp->f_type = 0;
+#endif
 	if (sbp != &mp->mnt_stat) {
 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
@@ -245,6 +243,19 @@
 {
 }
 
+int
+procfs_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;
+{
+	return (EOPNOTSUPP);
+}
+
 extern struct vnodeopv_desc procfs_vnodeop_opv_desc;
 
 struct vnodeopv_desc *procfs_vnodeopv_descs[] = {
@@ -265,6 +276,7 @@
 	procfs_fhtovp,
 	procfs_vptofh,
 	procfs_init,
+	procfs_sysctl,
 	NULL,				/* vfs_mountroot */
 	procfs_vnodeopv_descs,
 };
--- a/sys/miscfs/procfs/procfs_vnops.c	Sun Mar 01 02:15:35 1998 +0000
+++ b/sys/miscfs/procfs/procfs_vnops.c	Sun Mar 01 02:20:01 1998 +0000
@@ -1,8 +1,8 @@
-/*	$NetBSD: procfs_vnops.c,v 1.52 1997/10/10 02:01:05 fvdl Exp $	*/
+/*	$NetBSD: procfs_vnops.c,v 1.53 1998/03/01 02:21:17 fvdl Exp $	*/
 
 /*
  * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
+ * Copyright (c) 1993, 1995
  *	The Reg