summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/autoconf.c76
-rw-r--r--sys/amd64/amd64/db_trace.c2
-rw-r--r--sys/amd64/amd64/genassym.c4
-rw-r--r--sys/amd64/amd64/machdep.c2
-rw-r--r--sys/amd64/amd64/mem.c2
-rw-r--r--sys/amd64/amd64/pmap.c2
-rw-r--r--sys/amd64/amd64/sys_machdep.c2
-rw-r--r--sys/amd64/amd64/trap.c2
-rw-r--r--sys/amd64/amd64/vm_machdep.c2
-rw-r--r--sys/compat/linux/linux_file.c4
-rw-r--r--sys/compat/linux/linux_misc.c4
-rw-r--r--sys/conf/files2
-rw-r--r--sys/ddb/db_watch.c2
-rw-r--r--sys/dev/fdc/fdc.c2
-rw-r--r--sys/dev/vn/vn.c4
-rw-r--r--sys/fs/cd9660/TODO30
-rw-r--r--sys/fs/cd9660/cd9660_bmap.c12
-rw-r--r--sys/fs/cd9660/cd9660_lookup.c173
-rw-r--r--sys/fs/cd9660/cd9660_node.c462
-rw-r--r--sys/fs/cd9660/cd9660_node.h36
-rw-r--r--sys/fs/cd9660/cd9660_rrip.c76
-rw-r--r--sys/fs/cd9660/cd9660_rrip.h48
-rw-r--r--sys/fs/cd9660/cd9660_util.c107
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c448
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c721
-rw-r--r--sys/fs/cd9660/iso.h135
-rw-r--r--sys/fs/deadfs/dead_vnops.c28
-rw-r--r--sys/fs/fdescfs/fdesc.h5
-rw-r--r--sys/fs/fdescfs/fdesc_vfsops.c71
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c162
-rw-r--r--sys/fs/fifofs/fifo.h10
-rw-r--r--sys/fs/fifofs/fifo_vnops.c177
-rw-r--r--sys/fs/msdosfs/msdosfs_denode.c8
-rw-r--r--sys/fs/msdosfs/msdosfs_lookup.c29
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c6
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c28
-rw-r--r--sys/fs/msdosfs/msdosfsmount.h12
-rw-r--r--sys/fs/nullfs/null.h5
-rw-r--r--sys/fs/nullfs/null_subr.c61
-rw-r--r--sys/fs/nullfs/null_vfsops.c19
-rw-r--r--sys/fs/nullfs/null_vnops.c223
-rw-r--r--sys/fs/portalfs/portal_vfsops.c97
-rw-r--r--sys/fs/portalfs/portal_vnops.c57
-rw-r--r--sys/fs/procfs/procfs.h50
-rw-r--r--sys/fs/procfs/procfs_ctl.c24
-rw-r--r--sys/fs/procfs/procfs_fpregs.c3
-rw-r--r--sys/fs/procfs/procfs_map.c2
-rw-r--r--sys/fs/procfs/procfs_mem.c10
-rw-r--r--sys/fs/procfs/procfs_regs.c3
-rw-r--r--sys/fs/procfs/procfs_status.c5
-rw-r--r--sys/fs/procfs/procfs_subr.c55
-rw-r--r--sys/fs/procfs/procfs_vfsops.c109
-rw-r--r--sys/fs/procfs/procfs_vnops.c466
-rw-r--r--sys/fs/specfs/spec_vnops.c91
-rw-r--r--sys/fs/umapfs/umap.h5
-rw-r--r--sys/fs/umapfs/umap_subr.c61
-rw-r--r--sys/fs/umapfs/umap_vfsops.c21
-rw-r--r--sys/fs/umapfs/umap_vnops.c49
-rw-r--r--sys/fs/unionfs/union.h22
-rw-r--r--sys/fs/unionfs/union_subr.c538
-rw-r--r--sys/fs/unionfs/union_vfsops.c238
-rw-r--r--sys/fs/unionfs/union_vnops.c798
-rw-r--r--sys/gnu/ext2fs/ext2_bmap.c21
-rw-r--r--sys/gnu/ext2fs/ext2_extern.h2
-rw-r--r--sys/gnu/ext2fs/ext2_ihash.c117
-rw-r--r--sys/gnu/ext2fs/ext2_inode.c10
-rw-r--r--sys/gnu/ext2fs/ext2_inode_cnv.c26
-rw-r--r--sys/gnu/ext2fs/ext2_lookup.c29
-rw-r--r--sys/gnu/ext2fs/ext2_mount.h34
-rw-r--r--sys/gnu/ext2fs/ext2_vfsops.c13
-rw-r--r--sys/gnu/ext2fs/fs.h4
-rw-r--r--sys/gnu/ext2fs/inode.h100
-rw-r--r--sys/gnu/fs/ext2fs/ext2_bmap.c21
-rw-r--r--sys/gnu/fs/ext2fs/ext2_extern.h2
-rw-r--r--sys/gnu/fs/ext2fs/ext2_inode.c10
-rw-r--r--sys/gnu/fs/ext2fs/ext2_inode_cnv.c26
-rw-r--r--sys/gnu/fs/ext2fs/ext2_lookup.c29
-rw-r--r--sys/gnu/fs/ext2fs/ext2_mount.h34
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vfsops.c13
-rw-r--r--sys/gnu/fs/ext2fs/fs.h4
-rw-r--r--sys/gnu/fs/ext2fs/inode.h100
-rw-r--r--sys/i386/i386/autoconf.c76
-rw-r--r--sys/i386/i386/db_trace.c2
-rw-r--r--sys/i386/i386/genassym.c4
-rw-r--r--sys/i386/i386/machdep.c2
-rw-r--r--sys/i386/i386/math_emulate.c2
-rw-r--r--sys/i386/i386/mem.c2
-rw-r--r--sys/i386/i386/pmap.c2
-rw-r--r--sys/i386/i386/procfs_machdep.c2
-rw-r--r--sys/i386/i386/sys_machdep.c2
-rw-r--r--sys/i386/i386/trap.c2
-rw-r--r--sys/i386/i386/vm_machdep.c2
-rw-r--r--sys/i386/ibcs2/ibcs2_misc.c8
-rw-r--r--sys/i386/ibcs2/imgact_coff.c2
-rw-r--r--sys/i386/include/param.h60
-rw-r--r--sys/i386/include/types.h2
-rw-r--r--sys/i386/isa/fd.c2
-rw-r--r--sys/i386/isa/wd.c2
-rw-r--r--sys/i386/linux/linux_file.c4
-rw-r--r--sys/i386/linux/linux_misc.c4
-rw-r--r--sys/isa/fd.c2
-rw-r--r--sys/isofs/cd9660/TODO30
-rw-r--r--sys/isofs/cd9660/cd9660_bmap.c12
-rw-r--r--sys/isofs/cd9660/cd9660_lookup.c173
-rw-r--r--sys/isofs/cd9660/cd9660_node.c462
-rw-r--r--sys/isofs/cd9660/cd9660_node.h36
-rw-r--r--sys/isofs/cd9660/cd9660_rrip.c76
-rw-r--r--sys/isofs/cd9660/cd9660_rrip.h48
-rw-r--r--sys/isofs/cd9660/cd9660_util.c107
-rw-r--r--sys/isofs/cd9660/cd9660_vfsops.c448
-rw-r--r--sys/isofs/cd9660/cd9660_vnops.c721
-rw-r--r--sys/isofs/cd9660/iso.h135
-rw-r--r--sys/kern/imgact_aout.c2
-rw-r--r--sys/kern/imgact_elf.c4
-rw-r--r--sys/kern/imgact_gzip.c2
-rw-r--r--sys/kern/init_main.c14
-rw-r--r--sys/kern/init_sysent.c2
-rw-r--r--sys/kern/kern_acct.c36
-rw-r--r--sys/kern/kern_clock.c2
-rw-r--r--sys/kern/kern_conf.c8
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/kern/kern_exit.c6
-rw-r--r--sys/kern/kern_fork.c2
-rw-r--r--sys/kern/kern_ktrace.c6
-rw-r--r--sys/kern/kern_lkm.c76
-rw-r--r--sys/kern/kern_lockf.c123
-rw-r--r--sys/kern/kern_proc.c2
-rw-r--r--sys/kern/kern_resource.c2
-rw-r--r--sys/kern/kern_sig.c8
-rw-r--r--sys/kern/kern_synch.c7
-rw-r--r--sys/kern/kern_tc.c2
-rw-r--r--sys/kern/kern_time.c4
-rw-r--r--sys/kern/kern_timeout.c2
-rw-r--r--sys/kern/subr_diskslice.c1
-rw-r--r--sys/kern/subr_trap.c2
-rw-r--r--sys/kern/subr_xxx.c11
-rw-r--r--sys/kern/sys_pipe.c2
-rw-r--r--sys/kern/sys_process.c2
-rw-r--r--sys/kern/syscalls.c2
-rw-r--r--sys/kern/syscalls.master6
-rw-r--r--sys/kern/sysv_shm.c2
-rw-r--r--sys/kern/tty.c2
-rw-r--r--sys/kern/tty_tty.c20
-rw-r--r--sys/kern/uipc_usrreq.c14
-rw-r--r--sys/kern/vfs_cache.c158
-rw-r--r--sys/kern/vfs_conf.c74
-rw-r--r--sys/kern/vfs_export.c796
-rw-r--r--sys/kern/vfs_extattr.c1321
-rw-r--r--sys/kern/vfs_init.c106
-rw-r--r--sys/kern/vfs_lookup.c52
-rw-r--r--sys/kern/vfs_mount.c74
-rw-r--r--sys/kern/vfs_subr.c796
-rw-r--r--sys/kern/vfs_syscalls.c1321
-rw-r--r--sys/kern/vfs_vnops.c78
-rw-r--r--sys/kern/vnode_if.src209
-rw-r--r--sys/miscfs/deadfs/dead_vnops.c28
-rw-r--r--sys/miscfs/fdesc/fdesc.h5
-rw-r--r--sys/miscfs/fdesc/fdesc_vfsops.c71
-rw-r--r--sys/miscfs/fdesc/fdesc_vnops.c162
-rw-r--r--sys/miscfs/fifofs/fifo.h10
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c177
-rw-r--r--sys/miscfs/kernfs/kernfs.h15
-rw-r--r--sys/miscfs/kernfs/kernfs_vfsops.c153
-rw-r--r--sys/miscfs/kernfs/kernfs_vnops.c397
-rw-r--r--sys/miscfs/nullfs/null.h5
-rw-r--r--sys/miscfs/nullfs/null_subr.c61
-rw-r--r--sys/miscfs/nullfs/null_vfsops.c19
-rw-r--r--sys/miscfs/nullfs/null_vnops.c223
-rw-r--r--sys/miscfs/portal/portal_vfsops.c97
-rw-r--r--sys/miscfs/portal/portal_vnops.c57
-rw-r--r--sys/miscfs/procfs/procfs.h50
-rw-r--r--sys/miscfs/procfs/procfs_ctl.c24
-rw-r--r--sys/miscfs/procfs/procfs_fpregs.c3
-rw-r--r--sys/miscfs/procfs/procfs_map.c2
-rw-r--r--sys/miscfs/procfs/procfs_mem.c10
-rw-r--r--sys/miscfs/procfs/procfs_regs.c3
-rw-r--r--sys/miscfs/procfs/procfs_status.c5
-rw-r--r--sys/miscfs/procfs/procfs_subr.c55
-rw-r--r--sys/miscfs/procfs/procfs_vfsops.c109
-rw-r--r--sys/miscfs/procfs/procfs_vnops.c466
-rw-r--r--sys/miscfs/specfs/spec_vnops.c91
-rw-r--r--sys/miscfs/specfs/specdev.h12
-rw-r--r--sys/miscfs/umapfs/umap.h5
-rw-r--r--sys/miscfs/umapfs/umap_subr.c61
-rw-r--r--sys/miscfs/umapfs/umap_vfsops.c21
-rw-r--r--sys/miscfs/umapfs/umap_vnops.c49
-rw-r--r--sys/miscfs/union/union.h22
-rw-r--r--sys/miscfs/union/union_subr.c538
-rw-r--r--sys/miscfs/union/union_vfsops.c238
-rw-r--r--sys/miscfs/union/union_vnops.c798
-rw-r--r--sys/msdosfs/msdosfs_denode.c8
-rw-r--r--sys/msdosfs/msdosfs_lookup.c29
-rw-r--r--sys/msdosfs/msdosfs_vfsops.c6
-rw-r--r--sys/msdosfs/msdosfs_vnops.c28
-rw-r--r--sys/msdosfs/msdosfsmount.h12
-rw-r--r--sys/nfs/nfs.h168
-rw-r--r--sys/nfs/nfs_bio.c26
-rw-r--r--sys/nfs/nfs_common.c26
-rw-r--r--sys/nfs/nfs_common.h3
-rw-r--r--sys/nfs/nfs_node.c14
-rw-r--r--sys/nfs/nfs_nqlease.c38
-rw-r--r--sys/nfs/nfs_serv.c32
-rw-r--r--sys/nfs/nfs_socket.c7
-rw-r--r--sys/nfs/nfs_srvcache.c2
-rw-r--r--sys/nfs/nfs_subs.c26
-rw-r--r--sys/nfs/nfs_syscalls.c4
-rw-r--r--sys/nfs/nfs_vfsops.c165
-rw-r--r--sys/nfs/nfs_vnops.c71
-rw-r--r--sys/nfs/nfsdiskless.h7
-rw-r--r--sys/nfs/nfsm_subs.h3
-rw-r--r--sys/nfs/nfsmount.h3
-rw-r--r--sys/nfs/nfsnode.h25
-rw-r--r--sys/nfs/nfsrtt.h3
-rw-r--r--sys/nfs/nfsrvcache.h3
-rw-r--r--sys/nfs/nqnfs.h3
-rw-r--r--sys/nfs/rpcv2.h3
-rw-r--r--sys/nfs/xdr_subs.h3
-rw-r--r--sys/nfsclient/nfs.h168
-rw-r--r--sys/nfsclient/nfs_bio.c26
-rw-r--r--sys/nfsclient/nfs_nfsiod.c4
-rw-r--r--sys/nfsclient/nfs_node.c14
-rw-r--r--sys/nfsclient/nfs_socket.c7
-rw-r--r--sys/nfsclient/nfs_subs.c26
-rw-r--r--sys/nfsclient/nfs_vfsops.c165
-rw-r--r--sys/nfsclient/nfs_vnops.c71
-rw-r--r--sys/nfsclient/nfsargs.h168
-rw-r--r--sys/nfsclient/nfsdiskless.h7
-rw-r--r--sys/nfsclient/nfsm_subs.h3
-rw-r--r--sys/nfsclient/nfsmount.h3
-rw-r--r--sys/nfsclient/nfsnode.h25
-rw-r--r--sys/nfsclient/nfsstats.h168
-rw-r--r--sys/nfsserver/nfs.h168
-rw-r--r--sys/nfsserver/nfs_serv.c32
-rw-r--r--sys/nfsserver/nfs_srvcache.c2
-rw-r--r--sys/nfsserver/nfs_srvsock.c7
-rw-r--r--sys/nfsserver/nfs_srvsubs.c26
-rw-r--r--sys/nfsserver/nfs_syscalls.c4
-rw-r--r--sys/nfsserver/nfsm_subs.h3
-rw-r--r--sys/nfsserver/nfsrvcache.h3
-rw-r--r--sys/nfsserver/nfsrvstats.h168
-rw-r--r--sys/scsi/cd.c2
-rw-r--r--sys/scsi/od.c2
-rw-r--r--sys/scsi/sd.c3
-rw-r--r--sys/scsi/st.c2
-rw-r--r--sys/sys/conf.h7
-rw-r--r--sys/sys/linedisc.h7
-rw-r--r--sys/sys/lkm.h4
-rw-r--r--sys/sys/lockf.h20
-rw-r--r--sys/sys/malloc.h4
-rw-r--r--sys/sys/mount.h305
-rw-r--r--sys/sys/stat.h6
-rw-r--r--sys/sys/syscall-hide.h1
-rw-r--r--sys/sys/syscall.h1
-rw-r--r--sys/sys/sysctl.h3
-rw-r--r--sys/sys/sysent.h2
-rw-r--r--sys/sys/sysproto.h8
-rw-r--r--sys/sys/tty.h2
-rw-r--r--sys/sys/user.h2
-rw-r--r--sys/sys/vnode.h97
-rw-r--r--sys/ufs/ffs/ffs_alloc.c244
-rw-r--r--sys/ufs/ffs/ffs_balloc.c116
-rw-r--r--sys/ufs/ffs/ffs_extern.h41
-rw-r--r--sys/ufs/ffs/ffs_inode.c50
-rw-r--r--sys/ufs/ffs/ffs_subr.c27
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c314
-rw-r--r--sys/ufs/ffs/ffs_vnops.c51
-rw-r--r--sys/ufs/ffs/fs.h288
-rw-r--r--sys/ufs/lfs/lfs_subr.c9
-rw-r--r--sys/ufs/lfs/lfs_syscalls.c10
-rw-r--r--sys/ufs/mfs/mfs_extern.h4
-rw-r--r--sys/ufs/mfs/mfs_vfsops.c24
-rw-r--r--sys/ufs/mfs/mfs_vnops.c24
-rw-r--r--sys/ufs/mfs/mfsnode.h8
-rw-r--r--sys/ufs/ufs/dinode.h53
-rw-r--r--sys/ufs/ufs/dir.h63
-rw-r--r--sys/ufs/ufs/inode.h100
-rw-r--r--sys/ufs/ufs/quota.h48
-rw-r--r--sys/ufs/ufs/ufs_bmap.c21
-rw-r--r--sys/ufs/ufs/ufs_extern.h17
-rw-r--r--sys/ufs/ufs/ufs_ihash.c117
-rw-r--r--sys/ufs/ufs/ufs_inode.c88
-rw-r--r--sys/ufs/ufs/ufs_lookup.c151
-rw-r--r--sys/ufs/ufs/ufs_quota.c151
-rw-r--r--sys/ufs/ufs/ufs_readwrite.c14
-rw-r--r--sys/ufs/ufs/ufs_vfsops.c56
-rw-r--r--sys/ufs/ufs/ufs_vnops.c266
-rw-r--r--sys/ufs/ufs/ufsmount.h34
-rw-r--r--sys/vm/vm.h11
-rw-r--r--sys/vm/vm_extern.h2
-rw-r--r--sys/vm/vm_fault.c5
-rw-r--r--sys/vm/vm_glue.c8
-rw-r--r--sys/vm/vm_init.c2
-rw-r--r--sys/vm/vm_kern.c2
-rw-r--r--sys/vm/vm_map.c59
-rw-r--r--sys/vm/vm_map.h51
-rw-r--r--sys/vm/vm_meter.c2
-rw-r--r--sys/vm/vm_mmap.c2
-rw-r--r--sys/vm/vm_object.c19
-rw-r--r--sys/vm/vm_page.c2
-rw-r--r--sys/vm/vm_pageout.c8
-rw-r--r--sys/vm/vm_unix.c2
-rw-r--r--sys/vm/vnode_pager.c18
302 files changed, 13528 insertions, 9858 deletions
diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c
index 866b420..6e305d0 100644
--- a/sys/amd64/amd64/autoconf.c
+++ b/sys/amd64/amd64/autoconf.c
@@ -53,6 +53,7 @@
#include <sys/reboot.h>
#include <sys/kernel.h>
#include <sys/mount.h>
+#include <sys/vnode.h>
#include <sys/sysctl.h>
#include <machine/bootinfo.h>
@@ -88,31 +89,15 @@
static void configure __P((void *));
SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
-#ifdef MFS_ROOT
-extern struct vfsops mfs_vfsops;
-#endif
-#ifdef FFS
-extern struct vfsops ufs_vfsops;
-#endif
-#ifdef LFS
-extern struct vfsops lfs_vfsops;
-#endif
-#ifdef NFS
-extern int nfs_mountroot __P((void *));
-#endif
-#ifdef CD9660
-extern int cd9660_mountroot __P((void *));
-#endif
-#ifdef MSDOSFS
-extern int msdosfs_mountroot __P((void *));
-#endif
-
static void configure_finish __P((void));
static void configure_start __P((void));
static int setdumpdev __P((dev_t dev));
static void setroot __P((void));
#ifdef CD9660
+
+#include <isofs/cd9660/iso.h>
+
/* We need to try out all our potential CDROM drives, so we need a table. */
static struct {
char *name;
@@ -138,7 +123,7 @@ find_cdrom_root(dummy)
rootdev = makedev(try_cdrom[k].major,j*8);
printf("trying rootdev=0x%lx (%s%d)\n",
rootdev, try_cdrom[k].name,j);
- i = (*cd9660_mountroot)((void *)NULL);
+ i = (*cd9660_mountroot)();
if (!i) return i;
}
return EINVAL;
@@ -176,6 +161,11 @@ configure(dummy)
enable_intr();
INTREN(IRQ_SLAVE);
+#if NCRD > 0
+ /* Before isa_configure to avoid ISA drivers finding our cards */
+ pccard_configure();
+#endif
+
#if NEISA > 0
eisa_configure();
#endif
@@ -188,11 +178,6 @@ configure(dummy)
isa_configure();
#endif
-#if NCRD > 0
- /* After everyone else has a chance at grabbing resources */
- pccard_configure();
-#endif
-
if (setdumpdev(dumpdev) != 0)
dumpdev = NODEV;
@@ -235,19 +220,26 @@ configure(dummy)
}
#ifdef CD9660
- if ((boothowto & RB_CDROM) && !mountroot) {
+ if ((boothowto & RB_CDROM)) {
if (bootverbose)
printf("Considering CD-ROM root f/s.\n");
- mountroot = find_cdrom_root;
+ mountrootfsname = "cd9660";
}
#endif
+#ifdef NFS
+ if (!mountrootfsname && nfs_diskless_valid) {
+ if (bootverbose)
+ printf("Considering NFS root f/s.\n");
+ mountrootfsname = "nfs";
+ }
+#endif /* NFS */
+
#ifdef MFS_ROOT
- if (!mountroot) {
+ if (!mountrootfsname) {
if (bootverbose)
printf("Considering MFS root f/s.\n");
- mountroot = vfs_mountroot; /* XXX goes away*/
- mountrootvfsops = &mfs_vfsops;
+ mountrootfsname = "mfs";
/*
* Ignore the -a flag if this kernel isn't compiled
* with a generic root/swap configuration: if we skip
@@ -260,21 +252,11 @@ configure(dummy)
setroot();
}
#endif
-
-#ifdef NFS
- if (!mountroot && nfs_diskless_valid) {
- if (bootverbose)
- printf("Considering NFS root f/s.\n");
- mountroot = nfs_mountroot;
- }
-#endif /* NFS */
-
#ifdef FFS
- if (!mountroot) {
+ if (!mountrootfsname) {
+ mountrootfsname = "ufs";
if (bootverbose)
printf("Considering FFS root f/s.\n");
- mountroot = vfs_mountroot; /* XXX goes away*/
- mountrootvfsops = &ufs_vfsops;
/*
* Ignore the -a flag if this kernel isn't compiled
* with a generic root/swap configuration: if we skip
@@ -288,11 +270,10 @@ configure(dummy)
}
#endif
#ifdef LFS
- if (!mountroot) {
+ if (!mountrootfsname) {
if (bootverbose)
printf("Considering LFS root f/s.\n");
- mountroot = vfs_mountroot; /* XXX goes away*/
- mountrootvfsops = &lfs_vfsops;
+ mountrootfsname = "lfs";
/*
* Ignore the -a flag if this kernel isn't compiled
* with a generic root/swap configuration: if we skip
@@ -305,8 +286,7 @@ configure(dummy)
setroot();
}
#endif
-
- if (!mountroot) {
+ if (!mountrootfsname) {
panic("Nobody wants to mount my root for me");
}
@@ -417,4 +397,4 @@ sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
}
SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
- 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
+ 0, sizeof dumpdev, sysctl_kern_dumpdev, "I", "");
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index 386e093..93078a8 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -34,7 +34,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_prot.h>
#include <vm/pmap.h>
#include <ddb/ddb.h>
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 9a2f646e..c993129 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -61,13 +61,15 @@
#include <sys/vmmeter.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/user.h>
#include <net/if.h>
#include <netinet/in.h>
#include <nfs/nfsv2.h>
+#include <nfs/rpcv2.h>
+#include <nfs/nfs.h>
#include <nfs/nfsdiskless.h>
extern int main __P((void));
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 6ebccff..b95b0ff 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -82,7 +82,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c
index 28d8058..5275e7d 100644
--- a/sys/amd64/amd64/mem.c
+++ b/sys/amd64/amd64/mem.c
@@ -68,7 +68,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_prot.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 3c47ee4..0159c32 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -85,7 +85,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index d1b9807..8506cfc 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -44,7 +44,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index b38e35d..c866f32 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -61,7 +61,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index d320dac..f6c1606 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -58,7 +58,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 55c8a35..9fe4d40 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -450,7 +450,7 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
buflen = max(DIRBLKSIZ, nbytes + blockoff);
buflen = min(buflen, MAXBSIZE);
buf = malloc(buflen, M_TEMP, M_WAITOK);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
again:
aiov.iov_base = buf;
aiov.iov_len = buflen;
@@ -530,7 +530,7 @@ again:
eof:
*retval = nbytes - resid;
out:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
free(buf, M_TEMP);
return error;
}
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 536d797..d0332cf 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -237,7 +237,7 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
/*
* Lock no longer needed
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
locked = 0;
/*
@@ -392,7 +392,7 @@ cleanup:
* Unlock vnode if needed
*/
if (locked)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
/*
* Release the kernel mapping.
diff --git a/sys/conf/files b/sys/conf/files
index f543378..48e61f0 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -52,6 +52,7 @@ kern/kern_exit.c standard
kern/kern_fork.c standard
kern/kern_ktrace.c standard
kern/kern_lkm.c standard
+kern/kern_lock.c standard
kern/kern_lockf.c standard
kern/kern_malloc.c standard
kern/kern_mib.c standard
@@ -373,7 +374,6 @@ ufs/ufs/ufs_vfsops.c standard
ufs/ufs/ufs_vnops.c standard
vm/default_pager.c standard
vm/device_pager.c standard
-vm/kern_lock.c standard
vm/swap_pager.c standard
vm/vm_fault.c standard
vm/vm_glue.c standard
diff --git a/sys/ddb/db_watch.c b/sys/ddb/db_watch.c
index a8edc24..d42fb97 100644
--- a/sys/ddb/db_watch.c
+++ b/sys/ddb/db_watch.c
@@ -35,7 +35,7 @@
#include <sys/systm.h>
#include <vm/vm.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_prot.h>
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index 9c095c9..c2d495d 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -277,7 +277,7 @@ static d_strategy_t fdstrategy;
static struct cdevsw fd_cdevsw;
static struct bdevsw fd_bdevsw =
{ Fdopen, fdclose, fdstrategy, fdioctl, /*2*/
- nodump, nopsize, 0, "fd", &fd_cdevsw, -1 };
+ nodump, nopsize, D_DISK, "fd", &fd_cdevsw, -1 };
static struct isa_device *fdcdevs[NFDC];
diff --git a/sys/dev/vn/vn.c b/sys/dev/vn/vn.c
index cbff83c..f03b7c1 100644
--- a/sys/dev/vn/vn.c
+++ b/sys/dev/vn/vn.c
@@ -457,11 +457,11 @@ vnioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
return(error);
error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
if (error) {
- VOP_UNLOCK(nd.ni_vp);
+ VOP_UNLOCK(nd.ni_vp, 0, p);
(void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
return(error);
}
- VOP_UNLOCK(nd.ni_vp);
+ VOP_UNLOCK(nd.ni_vp, 0, p);
vn->sc_vp = nd.ni_vp;
vn->sc_size = btodb(vattr.va_size); /* note truncation */
error = vnsetcred(vn, p->p_ucred);
diff --git a/sys/fs/cd9660/TODO b/sys/fs/cd9660/TODO
index eb24a23..71859c7 100644
--- a/sys/fs/cd9660/TODO
+++ b/sys/fs/cd9660/TODO
@@ -25,16 +25,6 @@
There is some preliminary stuff in there that (ab-)uses the mknod
system call, but this needs a writable filesystem
- 3) should be called cdfs, as there are other ISO file system soon possible
-
- Not yet. Probably we should make another file system when the ECMA draft
- is valid and do it. For doing Rock Ridge Support, I can use almost same
- code. So I just use the same file system interface...
-
- 4) should have file handles implemented for use with NFS, etc
-
- Yes. we have already this one, and I based it for this release.
-
5) should have name translation enabled by mount flag
Yes. we can disable the Rock Ridge Extension by follows option;
@@ -57,23 +47,3 @@
clean. As far as I know, if you export the cdrom by NFS, the client
can access the 8 bit clean (ie. Solaris Japanese with EUC code )
- 9) Access checks in isofs_access
-
- Not yet.
-
- 10) Support for generation numbers
-
- Yes. Default is to list only the last file (the one with the highest
- generation number). If you mount with -gen, all files are shown with
- their generation numbers. In both cases you can specify the generation
- number on opening files (if you happen to know it) or leave it off,
- when it will again find the last file.
-
- 11) Support for extended attributes
-
- Yes. Since this requires an extra block buffer for the attributes
- this must be enabled on mounting with the option -extattr.
-
-----------
-Last update July 19, '93 by Atsushi Murai. (amurai@spec.co.jp)
-Last update August 19, '93 by Wolfgang Solfrank. (ws@tools.de)
diff --git a/sys/fs/cd9660/cd9660_bmap.c b/sys/fs/cd9660/cd9660_bmap.c
index 6fffe7a..71dfb9e 100644
--- a/sys/fs/cd9660/cd9660_bmap.c
+++ b/sys/fs/cd9660/cd9660_bmap.c
@@ -67,7 +67,7 @@ cd9660_bmap(ap)
{
struct iso_node *ip = VTOI(ap->a_vp);
daddr_t lblkno = ap->a_bn;
- long bsize;
+ int bshift;
/*
* Check for underlying vnode requests and ensure that logical
@@ -81,8 +81,8 @@ cd9660_bmap(ap)
/*
* Compute the requested block number
*/
- bsize = ip->i_mnt->logical_block_size;
- *ap->a_bnp = (ip->iso_start + lblkno) * btodb(bsize);
+ bshift = ip->i_mnt->im_bshift;
+ *ap->a_bnp = (ip->iso_start + lblkno) << (bshift - DEV_BSHIFT);
/*
* Determine maximum number of readahead blocks following the
@@ -91,11 +91,11 @@ cd9660_bmap(ap)
if (ap->a_runp) {
int nblk;
- nblk = (ip->i_size - (lblkno + 1) * bsize) / bsize;
+ nblk = (ip->i_size >> bshift) - (lblkno + 1);
if (nblk <= 0)
*ap->a_runp = 0;
- else if (nblk >= MAXBSIZE/bsize)
- *ap->a_runp = MAXBSIZE/bsize - 1;
+ else if (nblk >= (MAXBSIZE >> bshift))
+ *ap->a_runp = (MAXBSIZE >> bshift) - 1;
else
*ap->a_runp = nblk;
}
diff --git a/sys/fs/cd9660/cd9660_lookup.c b/sys/fs/cd9660/cd9660_lookup.c
index 6e85a81..a7e38bb 100644
--- a/sys/fs/cd9660/cd9660_lookup.c
+++ b/sys/fs/cd9660/cd9660_lookup.c
@@ -108,8 +108,9 @@ cd9660_lookup(ap)
int saveoffset = 0; /* offset of last directory entry in dir */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
- struct iso_node *pdp; /* saved dp during symlink work */
- struct iso_node *tdp; /* returned by iget */
+ struct vnode *pdp; /* saved dp during symlink work */
+ struct vnode *tdp; /* returned by cd9660_vget_internal */
+ u_long bmask; /* block offset mask */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
int error;
@@ -126,6 +127,7 @@ cd9660_lookup(ap)
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
+ struct proc *p = cnp->cn_proc;
bp = NULL;
*vpp = NULL;
@@ -139,13 +141,13 @@ cd9660_lookup(ap)
* Check accessiblity of directory.
*/
if (vdp->v_type != VDIR)
- return (ENOTDIR);
- if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)))
+ return (ENOTDIR);
+ if (error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))
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.
*
@@ -160,29 +162,29 @@ cd9660_lookup(ap)
return (error);
#ifdef PARANOID
if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT))
- panic("ufs_lookup: .. through root");
+ panic("cd9660_lookup: .. through root");
#endif
/*
* Get the next vnode in the path.
* See comment below starting `Step through' for
* an explaination of the locking protocol.
*/
- pdp = dp;
+ pdp = vdp;
dp = VTOI(*vpp);
vdp = *vpp;
vpid = vdp->v_id;
- if (pdp == dp) {
+ if (pdp == vdp) {
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- ISO_IUNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, p);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- ISO_ILOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
/*
* Check that the capability number did not change
@@ -191,13 +193,14 @@ cd9660_lookup(ap)
if (!error) {
if (vpid == vdp->v_id)
return (0);
- iso_iput(dp);
- if (lockparent && pdp != dp && (flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
+ vput(vdp);
+ if (lockparent && pdp != vdp && (flags & ISLASTCN))
+ VOP_UNLOCK(pdp, 0, p);
}
- ISO_ILOCK(pdp);
- dp = pdp;
- vdp = ITOV(dp);
+ if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
+ return (error);
+ vdp = pdp;
+ dp = VTOI(pdp);
*vpp = NULL;
}
@@ -223,6 +226,7 @@ cd9660_lookup(ap)
* profiling time and hence has been removed in the interest
* of simplicity.
*/
+ bmask = imp->im_bmask;
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
dp->i_diroff > dp->i_size) {
entryoffsetinblock = 0;
@@ -230,16 +234,14 @@ cd9660_lookup(ap)
numdirpasses = 1;
} else {
dp->i_offset = dp->i_diroff;
- entryoffsetinblock = iso_blkoff(imp, dp->i_offset);
- if (entryoffsetinblock != 0) {
- if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
+ if ((entryoffsetinblock = dp->i_offset & bmask) &&
+ (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
return (error);
- }
numdirpasses = 2;
iso_nchstats.ncs_2passes++;
}
- endsearch = roundup(dp->i_size, imp->logical_block_size);
-
+ endsearch = dp->i_size;
+
searchloop:
while (dp->i_offset < endsearch) {
/*
@@ -247,10 +249,11 @@ searchloop:
* read the next directory block.
* Release previous if it exists.
*/
- if (iso_blkoff(imp, dp->i_offset) == 0) {
+ if ((dp->i_offset & bmask) == 0) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
+ if (error =
+ VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))
return (error);
entryoffsetinblock = 0;
}
@@ -258,13 +261,13 @@ searchloop:
* Get pointer to next entry.
*/
ep = (struct iso_directory_record *)
- (bp->b_un.b_addr + entryoffsetinblock);
-
- reclen = isonum_711 (ep->length);
+ ((char *)bp->b_data + entryoffsetinblock);
+
+ reclen = isonum_711(ep->length);
if (reclen == 0) {
/* skip to next block, if any */
dp->i_offset =
- roundup(dp->i_offset, imp->logical_block_size);
+ (dp->i_offset & ~bmask) + imp->logical_block_size;
continue;
}
@@ -275,10 +278,7 @@ searchloop:
if (entryoffsetinblock + reclen > imp->logical_block_size)
/* entries are not allowed to cross boundaries */
break;
-
- /*
- * Check for a name match.
- */
+
namelen = isonum_711(ep->name_len);
isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
&ep->date[6]: ep->flags);
@@ -286,7 +286,10 @@ searchloop:
if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen)
/* illegal entry, stop */
break;
-
+
+ /*
+ * Check for a name match.
+ */
switch (imp->iso_ftype) {
default:
if (!(isoflags & 4) == !assoc) {
@@ -297,10 +300,9 @@ searchloop:
&& ep->name[0] == ((flags & ISDOTDOT) ? 1 : 0)) {
/*
* Save directory entry's inode number and
- * reclen in ndp->ni_ufs area, and release
- * directory buffer.
+ * release directory buffer.
*/
- isodirino(&dp->i_ino,ep,imp);
+ dp->i_ino = isodirino(ep, imp);
goto found;
}
if (namelen != 1
@@ -308,8 +310,8 @@ searchloop:
goto notfound;
} else if (!(res = isofncmp(name,len,
ep->name,namelen))) {
- if (isoflags & 2)
- isodirino(&ino,ep,imp);
+ if (isonum_711(ep->flags)&2)
+ ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno)
+ entryoffsetinblock;
@@ -326,7 +328,7 @@ searchloop:
break;
case ISO_FTYPE_RRIP:
if (isonum_711(ep->flags)&2)
- isodirino(&ino,ep,imp);
+ ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno) + entryoffsetinblock;
dp->i_ino = ino;
@@ -344,15 +346,17 @@ searchloop:
foundino:
dp->i_ino = ino;
if (saveoffset != dp->i_offset) {
- if (iso_lblkno(imp,dp->i_offset)
- != iso_lblkno(imp,saveoffset)) {
+ if (lblkno(imp, dp->i_offset) !=
+ lblkno(imp, saveoffset)) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(dp, saveoffset, &bp)))
+ if (error = VOP_BLKATOFF(vdp,
+ (off_t)saveoffset, NULL, &bp))
return (error);
}
- ep = (struct iso_directory_record *)(bp->b_un.b_addr
- + iso_blkoff(imp,saveoffset));
+ entryoffsetinblock = saveoffset & bmask;
+ ep = (struct iso_directory_record *)
+ ((char *)bp->b_data + entryoffsetinblock);
dp->i_offset = saveoffset;
}
goto found;
@@ -370,6 +374,7 @@ notfound:
}
if (bp != NULL)
brelse(bp);
+
/*
* Insert name into cache (as non-existent) if appropriate.
*/
@@ -382,9 +387,7 @@ notfound:
found:
if (numdirpasses == 2)
iso_nchstats.ncs_pass2++;
- if (bp != NULL)
- brelse(bp);
-
+
/*
* Found component in pathname.
* If the final component of path name, save information
@@ -412,31 +415,39 @@ found:
* work if the file system has any hard links other than ".."
* that point backwards in the directory structure.
*/
- pdp = dp;
+ pdp = vdp;
/*
* If ino is different from dp->i_ino,
* it's a relocated directory.
*/
if (flags & ISDOTDOT) {
- ISO_IUNLOCK(pdp); /* race to get the inode */
- if ((error = iso_iget(dp,dp->i_ino,
- dp->i_ino != ino,
- &tdp,ep))) {
- ISO_ILOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p); /* 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) {
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
- if (lockparent && (flags & ISLASTCN))
- ISO_ILOCK(pdp);
- *vpp = ITOV(tdp);
+ if (lockparent && (flags & ISLASTCN) &&
+ (error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
+ vput(tdp);
+ return (error);
+ }
+ *vpp = tdp;
} else if (dp->i_number == dp->i_ino) {
+ brelse(bp);
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
- if ((error = iso_iget(dp,dp->i_ino,dp->i_ino!=ino,&tdp,ep)))
+ error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
+ dp->i_ino != ino, ep);
+ brelse(bp);
+ if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
- *vpp = ITOV(tdp);
+ VOP_UNLOCK(pdp, 0, p);
+ *vpp = tdp;
}
/*
@@ -448,29 +459,37 @@ found:
}
/*
- * Return buffer with contents of block "offset"
- * from the beginning of directory "ip". If "res"
- * is non-zero, fill it in with a pointer to the
+ * Return buffer with the contents of block "offset" from the beginning of
+ * directory "ip". If "res" is non-zero, fill it in with a pointer to the
* remaining space in the directory.
*/
int
-iso_blkatoff(ip, offset, bpp)
- struct iso_node *ip;
- doff_t offset;
- struct buf **bpp;
+cd9660_blkatoff(ap)
+ struct vop_blkatoff_args /* {
+ struct vnode *a_vp;
+ off_t a_offset;
+ char **a_res;
+ struct buf **a_bpp;
+ } */ *ap;
{
- register struct iso_mnt *imp = ip->i_mnt;
- daddr_t lbn = iso_lblkno(imp,offset);
- int bsize = iso_blksize(imp,ip,lbn);
+ struct iso_node *ip;
+ register struct iso_mnt *imp;
struct buf *bp;
- int error;
+ daddr_t lbn;
+ int bsize, error;
- if ((error = bread(ITOV(ip),lbn,bsize,NOCRED,&bp))) {
+ ip = VTOI(ap->a_vp);
+ imp = ip->i_mnt;
+ lbn = lblkno(imp, ap->a_offset);
+ bsize = blksize(imp, ip, lbn);
+
+ if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
brelse(bp);
- *bpp = 0;
+ *ap->a_bpp = NULL;
return (error);
}
- *bpp = bp;
-
+ if (ap->a_res)
+ *ap->a_res = (char *)bp->b_data + blkoff(imp, ap->a_offset);
+ *ap->a_bpp = bp;
return (0);
}
diff --git a/sys/fs/cd9660/cd9660_node.c b/sys/fs/cd9660/cd9660_node.c
index c3f0911..c726696 100644
--- a/sys/fs/cd9660/cd9660_node.c
+++ b/sys/fs/cd9660/cd9660_node.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1982, 1986, 1989, 1994
+ * Copyright (c) 1982, 1986, 1989, 1994, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
@@ -52,32 +52,21 @@
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
#include <isofs/cd9660/iso_rrip.h>
-#define INOHSZ 512
-#if ((INOHSZ&(INOHSZ-1)) == 0)
-#define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1))
-#else
-#define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ)
-#endif
-
-union iso_ihead {
- union iso_ihead *ih_head[2];
- struct iso_node *ih_chain[2];
-} iso_ihead[INOHSZ];
-
-#ifdef ISODEVMAP
-#define DNOHSZ 64
-#if ((DNOHSZ&(DNOHSZ-1)) == 0)
-#define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1))
-#else
-#define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ)
-#endif
-
-union iso_dhead {
- union iso_dhead *dh_head[2];
- struct iso_dnode *dh_chain[2];
-} iso_dhead[DNOHSZ];
+/*
+ * Structures associated with iso_node caching.
+ */
+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;
+u_long idvhash;
+#define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
#endif
static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
@@ -86,73 +75,68 @@ static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
* Initialize hash links for inodes and dnodes.
*/
int
-cd9660_init()
+cd9660_init(vfsp)
+ struct vfsconf *vfsp;
{
- register int i;
- register union iso_ihead *ih = iso_ihead;
-#ifdef ISODEVMAP
- register union iso_dhead *dh = iso_dhead;
-#endif
- for (i = INOHSZ; --i >= 0; ih++) {
- ih->ih_head[0] = ih;
- ih->ih_head[1] = ih;
- }
-#ifdef ISODEVMAP
- for (i = DNOHSZ; --i >= 0; dh++) {
- dh->dh_head[0] = dh;
- dh->dh_head[1] = dh;
- }
+ isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash);
+ simple_lock_init(&cd9660_ihash_slock);
+#ifdef ISODEVMAP
+ idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash);
#endif
return (0);
}
-#ifdef ISODEVMAP
+#ifdef ISODEVMAP
/*
* Enter a new node into the device hash list
*/
struct iso_dnode *
-iso_dmap(dev,ino,create)
- dev_t dev;
- ino_t ino;
+iso_dmap(device, inum, create)
+ dev_t device;
+ ino_t inum;
int create;
{
- struct iso_dnode *dp;
- union iso_dhead *dh;
+ register struct iso_dnode **dpp, *dp, *dq;
- dh = &iso_dhead[DNOHASH(dev, ino)];
- for (dp = dh->dh_chain[0];
- dp != (struct iso_dnode *)dh;
- dp = dp->d_forw)
- if (ino == dp->i_number && dev == dp->i_dev)
- return dp;
+ dpp = &idvhashtbl[DNOHASH(device, inum)];
+ for (dp = *dpp;; dp = dp->d_next) {
+ if (dp == NULL)
+ return (NULL);
+ if (inum == dp->i_number && device == dp->i_dev)
+ return (dp);
if (!create)
- return (struct iso_dnode *)0;
+ return (NULL);
- MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK);
+ MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE,
+ M_WAITOK);
dp->i_dev = dev;
dp->i_number = ino;
- insque(dp,dh);
- return dp;
+ if (dq = *dpp)
+ dq->d_prev = dp->d_next;
+ dp->d_next = dq;
+ dp->d_prev = dpp;
+ *dpp = dp;
+
+ return (dp);
}
void
-iso_dunmap(dev)
- dev_t dev;
+iso_dunmap(device)
+ dev_t device;
{
- struct iso_dnode *dp, *dq;
- union iso_dhead *dh;
-
- for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) {
- for (dp = dh->dh_chain[0];
- dp != (struct iso_dnode *)dh;
- dp = dq) {
- dq = dp->d_forw;
- if (dev == dp->i_dev) {
- remque(dp);
- FREE(dp,M_CACHE);
+ struct iso_dnode **dpp, *dp, *dq;
+
+ for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) {
+ for (dp = *dpp; dp != NULL; dp = dq)
+ dq = dp->d_next;
+ if (device == dp->i_dev) {
+ if (dq)
+ dq->d_prev = dp->d_prev;
+ *dp->d_prev = dq;
+ FREE(dp, M_CACHE);
}
}
}
@@ -160,197 +144,74 @@ iso_dunmap(dev)
#endif
/*
- * Look up a ISOFS dinode number to find its incore vnode.
- * If it is not in core, read it in from the specified device.
- * If it is in core, wait for the lock bit to clear, then
- * return the inode locked. Detection and handling of mount
- * points must be done by the calling routine.
+ * Use the device/inum pair to find the incore inode, and return a pointer
+ * to it. If it is in core, but locked, wait for it.
*/
-int
-iso_iget(xp, ino, relocated, ipp, isodir)
- struct iso_node *xp;
- ino_t ino;
- int relocated;
- struct iso_node **ipp;
- struct iso_directory_record *isodir;
+struct vnode *
+cd9660_ihashget(dev, inum)
+ dev_t dev;
+ ino_t inum;
{
- dev_t dev = xp->i_dev;
- struct mount *mntp = ITOV(xp)->v_mount;
- register struct iso_node *ip, *iq;
- register struct vnode *vp;
-#ifdef ISODEVMAP
- register struct iso_dnode *dp;
-#endif
- struct vnode *nvp;
- struct buf *bp = NULL, *bp2 = NULL;
- union iso_ihead *ih;
- int error, result;
- struct iso_mnt *imp;
+ struct proc *p = curproc; /* XXX */
+ struct iso_node *ip;
+ struct vnode *vp;
- ih = &iso_ihead[INOHASH(dev, ino)];
loop:
- for (ip = ih->ih_chain[0];
- ip != (struct iso_node *)ih;
- ip = ip->i_forw) {
- if (ino != ip->i_number || dev != ip->i_dev)
- continue;
- if ((ip->i_flag&ILOCKED) != 0) {
- ip->i_flag |= IWANT;
- (void) tsleep((caddr_t)ip, PINOD, "isoigt", 0);
- goto loop;
- }
- if (vget(ITOV(ip), 1))
- goto loop;
- *ipp = ip;
- return 0;
- }
-
- /*
- * Do the MALLOC before the getnewvnode since doing so afterward
- * might cause a bogus v_data pointer to get dereferenced
- * elsewhere if MALLOC should block.
- */
- MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE, M_WAITOK);
-
- /*
- * Allocate a new vnode/iso_node.
- */
- if ((error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp))) {
- *ipp = NULL;
- FREE(ip, M_ISOFSNODE);
- return error;
- }
- bzero((caddr_t)ip, sizeof(struct iso_node));
- nvp->v_data = ip;
- ip->i_vnode = nvp;
- ip->i_flag = 0;
- ip->i_devvp = 0;
- ip->i_diroff = 0;
- ip->i_lockf = 0;
-
- /*
- * Put it onto its hash chain and lock it so that other requests for
- * this inode will block if they arrive while we are sleeping waiting
- * for old data structures to be purged or for the contents of the
- * disk portion of this inode to be read.
- */
- ip->i_dev = dev;
- ip->i_number = ino;
- insque(ip, ih);
- ISO_ILOCK(ip);
-
- imp = VFSTOISOFS (mntp);
- ip->i_mnt = imp;
- ip->i_devvp = imp->im_devvp;
- VREF(ip->i_devvp);
-
- if (relocated) {
- /*
- * On relocated directories we must
- * read the `.' entry out of a dir.
- */
- ip->iso_start = ino >> imp->im_bshift;
- if ((error = iso_blkatoff(ip,0,&bp))) {
- vrele(ip->i_devvp);
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
- iso_iput(ip);
- *ipp = 0;
- return error;
- }
- isodir = (struct iso_directory_record *)bp->b_un.b_addr;
- }
-
- ip->iso_extent = isonum_733(isodir->extent);
- ip->i_size = isonum_733(isodir->size);
- ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
-
- vp = ITOV(ip);
-
- /*
- * Setup time stamp, attribute
- */
- vp->v_type = VNON;
- switch (imp->iso_ftype) {
- default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */
- if ((imp->im_flags&ISOFSMNT_EXTATT)
- && isonum_711(isodir->ext_attr_length))
- iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length),
- &bp2);
- cd9660_defattr(isodir,ip,bp2,imp->iso_ftype );
- cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype );
- break;
- case ISO_FTYPE_RRIP:
- result = cd9660_rrip_analyze(isodir,ip,imp);
- break;
- }
- if (bp2)
- brelse(bp2);
- if (bp)
- brelse(bp);
-
- /*
- * Initialize the associated vnode
- */
- vp->v_type = IFTOVT(ip->inode.iso_mode);
-
- if ( vp->v_type == VFIFO ) {
- vp->v_op = cd9660_fifoop_p;
- } else if ( vp->v_type == VCHR || vp->v_type == VBLK ) {
- /*
- * if device, look at device number table for translation
- */
-#ifdef ISODEVMAP
- if (dp = iso_dmap(dev,ino,0))
- ip->inode.iso_rdev = dp->d_dev;
-#endif
- vp->v_op = cd9660_specop_p;
- if ((nvp = checkalias(vp, ip->inode.iso_rdev, mntp))) {
- /*
- * Reinitialize aliased inode.
- */
- vp = nvp;
- iq = VTOI(vp);
- iq->i_vnode = vp;
- iq->i_flag = 0;
- ISO_ILOCK(iq);
- iq->i_dev = dev;
- iq->i_number = ino;
- iq->i_mnt = ip->i_mnt;
- bcopy(&ip->iso_extent,&iq->iso_extent,
- (char *)(ip + 1) - (char *)&ip->iso_extent);
- insque(iq, ih);
- /*
- * Discard unneeded vnode
- * (This introduces the need of INACTIVE modification)
- */
- ip->inode.iso_mode = 0;
- iso_iput(ip);
- ip = iq;
+ 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, p))
+ goto loop;
+ return (vp);
}
}
+ simple_unlock(&cd9660_ihash_slock);
+ return (NULL);
+}
- if (ip->iso_extent == imp->root_extent)
- vp->v_flag |= VROOT;
-
+/*
+ * Insert the inode into the hash table, and return it locked.
+ */
+void
+cd9660_ihashins(ip)
+ struct iso_node *ip;
+{
+ struct proc *p = curproc; /* XXX */
+ struct iso_node **ipp, *iq;
+
+ simple_lock(&cd9660_ihash_slock);
+ ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
+ if (iq = *ipp)
+ iq->i_prev = &ip->i_next;
+ ip->i_next = iq;
+ ip->i_prev = ipp;
*ipp = ip;
- return 0;
+ simple_unlock(&cd9660_ihash_slock);
+
+ lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
}
/*
- * Unlock and decrement the reference count of an inode structure.
+ * Remove the inode from the hash table.
*/
-int
-iso_iput(ip)
+void
+cd9660_ihashrem(ip)
register struct iso_node *ip;
{
-
- if ((ip->i_flag & ILOCKED) == 0)
- panic("iso_iput");
- ISO_IUNLOCK(ip);
- vrele(ITOV(ip));
- return (0);
+ register struct iso_node *iq;
+
+ simple_lock(&cd9660_ihash_slock);
+ if (iq = ip->i_next)
+ iq->i_prev = ip->i_prev;
+ *ip->i_prev = iq;
+#ifdef DIAGNOSTIC
+ ip->i_next = NULL;
+ ip->i_prev = NULL;
+#endif
+ simple_unlock(&cd9660_ihash_slock);
}
/*
@@ -361,9 +222,11 @@ int
cd9660_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
register struct iso_node *ip = VTOI(vp);
int error = 0;
@@ -371,12 +234,13 @@ cd9660_inactive(ap)
vprint("cd9660_inactive: pushing active", vp);
ip->i_flag = 0;
+ VOP_UNLOCK(vp, 0, p);
/*
* 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;
}
@@ -387,6 +251,7 @@ int
cd9660_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
@@ -397,9 +262,7 @@ cd9660_reclaim(ap)
/*
* Remove the inode from its hash chain.
*/
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
+ cd9660_ihashrem(ip);
/*
* Purge old data structures associated with the inode.
*/
@@ -410,46 +273,6 @@ cd9660_reclaim(ap)
}
FREE(vp->v_data, M_ISOFSNODE);
vp->v_data = NULL;
- return 0;
-}
-
-/*
- * Lock an inode. If its already locked, set the WANT bit and sleep.
- */
-int
-iso_ilock(ip)
- register struct iso_node *ip;
-{
-
- while (ip->i_flag & ILOCKED) {
- ip->i_flag |= IWANT;
- if (ip->i_spare0 == curproc->p_pid)
- panic("locking against myself");
- ip->i_spare1 = curproc->p_pid;
- (void) tsleep((caddr_t)ip, PINOD, "isoilk", 0);
- }
- ip->i_spare1 = 0;
- ip->i_spare0 = curproc->p_pid;
- ip->i_flag |= ILOCKED;
- return (0);
-}
-
-/*
- * Unlock an inode. If WANT bit is on, wakeup.
- */
-int
-iso_iunlock(ip)
- register struct iso_node *ip;
-{
-
- if ((ip->i_flag & ILOCKED) == 0)
- vprint("iso_iunlock: unlocked inode", ITOV(ip));
- ip->i_spare0 = 0;
- ip->i_flag &= ~ILOCKED;
- if (ip->i_flag&IWANT) {
- ip->i_flag &= ~IWANT;
- wakeup((caddr_t)ip);
- }
return (0);
}
@@ -457,7 +280,7 @@ iso_iunlock(ip)
* File attributes
*/
void
-cd9660_defattr(isodir,inop,bp,ftype)
+cd9660_defattr(isodir, inop, bp, ftype)
struct iso_directory_record *isodir;
struct iso_node *inop;
struct buf *bp;
@@ -482,14 +305,15 @@ cd9660_defattr(isodir,inop,bp,ftype)
inop->inode.iso_links = 1;
}
if (!bp
- && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
- iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
bp = bp2;
}
if (bp) {
- ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
-
+ ap = (struct iso_extended_attributes *)bp->b_data;
+
if (isonum_711(ap->version) == 1) {
if (!(ap->perm[0]&0x40))
inop->inode.iso_mode |= VEXEC >> 6;
@@ -533,16 +357,16 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
int off;
if (!bp
- && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
- iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
bp = bp2;
}
if (bp) {
- ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
-
- if (ftype != ISO_FTYPE_HIGH_SIERRA
- && isonum_711(ap->version) == 1) {
+ ap = (struct iso_extended_attributes *)bp->b_data;
+
+ if (isonum_711(ap->version) == 1) {
if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
@@ -563,9 +387,9 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
int
cd9660_tstamp_conv7(pi,pu,ftype)
-char *pi;
-struct timespec *pu;
-enum ISO_FTYPE ftype;
+ u_char *pi;
+ struct timespec *pu;
+ enum ISO_FTYPE ftype;
{
int crtime, days;
int y, m, d, hour, minute, second, tz;
@@ -609,13 +433,13 @@ enum ISO_FTYPE ftype;
return 1;
}
-static unsigned
+static u_int
cd9660_chars2ui(begin,len)
- unsigned char *begin;
+ u_char *begin;
int len;
{
- unsigned rc;
-
+ u_int rc;
+
for (rc = 0; --len >= 0;) {
rc *= 10;
rc += *begin++ - '0';
@@ -625,12 +449,12 @@ cd9660_chars2ui(begin,len)
int
cd9660_tstamp_conv17(pi,pu)
- unsigned char *pi;
+ u_char *pi;
struct timespec *pu;
{
- unsigned char buf[7];
-
- /* year:"0001"-"9999" -> -1900 */
+ u_char buf[7];
+
+ /* year:"0001"-"9999" -> -1900 */
buf[0] = cd9660_chars2ui(pi,4) - 1900;
/* month: " 1"-"12" -> 1 - 12 */
@@ -654,12 +478,14 @@ cd9660_tstamp_conv17(pi,pu)
return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT);
}
-void
-isodirino(inump,isodir,imp)
- ino_t *inump;
+ino_t
+isodirino(isodir, imp)
struct iso_directory_record *isodir;
struct iso_mnt *imp;
{
- *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
- * imp->logical_block_size;
+ ino_t ino;
+
+ ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
+ << imp->im_bshift;
+ return (ino);
}
diff --git a/sys/fs/cd9660/cd9660_node.h b/sys/fs/cd9660/cd9660_node.h
index 992f9cb..de538fb 100644
--- a/sys/fs/cd9660/cd9660_node.h
+++ b/sys/fs/cd9660/cd9660_node.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_node.h 8.2 (Berkeley) 1/23/94
+ * @(#)cd9660_node.h 8.6 (Berkeley) 5/14/95
* $FreeBSD$
*/
@@ -59,22 +59,20 @@ typedef struct {
dev_t iso_rdev; /* Major/Minor number for special */
} ISO_RRIP_INODE;
-#ifdef ISODEVMAP
+#ifdef ISODEVMAP
/*
* FOr device# (major,minor) translation table
*/
struct iso_dnode {
- struct iso_dnode *d_chain[2]; /* hash chain, MUST be first */
+ struct iso_dnode *d_next, **d_prev; /* hash chain */
dev_t i_dev; /* device where dnode resides */
ino_t i_number; /* the identity of the inode */
dev_t d_dev; /* device # for translation */
};
-#define d_forw d_chain[0]
-#define d_back d_chain[1]
#endif
struct iso_node {
- struct iso_node *i_chain[2]; /* hash chain, MUST be first */
+ struct iso_node *i_next, **i_prev; /* hash chain */
struct vnode *i_vnode; /* vnode associated with this inode */
struct vnode *i_devvp; /* vnode for block I/O */
u_long i_flag; /* see below */
@@ -87,8 +85,7 @@ struct iso_node {
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 */
- long i_spare0;
- long i_spare1;
+ struct lock i_lock; /* node lock */
long iso_extent; /* extent of file */
long i_size;
@@ -101,19 +98,11 @@ struct iso_node {
#define i_back i_chain[1]
/* flags */
-#define ILOCKED 0x0001 /* inode is locked */
-#define IWANT 0x0002 /* some process waiting on lock */
-#define IACC 0x0020 /* inode access time to be updated */
+#define IN_ACCESS 0x0020 /* inode access time to be updated */
#define VTOI(vp) ((struct iso_node *)(vp)->v_data)
#define ITOV(ip) ((ip)->i_vnode)
-#define ISO_ILOCK(ip) iso_ilock(ip)
-#define ISO_IUNLOCK(ip) iso_iunlock(ip)
-
-extern vop_t **cd9660_fifoop_p;
-extern vop_t **cd9660_specop_p;
-
/*
* Prototypes for ISOFS vnode operations
*/
@@ -121,14 +110,19 @@ int cd9660_lookup __P((struct vop_lookup_args *));
int cd9660_inactive __P((struct vop_inactive_args *));
int cd9660_reclaim __P((struct vop_reclaim_args *));
int cd9660_bmap __P((struct vop_bmap_args *));
+int cd9660_pathconf __P((struct vop_pathconf_args *));
+int cd9660_blkatoff __P((struct vop_blkatoff_args *));
+#define cd9660_revoke vop_revoke
+
void cd9660_defattr __P((struct iso_directory_record *,
struct iso_node *, struct buf *, enum ISO_FTYPE));
void cd9660_deftstamp __P((struct iso_directory_record *,
struct iso_node *, struct buf *, enum ISO_FTYPE));
-int cd9660_tstamp_conv7 __P((char *pi, struct timespec *pu, enum ISO_FTYPE));
-int cd9660_tstamp_conv17 __P((unsigned char *pi, struct timespec *pu));
-void isodirino __P((ino_t *inump, struct iso_directory_record *isodir,
- struct iso_mnt *imp));
+struct vnode *cd9660_ihashget __P((dev_t, ino_t));
+void cd9660_ihashins __P((struct iso_node *));
+void cd9660_ihashrem __P((struct iso_node *));
+int cd9660_tstamp_conv7 __P((u_char *, struct timespec *, enum ISO_FTYPE));
+int cd9660_tstamp_conv17 __P((u_char *, struct timespec *));
#ifdef ISODEVMAP
struct iso_dnode *iso_dmap __P((dev_t, ino_t, int));
void iso_dunmap __P((dev_t));
diff --git a/sys/fs/cd9660/cd9660_rrip.c b/sys/fs/cd9660/cd9660_rrip.c
index 44d52eb..521094f 100644
--- a/sys/fs/cd9660/cd9660_rrip.c
+++ b/sys/fs/cd9660/cd9660_rrip.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_rrip.c 8.2 (Berkeley) 1/23/94
+ * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94
* $FreeBSD$
*/
@@ -104,10 +104,10 @@ cd9660_rrip_attr(p,ana)
ISO_RRIP_ATTR *p;
ISO_RRIP_ANALYZE *ana;
{
- ana->inop->inode.iso_mode = isonum_731(p->mode_l);
- ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
- ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
- ana->inop->inode.iso_links = isonum_731(p->links_l);
+ ana->inop->inode.iso_mode = isonum_733(p->mode);
+ ana->inop->inode.iso_uid = isonum_733(p->uid);
+ ana->inop->inode.iso_gid = isonum_733(p->gid);
+ ana->inop->inode.iso_links = isonum_733(p->links);
ana->fields &= ~ISO_SUSP_ATTR;
return ISO_SUSP_ATTR;
}
@@ -352,8 +352,8 @@ cd9660_rrip_tstamp(p,ana)
ISO_RRIP_TSTAMP *p;
ISO_RRIP_ANALYZE *ana;
{
- unsigned char *ptime;
-
+ u_char *ptime;
+
ptime = p->time;
/* Check a format of time stamp (7bytes/17bytes) */
@@ -367,7 +367,7 @@ cd9660_rrip_tstamp(p,ana)
ptime += 7;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
-
+
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime,
ISO_FTYPE_RRIP);
@@ -390,7 +390,7 @@ cd9660_rrip_tstamp(p,ana)
ptime += 17;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
-
+
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
ptime += 17;
@@ -423,16 +423,15 @@ cd9660_rrip_device(p,ana)
ISO_RRIP_DEVICE *p;
ISO_RRIP_ANALYZE *ana;
{
- unsigned high, low;
-
- high = isonum_733(p->dev_t_high_l);
- low = isonum_733(p->dev_t_low_l);
-
- if ( high == 0 ) {
- ana->inop->inode.iso_rdev = makedev( major(low), minor(low) );
- } else {
- ana->inop->inode.iso_rdev = makedev( high, minor(low) );
- }
+ u_int high, low;
+
+ high = isonum_733(p->dev_t_high);
+ low = isonum_733(p->dev_t_low);
+
+ if (high == 0)
+ ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
+ else
+ ana->inop->inode.iso_rdev = makedev(high, minor(low));
ana->fields &= ~ISO_SUSP_DEVICE;
return ISO_SUSP_DEVICE;
}
@@ -475,8 +474,6 @@ cd9660_rrip_stop(p,ana)
ISO_SUSP_HEADER *p;
ISO_RRIP_ANALYZE *ana;
{
- /* stop analyzing */
- ana->fields = 0;
return ISO_SUSP_STOP;
}
@@ -545,22 +542,30 @@ cd9660_rrip_loop(isodir,ana,table)
if (!ana->fields)
break;
}
+ if (result&ISO_SUSP_STOP) {
+ result &= ~ISO_SUSP_STOP;
+ break;
+ }
+ /* plausibility check */
+ if (isonum_711(phead->length) < sizeof(*phead))
+ break;
/*
* move to next SUSP
* Hopefully this works with newer versions, too
*/
phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
}
-
- if ( ana->fields && ana->iso_ce_len ) {
+
+ if (ana->fields && ana->iso_ce_len) {
if (ana->iso_ce_blk >= ana->imp->volume_space_size
|| ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
|| bread(ana->imp->im_devvp,
- iso_lblktodaddr(ana->imp, ana->iso_ce_blk),
- ana->imp->logical_block_size,NOCRED,&bp))
+ ana->iso_ce_blk <<
+ (ana->imp->im_bshift - DEV_BSHIFT),
+ ana->imp->logical_block_size, NOCRED, &bp))
/* what to do now? */
break;
- phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off);
+ phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
} else
break;
@@ -569,7 +574,7 @@ cd9660_rrip_loop(isodir,ana,table)
brelse(bp);
/*
* If we don't find the Basic SUSP stuffs, just set default value
- * ( attribute/time stamp )
+ * (attribute/time stamp)
*/
for (ptable = table; ptable->func2; ptable++)
if (!(ptable->result&result))
@@ -579,6 +584,9 @@ cd9660_rrip_loop(isodir,ana,table)
}
/*
+ * Get Attributes.
+ */
+/*
* XXX the casts are bogus but will do for now.
*/
#define BC (rrt_func_t *)
@@ -607,10 +615,8 @@ cd9660_rrip_analyze(isodir,inop,imp)
return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
}
-/*
- * Get Alternate Name from 'AL' record
- * If either no AL record or 0 length,
- * it will be return the translated ISO9660 name,
+/*
+ * Get Alternate Name.
*/
static RRIP_TABLE rrip_table_getname[] = {
{ "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME },
@@ -654,10 +660,8 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
return cd9660_rrip_loop(isodir,&analyze,tab);
}
-/*
- * Get Symbolic Name from 'SL' record
- *
- * Note: isodir should contains SL record!
+/*
+ * Get Symbolic Link.
*/
static RRIP_TABLE rrip_table_getsymname[] = {
{ "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK },
@@ -696,7 +700,7 @@ static RRIP_TABLE rrip_table_extref[] = {
/*
* Check for Rock Ridge Extension and return offset of its fields.
- * Note: We require the ER field.
+ * Note: We insist on the ER field.
*/
int
cd9660_rrip_offset(isodir,imp)
diff --git a/sys/fs/cd9660/cd9660_rrip.h b/sys/fs/cd9660/cd9660_rrip.h
index e65fb3b..cacee39 100644
--- a/sys/fs/cd9660/cd9660_rrip.h
+++ b/sys/fs/cd9660/cd9660_rrip.h
@@ -35,36 +35,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_rrip.h 8.1 (Berkeley) 1/21/94
- * $FreeBSD$
+ * @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94
+ * $Id: cd9660_rrip.h,v 1.3.2000.1 1996/09/30 12:46:48 dfr Exp $
*/
-
+
typedef struct {
- char type [ISODCL ( 0, 1)];
- unsigned char length [ISODCL ( 2, 2)]; /* 711 */
- unsigned char version [ISODCL ( 3, 3)];
+ char type [ISODCL ( 0, 1)];
+ u_char length [ISODCL ( 2, 2)]; /* 711 */
+ u_char version [ISODCL ( 3, 3)];
} ISO_SUSP_HEADER;
-
+
typedef struct {
ISO_SUSP_HEADER h;
- char mode_l [ISODCL ( 4, 7)]; /* 731 */
- char mode_m [ISODCL ( 8, 11)]; /* 732 */
- char links_l [ISODCL ( 12, 15)]; /* 731 */
- char links_m [ISODCL ( 16, 19)]; /* 732 */
- char uid_l [ISODCL ( 20, 23)]; /* 731 */
- char uid_m [ISODCL ( 24, 27)]; /* 732 */
- char gid_l [ISODCL ( 28, 31)]; /* 731 */
- char gid_m [ISODCL ( 32, 35)]; /* 732 */
+ char mode [ISODCL ( 4, 11)]; /* 733 */
+ char links [ISODCL ( 12, 19)]; /* 733 */
+ char uid [ISODCL ( 20, 27)]; /* 733 */
+ char gid [ISODCL ( 28, 35)]; /* 733 */
} ISO_RRIP_ATTR;
-
+
typedef struct {
ISO_SUSP_HEADER h;
- char dev_t_high_l [ISODCL ( 4, 7)]; /* 731 */
- char dev_t_high_m [ISODCL ( 8, 11)]; /* 732 */
- char dev_t_low_l [ISODCL ( 12, 15)]; /* 731 */
- char dev_t_low_m [ISODCL ( 16, 19)]; /* 732 */
+ char dev_t_high [ISODCL ( 4, 11)]; /* 733 */
+ char dev_t_low [ISODCL ( 12, 19)]; /* 733 */
} ISO_RRIP_DEVICE;
-
+
#define ISO_SUSP_CFLAG_CONTINUE 0x01
#define ISO_SUSP_CFLAG_CURRENT 0x02
#define ISO_SUSP_CFLAG_PARENT 0x04
@@ -73,9 +67,9 @@ typedef struct {
#define ISO_SUSP_CFLAG_HOST 0x20
typedef struct {
- u_char cflag [ISODCL ( 1, 1)];
- u_char clen [ISODCL ( 2, 2)];
- u_char name [0];
+ u_char cflag [ISODCL ( 1, 1)];
+ u_char clen [ISODCL ( 2, 2)];
+ u_char name [1]; /* XXX */
} ISO_RRIP_SLINK_COMPONENT;
#define ISO_RRIP_SLSIZ 2
@@ -116,13 +110,13 @@ typedef struct {
typedef struct {
ISO_SUSP_HEADER h;
- unsigned char flags [ISODCL ( 4, 4)];
- unsigned char time [ISODCL ( 5, 5)];
+ u_char flags [ISODCL ( 4, 4)];
+ u_char time [ISODCL ( 5, 5)];
} ISO_RRIP_TSTAMP;
typedef struct {
ISO_SUSP_HEADER h;
- unsigned char flags [ISODCL ( 4, 4)];
+ u_char flags [ISODCL ( 4, 4)];
} ISO_RRIP_IDFLAG;
typedef struct {
diff --git a/sys/fs/cd9660/cd9660_util.c b/sys/fs/cd9660/cd9660_util.c
index 786d4fd..151d1c3 100644
--- a/sys/fs/cd9660/cd9660_util.c
+++ b/sys/fs/cd9660/cd9660_util.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_util.c 8.1 (Berkeley) 1/21/94
+ * @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94
* $FreeBSD$
*/
@@ -58,104 +58,14 @@
#include <isofs/cd9660/iso.h>
-#ifdef __notanymore__
-int
-isonum_711 (p)
-unsigned char *p;
-{
- return (*p);
-}
-
-int
-isonum_712 (p)
-signed char *p;
-{
- return (*p);
-}
-
-int
-isonum_721 (p)
-unsigned char *p;
-{
- /* little endian short */
-#if BYTE_ORDER != LITTLE_ENDIAN
- printf ("isonum_721 called on non little-endian machine!\n");
-#endif
-
- return *(short *)p;
-}
-
-int
-isonum_722 (p)
-unsigned char *p;
-{
- /* big endian short */
-#if BYTE_ORDER != BIG_ENDIAN
- printf ("isonum_722 called on non big-endian machine!\n");
-#endif
-
- return *(short *)p;
-}
-
-int
-isonum_723 (p)
-unsigned char *p;
-{
-#if BYTE_ORDER == BIG_ENDIAN
- return isonum_722 (p + 2);
-#elif BYTE_ORDER == LITTLE_ENDIAN
- return isonum_721 (p);
-#else
- printf ("isonum_723 unsupported byte order!\n");
- return 0;
-#endif
-}
-
-int
-isonum_731 (p)
-unsigned char *p;
-{
- /* little endian long */
-#if BYTE_ORDER != LITTLE_ENDIAN
- printf ("isonum_731 called on non little-endian machine!\n");
-#endif
-
- return *(long *)p;
-}
-
-int
-isonum_732 (p)
-unsigned char *p;
-{
- /* big endian long */
-#if BYTE_ORDER != BIG_ENDIAN
- printf ("isonum_732 called on non big-endian machine!\n");
-#endif
-
- return *(long *)p;
-}
-
-int
-isonum_733 (p)
-unsigned char *p;
-{
-#if BYTE_ORDER == BIG_ENDIAN
- return isonum_732 (p + 4);
-#elif BYTE_ORDER == LITTLE_ENDIAN
- return isonum_731 (p);
-#else
- printf ("isonum_733 unsupported byte order!\n");
- return 0;
-#endif
-}
-#endif /* __notanymore__ */
-
/*
* translate and compare a filename
* Note: Version number plus ';' may be omitted.
*/
int
-isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
+isofncmp(fn, fnlen, isofn, isolen)
+ u_char *fn, *isofn;
+ int fnlen, isolen;
{
int i, j;
unsigned char c;
@@ -211,9 +121,12 @@ isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
* translate a filename
*/
void
-isofntrans(unsigned char *infn,int infnlen,
- unsigned char *outfn,unsigned short *outfnlen,
- int original,int assoc)
+isofntrans(infn, infnlen, outfn, outfnlen, original, assoc)
+ u_char *infn, *outfn;
+ int infnlen;
+ u_short *outfnlen;
+ int original;
+ int assoc;
{
int fnidx = 0;
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 752a7b4..15eade4 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_vfsops.c 8.3 (Berkeley) 1/31/94
+ * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $FreeBSD$
*/
@@ -52,10 +52,12 @@
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
+#include <sys/stat.h>
#include <isofs/cd9660/iso.h>
-#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/iso_rrip.h>
+#include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
static int cd9660_mount __P((struct mount *,
@@ -84,17 +86,14 @@ static struct vfsops cd9660_vfsops = {
cd9660_vget,
cd9660_fhtovp,
cd9660_vptofh,
- cd9660_init,
+ cd9660_init
};
VFS_SET(cd9660_vfsops, cd9660, MOUNT_CD9660, VFCF_READONLY);
/*
* Called by vfs_mountroot when iso is going to be mounted as root.
- *
- * Name is updated by mount(8) after booting.
*/
-#define ROOTNAME "root_device"
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
struct proc *p, struct iso_args *argp));
@@ -102,55 +101,38 @@ static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
int
cd9660_mountroot()
{
- register struct mount *mp;
+ struct mount *mp;
struct proc *p = curproc; /* XXX */
- struct iso_mnt *imp;
- u_int size;
- int error;
struct iso_args args;
-
+ int error;
+
/*
* Get vnode for rootdev.
*/
- if (bdevvp(rootdev, &rootvp))
- panic("cd9660_mountroot: can't setup bdevvp for rootdev");
-
- 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;
- args.flags = ISOFSMNT_ROOT;
- if ((error = iso_mountfs(rootvp, mp, p, &args))) {
- free(mp, M_MOUNT);
+ if ((error = bdevvp(swapdev, &swapdev_vp)) ||
+ (error = bdevvp(rootdev, &rootvp))) {
+ printf("cd9660_mountroot: can't setup bdevvp's");
return (error);
}
- if ((error = vfs_lock(mp))) {
- (void)cd9660_unmount(mp, 0, p);
+
+ if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
+ return (error);
+ args.flags = ISOFSMNT_ROOT;
+ if (error = iso_mountfs(rootvp, mp, p, &args)) {
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
free(mp, M_MOUNT);
return (error);
}
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
- mp->mnt_flag |= MNT_ROOTFS;
- mp->mnt_vnodecovered = NULLVP;
- imp = VFSTOISOFS(mp);
- bzero(imp->im_fsmnt, sizeof(imp->im_fsmnt));
- imp->im_fsmnt[0] = '/';
- bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
- MNAMELEN);
- (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
- &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
- (void) cd9660_statfs(mp, &mp->mnt_stat, p);
- vfs_unlock(mp);
+ simple_unlock(&mountlist_slock);
+ (void)cd9660_statfs(mp, &mp->mnt_stat, p);
+ vfs_unbusy(mp, p);
return (0);
}
/*
- * Flag to allow forcible unmounting.
- */
-static int iso_doforce = 1;
-
-/*
* VFS Operations.
*
* mount system call
@@ -214,10 +196,8 @@ cd9660_mount(mp, path, data, ndp, p)
return error;
}
imp = VFSTOISOFS(mp);
- (void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size);
- bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size);
- bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
- MNAMELEN);
+ (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
+ bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
&size);
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
@@ -277,11 +257,11 @@ iso_mountfs(devvp, mp, p, argp)
iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
- if ((error = bread (devvp, btodb(iso_blknum * iso_bsize),
- iso_bsize, NOCRED, &bp)))
+ if (error = bread(devvp, iso_blknum * btodb(iso_bsize),
+ iso_bsize, NOCRED, &bp))
goto out;
-
- vdp = (struct iso_volume_descriptor *)bp->b_un.b_addr;
+
+ vdp = (struct iso_volume_descriptor *)bp->b_data;
if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
if (bcmp (vdp->id_sierra, ISO_SIERRA_ID,
sizeof vdp->id) != 0) {
@@ -347,7 +327,7 @@ iso_mountfs(devvp, mp, p, argp)
mp->mnt_data = (qaddr_t)isomp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
- mp->mnt_stat.f_fsid.val[1] = MOUNT_CD9660;
+ mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
isomp->im_mountp = mp;
@@ -358,14 +338,14 @@ iso_mountfs(devvp, mp, p, argp)
/* Check the Rock Ridge Extention support */
if (!(argp->flags & ISOFSMNT_NORRIP)) {
- if ((error = bread (isomp->im_devvp,
- (isomp->root_extent + isonum_711(rootp->ext_attr_length))
- * isomp->logical_block_size / DEV_BSIZE,
- isomp->logical_block_size,NOCRED,&bp)))
+ if (error = bread(isomp->im_devvp,
+ (isomp->root_extent + isonum_711(rootp->ext_attr_length)) <<
+ (isomp->im_bshift - DEV_BSHIFT),
+ isomp->logical_block_size, NOCRED, &bp))
goto out;
-
- rootp = (struct iso_directory_record *)bp->b_un.b_addr;
-
+
+ rootp = (struct iso_directory_record *)bp->b_data;
+
if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
argp->flags |= ISOFSMNT_NORRIP;
} else {
@@ -436,12 +416,9 @@ cd9660_unmount(mp, mntflags, p)
{
register struct iso_mnt *isomp;
int error, flags = 0;
-
- if (mntflags & MNT_FORCE) {
- if (!iso_doforce)
- return (EINVAL);
+
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
#if 0
mntflushbuf(mp, 0);
if (mntinvalbuf(mp))
@@ -474,33 +451,17 @@ cd9660_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- register struct iso_node *ip;
- struct iso_node tip, *nip;
- struct vnode tvp;
- int error;
- struct iso_mnt *imp = VFSTOISOFS (mp);
- struct iso_directory_record *dp;
-
- tvp.v_mount = mp;
- tvp.v_data = &tip;
- ip = VTOI(&tvp);
- ip->i_vnode = &tvp;
- ip->i_dev = imp->im_dev;
- ip->i_diroff = 0;
- dp = (struct iso_directory_record *)imp->root;
- isodirino(&ip->i_number,dp,imp);
-
+ struct iso_mnt *imp = VFSTOISOFS(mp);
+ struct iso_directory_record *dp =
+ (struct iso_directory_record *)imp->root;
+ ino_t ino = isodirino(dp, imp);
+
/*
* With RRIP we must use the `.' entry of the root directory.
- * Simply tell iget, that it's a relocated directory.
+ * Simply tell vget, that it's a relocated directory.
*/
- error = iso_iget(ip,ip->i_number,
- imp->iso_ftype == ISO_FTYPE_RRIP,
- &nip,dp);
- if (error)
- return error;
- *vpp = ITOV(nip);
- return 0;
+ return (cd9660_vget_internal(mp, ino, vpp,
+ imp->iso_ftype == ISO_FTYPE_RRIP, dp));
}
/*
@@ -541,10 +502,8 @@ cd9660_statfs(mp, sbp, p)
sbp->f_files = 0; /* total files */
sbp->f_ffree = 0; /* free file nodes */
if (sbp != &mp->mnt_stat) {
- bcopy((caddr_t)mp->mnt_stat.f_mntonname,
- (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
- bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
- (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
+ bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
+ bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
/* Use the first spare for flags: */
sbp->f_spare[0] = isomp->im_flags;
@@ -563,21 +522,6 @@ cd9660_sync(mp, waitfor, cred, p)
}
/*
- * Flat namespace lookup.
- * Currently unsupported.
- */
-/* ARGSUSED */
-static int
-cd9660_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-/*
* File handle to vnode
*
* Have to be really careful about stale file handles:
@@ -604,92 +548,262 @@ cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
int *exflagsp;
struct ucred **credanonp;
{
- struct vnode tvp;
- int error;
- int lbn, off;
- struct ifid *ifhp;
- struct iso_mnt *imp;
- struct buf *bp;
- struct iso_directory_record *dirp;
- struct iso_node tip, *ip, *nip;
- struct netcred *np;
-
- imp = VFSTOISOFS (mp);
- ifhp = (struct ifid *)fhp;
-
+ struct ifid *ifhp = (struct ifid *)fhp;
+ register struct iso_node *ip;
+ register struct netcred *np;
+ register struct iso_mnt *imp = VFSTOISOFS(mp);
+ struct vnode *nvp;
+ int error;
+
#ifdef ISOFS_DBG
printf("fhtovp: ino %d, start %ld\n",
ifhp->ifid_ino, ifhp->ifid_start);
#endif
-
+
+ /*
+ * Get the export permission structure for this <mp, client> tuple.
+ */
np = vfs_export_lookup(mp, &imp->im_export, nam);
if (np == NULL)
return (EACCES);
- lbn = iso_lblkno(imp, ifhp->ifid_ino);
- if (lbn >= imp->volume_space_size) {
- printf("fhtovp: lbn exceed volume space %d\n", lbn);
- return (ESTALE);
+ if (error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) {
+ *vpp = NULLVP;
+ return (error);
}
-
- off = iso_blkoff(imp, ifhp->ifid_ino);
- if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
- printf("fhtovp: crosses block boundary %d\n",
- off + ISO_DIRECTORY_RECORD_SIZE);
+ ip = VTOI(nvp);
+ if (ip->inode.iso_mode == 0) {
+ vput(nvp);
+ *vpp = NULLVP;
return (ESTALE);
}
+ *vpp = nvp;
+ *exflagsp = np->netc_exflags;
+ *credanonp = &np->netc_anon;
+ return (0);
+}
- error = bread(imp->im_devvp, btodb(lbn * imp->logical_block_size),
- imp->logical_block_size, NOCRED, &bp);
- if (error) {
- printf("fhtovp: bread error %d\n",error);
- brelse(bp);
+int
+cd9660_vget(mp, ino, vpp)
+ struct mount *mp;
+ ino_t ino;
+ struct vnode **vpp;
+{
+
+ /*
+ * XXXX
+ * It would be nice if we didn't always set the `relocated' flag
+ * and force the extra read, but I don't want to think about fixing
+ * that right now.
+ */
+ return (cd9660_vget_internal(mp, ino, vpp,
+#if 0
+ VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
+#else
+ 0,
+#endif
+ (struct iso_directory_record *)0));
+}
+
+int
+cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
+ struct mount *mp;
+ ino_t ino;
+ struct vnode **vpp;
+ int relocated;
+ struct iso_directory_record *isodir;
+{
+ struct iso_mnt *imp;
+ struct iso_node *ip;
+ struct buf *bp;
+ struct vnode *vp, *nvp;
+ dev_t dev;
+ int error;
+
+ imp = VFSTOISOFS(mp);
+ dev = imp->im_dev;
+ if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
+ return (0);
+
+ /* Allocate a new vnode/iso_node. */
+ if (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) {
+ *vpp = NULLVP;
return (error);
}
+ 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;
+ ip->i_number = ino;
- dirp = (struct iso_directory_record *)(bp->b_un.b_addr + off);
- if (off + isonum_711(dirp->length) > imp->logical_block_size) {
- brelse(bp);
- printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
- off+isonum_711(dirp->length), off,
- isonum_711(dirp->length));
- return (ESTALE);
+ /*
+ * Put it onto its hash chain and lock it so that other requests for
+ * this inode will block if they arrive while we are sleeping waiting
+ * for old data structures to be purged or for the contents of the
+ * disk portion of this inode to be read.
+ */
+ cd9660_ihashins(ip);
+
+ if (isodir == 0) {
+ int lbn, off;
+
+ lbn = lblkno(imp, ino);
+ if (lbn >= imp->volume_space_size) {
+ vput(vp);
+ printf("fhtovp: lbn exceed volume space %d\n", lbn);
+ return (ESTALE);
+ }
+
+ off = blkoff(imp, ino);
+ if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
+ vput(vp);
+ printf("fhtovp: crosses block boundary %d\n",
+ off + ISO_DIRECTORY_RECORD_SIZE);
+ return (ESTALE);
+ }
+
+ error = bread(imp->im_devvp,
+ lbn << (imp->im_bshift - DEV_BSHIFT),
+ imp->logical_block_size, NOCRED, &bp);
+ if (error) {
+ vput(vp);
+ brelse(bp);
+ printf("fhtovp: bread error %d\n",error);
+ return (error);
+ }
+ isodir = (struct iso_directory_record *)(bp->b_data + off);
+
+ if (off + isonum_711(isodir->length) >
+ imp->logical_block_size) {
+ vput(vp);
+ if (bp != 0)
+ brelse(bp);
+ printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
+ off +isonum_711(isodir->length), off,
+ isonum_711(isodir->length));
+ return (ESTALE);
+ }
+
+#if 0
+ if (isonum_733(isodir->extent) +
+ isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
+ if (bp != 0)
+ brelse(bp);
+ printf("fhtovp: file start miss %d vs %d\n",
+ isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
+ ifhp->ifid_start);
+ return (ESTALE);
+ }
+#endif
+ } else
+ bp = 0;
+
+ ip->i_mnt = imp;
+ ip->i_devvp = imp->im_devvp;
+ VREF(ip->i_devvp);
+
+ if (relocated) {
+ /*
+ * On relocated directories we must
+ * read the `.' entry out of a dir.
+ */
+ ip->iso_start = ino >> imp->im_bshift;
+ if (bp != 0)
+ brelse(bp);
+ if (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) {
+ vput(vp);
+ return (error);
+ }
+ isodir = (struct iso_directory_record *)bp->b_data;
}
- if (isonum_733(dirp->extent) + isonum_711(dirp->ext_attr_length) !=
- ifhp->ifid_start) {
- brelse(bp);
- printf("fhtovp: file start miss %d vs %ld\n",
- isonum_733(dirp->extent)+isonum_711(dirp->ext_attr_length),
- ifhp->ifid_start);
- return (ESTALE);
+ ip->iso_extent = isonum_733(isodir->extent);
+ ip->i_size = isonum_733(isodir->size);
+ ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
+
+ /*
+ * Setup time stamp, attribute
+ */
+ vp->v_type = VNON;
+ switch (imp->iso_ftype) {
+ default: /* ISO_FTYPE_9660 */
+ {
+ struct buf *bp2;
+ int off;
+ if ((imp->im_flags & ISOFSMNT_EXTATT)
+ && (off = isonum_711(isodir->ext_attr_length)))
+ VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
+ else
+ bp2 = NULL;
+ cd9660_defattr(isodir, ip, bp2, ISO_FTYPE_9660);
+ cd9660_deftstamp(isodir, ip, bp2, ISO_FTYPE_9660);
+ if (bp2)
+ brelse(bp2);
+ break;
+ }
+ case ISO_FTYPE_RRIP:
+ cd9660_rrip_analyze(isodir, ip, imp);
+ break;
}
- brelse(bp);
- ip = &tip;
- tvp.v_mount = mp;
- tvp.v_data = ip;
- ip->i_vnode = &tvp;
- ip->i_dev = imp->im_dev;
- if ((error = iso_iget(ip, ifhp->ifid_ino, 0, &nip, dirp))) {
- *vpp = NULLVP;
- printf("fhtovp: failed to get inode\n");
- return (error);
+ if (bp != 0)
+ brelse(bp);
+
+ /*
+ * Initialize the associated vnode
+ */
+ switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
+ case VFIFO:
+#ifdef FIFO
+ vp->v_op = cd9660_fifoop_p;
+ break;
+#else
+ vput(vp);
+ return (EOPNOTSUPP);
+#endif /* FIFO */
+ case VCHR:
+ case VBLK:
+ /*
+ * if device, look at device number table for translation
+ */
+#ifdef ISODEVMAP
+ if (dp = iso_dmap(dev, ino, 0))
+ ip->inode.iso_rdev = dp->d_dev;
+#endif
+ vp->v_op = cd9660_specop_p;
+ if (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) {
+ /*
+ * Discard unneeded vnode, but save its iso_node.
+ * Note that the lock is carried over in the iso_node
+ * to the replacement vnode.
+ */
+ nvp->v_data = vp->v_data;
+ vp->v_data = NULL;
+ vp->v_op = spec_vnodeop_p;
+ vrele(vp);
+ vgone(vp);
+ /*
+ * Reinitialize aliased inode.
+ */
+ vp = nvp;
+ ip->i_vnode = vp;
+ }
+ break;
}
- ip = nip;
+
+ if (ip->iso_extent == imp->root_extent)
+ vp->v_flag |= VROOT;
+
/*
* XXX need generation number?
*/
- if (ip->inode.iso_mode == 0) {
- iso_iput(ip);
- *vpp = NULLVP;
- printf("fhtovp: inode mode == 0\n");
- return (ESTALE);
- }
- *vpp = ITOV(ip);
- *exflagsp = np->netc_exflags;
- *credanonp = &np->netc_anon;
- return 0;
+
+ *vpp = vp;
+ return (0);
}
/*
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index 88440eb..854d6b5 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_vnops.c 8.3 (Berkeley) 1/23/94
+ * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
* $FreeBSD$
*/
@@ -55,6 +55,7 @@
#include <miscfs/fifofs/fifo.h>
#include <sys/malloc.h>
#include <sys/dir.h>
+#include <sys/unistd.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
@@ -81,7 +82,6 @@ static int cd9660_lock __P((struct vop_lock_args *));
static int cd9660_unlock __P((struct vop_unlock_args *));
static int cd9660_strategy __P((struct vop_strategy_args *));
static int cd9660_print __P((struct vop_print_args *));
-static int cd9660_enotsupp __P((void));
static int cd9660_islocked __P((struct vop_islocked_args *));
#if 0
@@ -100,7 +100,7 @@ cd9660_mknod(ndp, vap, cred, p)
free(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
vput(ndp->ni_vp);
- return EINVAL;
+ return (EINVAL);
#else
register struct vnode *vp;
struct iso_node *ip;
@@ -116,7 +116,7 @@ cd9660_mknod(ndp, vap, cred, p)
free(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
vput(ndp->ni_vp);
- return EINVAL;
+ return (EINVAL);
}
dp = iso_dmap(ip->i_dev,ip->i_number,1);
@@ -144,7 +144,7 @@ cd9660_mknod(ndp, vap, cred, p)
/*
* Setattr call. Only allowed for block and character special devices.
*/
-static int
+int
cd9660_setattr(ap)
struct vop_setattr_args /* {
struct vnodeop_desc *a_desc;
@@ -175,7 +175,7 @@ cd9660_setattr(ap)
return (0);
}
}
- return (EOPNOTSUPP);
+ return (0);
}
/*
@@ -229,23 +229,65 @@ cd9660_access(ap)
struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
+ struct iso_node *ip = VTOI(vp);
+ struct ucred *cred = ap->a_cred;
+ mode_t mask, mode = ap->a_mode;
+ gid_t *gp;
+ int i;
+
/*
- * Disallow write attempts on read-only file systems;
- * unless the file is a socket, fifo, or a block or
- * character device resident on the file system.
+ * 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 (ap->a_vp->v_type) {
+ if (mode & VWRITE) {
+ switch (vp->v_type) {
case VDIR:
case VLNK:
case VREG:
- if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- break;
+ return (EROFS);
}
}
- return (0);
+ /* User id 0 always gets access. */
+ if (cred->cr_uid == 0)
+ return (0);
+
+ mask = 0;
+
+ /* Otherwise, check the owner. */
+ if (cred->cr_uid == ip->inode.iso_uid) {
+ if (mode & VEXEC)
+ mask |= S_IXUSR;
+ if (mode & VREAD)
+ mask |= S_IRUSR;
+ if (mode & VWRITE)
+ mask |= S_IWUSR;
+ return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
+ }
+
+ /* Otherwise, check the groups. */
+ for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
+ if (ip->inode.iso_gid == *gp) {
+ if (mode & VEXEC)
+ mask |= S_IXGRP;
+ if (mode & VREAD)
+ mask |= S_IRGRP;
+ if (mode & VWRITE)
+ mask |= S_IWGRP;
+ return ((ip->inode.iso_mode & mask) == mask ?
+ 0 : EACCES);
+ }
+
+ /* Otherwise, check everyone else. */
+ if (mode & VEXEC)
+ mask |= S_IXOTH;
+ if (mode & VREAD)
+ mask |= S_IROTH;
+ if (mode & VWRITE)
+ mask |= S_IWOTH;
+ return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
}
static int
@@ -275,6 +317,29 @@ cd9660_getattr(ap)
vap->va_rdev = ip->inode.iso_rdev;
vap->va_size = (u_quad_t) ip->i_size;
+ if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
+ struct vop_readlink_args rdlnk;
+ struct iovec aiov;
+ struct uio auio;
+ char *cp;
+
+ MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
+ aiov.iov_base = cp;
+ aiov.iov_len = MAXPATHLEN;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_procp = ap->a_p;
+ auio.uio_resid = MAXPATHLEN;
+ rdlnk.a_uio = &auio;
+ rdlnk.a_vp = ap->a_vp;
+ rdlnk.a_cred = ap->a_cred;
+ if (cd9660_readlink(&rdlnk) == 0)
+ vap->va_size = MAXPATHLEN - auio.uio_resid;
+ FREE(cp, M_TEMP);
+ }
vap->va_flags = 0;
vap->va_gen = 1;
vap->va_blocksize = ip->i_mnt->logical_block_size;
@@ -325,31 +390,31 @@ cd9660_read(ap)
return (0);
if (uio->uio_offset < 0)
return (EINVAL);
- ip->i_flag |= IACC;
+ ip->i_flag |= IN_ACCESS;
imp = ip->i_mnt;
do {
- lbn = iso_lblkno(imp, uio->uio_offset);
- on = iso_blkoff(imp, uio->uio_offset);
- n = min((unsigned)(imp->logical_block_size - on),
+ lbn = lblkno(imp, uio->uio_offset);
+ on = blkoff(imp, uio->uio_offset);
+ n = min((u_int)(imp->logical_block_size - on),
uio->uio_resid);
diff = (off_t)ip->i_size - uio->uio_offset;
if (diff <= 0)
return (0);
if (diff < n)
n = diff;
- size = iso_blksize(imp, ip, lbn);
+ size = blksize(imp, ip, lbn);
rablock = lbn + 1;
if (doclusterread) {
- if (iso_lblktosize(imp, rablock) <= ip->i_size)
- error = cluster_read(vp, ip->i_size,
+ if (lblktosize(imp, rablock) <= ip->i_size)
+ error = cluster_read(vp, (off_t)ip->i_size,
lbn, size, NOCRED, uio->uio_resid,
(ap->a_ioflag >> 16), &bp);
else
error = bread(vp, lbn, size, NOCRED, &bp);
} else {
if (vp->v_lastr + 1 == lbn &&
- iso_lblktosize(imp, rablock) < ip->i_size) {
- rasize = iso_blksize(imp, ip, rablock);
+ lblktosize(imp, rablock) < ip->i_size) {
+ rasize = blksize(imp, ip, rablock);
error = breadn(vp, lbn, size, &rablock,
&rasize, 1, NOCRED, &bp);
} else
@@ -362,7 +427,10 @@ cd9660_read(ap)
return (error);
}
- error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
+ error = uiomove(bp->b_data + on, (int)n, uio);
+ if (n + on == imp->logical_block_size ||
+ uio->uio_offset == (off_t)ip->i_size)
+ bp->b_flags |= B_AGE;
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
return (error);
@@ -373,8 +441,8 @@ static int
cd9660_ioctl(ap)
struct vop_ioctl_args /* {
struct vnode *a_vp;
- int a_command;
- caddr_t a_data;
+ u_long a_command;
+ caddr_t a_data;
int a_fflag;
struct ucred *a_cred;
struct proc *a_p;
@@ -452,12 +520,12 @@ struct isoreaddir {
off_t curroff;
struct uio *uio;
off_t uio_off;
- u_int *cookiep;
+ int eofflag;
+ u_long *cookies;
int ncookies;
- int eof;
};
-static int
+int
iso_uiodir(idp,dp,off)
struct isoreaddir *idp;
struct dirent *dp;
@@ -469,27 +537,27 @@ iso_uiodir(idp,dp,off)
dp->d_reclen = DIRSIZ(dp);
if (idp->uio->uio_resid < dp->d_reclen) {
- idp->eof = 0;
- return -1;
+ idp->eofflag = 0;
+ return (-1);
}
- if (idp->cookiep) {
+ if (idp->cookies) {
if (idp->ncookies <= 0) {
- idp->eof = 0;
- return -1;
+ idp->eofflag = 0;
+ return (-1);
}
- *idp->cookiep++ = off;
+ *idp->cookies++ = off;
--idp->ncookies;
}
- if ((error = uiomove((caddr_t)dp,dp->d_reclen,idp->uio)))
- return error;
+ if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio))
+ return (error);
idp->uio_off = off;
- return 0;
+ return (0);
}
-static int
+int
iso_shipdir(idp)
struct isoreaddir *idp;
{
@@ -517,13 +585,13 @@ assoc = (cl > 1) && (*cname == ASSOCCHAR);
if (sl != cl
|| bcmp(sname,cname,sl)) {
if (idp->assocent.d_namlen) {
- if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)))
- return error;
+ if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
+ return (error);
idp->assocent.d_namlen = 0;
}
if (idp->saveent.d_namlen) {
- if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)))
- return error;
+ if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
+ return (error);
idp->saveent.d_namlen = 0;
}
}
@@ -536,13 +604,11 @@ assoc = (cl > 1) && (*cname == ASSOCCHAR);
idp->saveoff = idp->curroff;
bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
}
- return 0;
+ return (0);
}
/*
* Vnode op for readdir
- * XXX make sure everything still works now that eofflagp and cookiep
- * are no longer args.
*/
static int
cd9660_readdir(ap)
@@ -550,54 +616,61 @@ cd9660_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ int *a_ncookies;
+ u_long *a_cookies;
} */ *ap;
{
register struct uio *uio = ap->a_uio;
struct isoreaddir *idp;
+ struct vnode *vdp = ap->a_vp;
+ struct iso_node *dp;
+ struct iso_mnt *imp;
+ struct buf *bp = NULL;
+ struct iso_directory_record *ep;
int entryoffsetinblock;
+ doff_t endsearch;
+ u_long bmask;
int error = 0;
- int endsearch;
- struct iso_directory_record *ep;
- u_short elen;
- int namlen;
int reclen;
- int isoflags;
- struct iso_mnt *imp;
- struct iso_node *ip;
- struct buf *bp = NULL;
- u_short tmplen;
+ u_short namelen;
int ncookies = 0;
- u_int *cookies = NULL;
+ u_long *cookies = NULL;
- ip = VTOI(ap->a_vp);
- imp = ip->i_mnt;
+ dp = VTOI(vdp);
+ imp = dp->i_mnt;
+ bmask = imp->im_bmask;
- MALLOC(idp,struct isoreaddir *,sizeof(*idp),M_TEMP,M_WAITOK);
- idp->saveent.d_namlen = 0;
- idp->assocent.d_namlen = 0;
+ MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
+ idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
+ /*
+ * XXX
+ * Is it worth trying to figure out the type?
+ */
+ idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
+ DT_UNKNOWN;
idp->uio = uio;
- if (ap->a_ncookies != NULL) {
+ if (ap->a_ncookies == NULL) {
+ idp->cookies = NULL;
+ } else {
/*
* Guess the number of cookies needed.
*/
ncookies = uio->uio_resid / 16;
- MALLOC(cookies, u_int *, ncookies * sizeof(u_int), M_TEMP, M_WAITOK);
- idp->cookiep = cookies;
+ MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP,
+ M_WAITOK);
+ idp->cookies = cookies;
idp->ncookies = ncookies;
- } else
- idp->cookiep = 0;
- idp->eof = 0;
+ }
+ idp->eofflag = 1;
idp->curroff = uio->uio_offset;
- entryoffsetinblock = iso_blkoff(imp, idp->curroff);
- if (entryoffsetinblock != 0) {
- if ((error = iso_blkatoff(ip, idp->curroff, &bp))) {
- FREE(idp,M_TEMP);
- return (error);
- }
+ if ((entryoffsetinblock = idp->curroff & bmask) &&
+ (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
+ FREE(idp, M_TEMP);
+ return (error);
}
-
- endsearch = ip->i_size;
+ endsearch = dp->i_size;
while (idp->curroff < endsearch) {
/*
@@ -605,26 +678,25 @@ cd9660_readdir(ap)
* read the next directory block.
* Release previous if it exists.
*/
-
- if (iso_blkoff(imp, idp->curroff) == 0) {
+ if ((idp->curroff & bmask) == 0) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(ip, idp->curroff, &bp)))
+ if (error =
+ VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))
break;
entryoffsetinblock = 0;
}
/*
* Get pointer to next entry.
*/
-
ep = (struct iso_directory_record *)
- (bp->b_un.b_addr + entryoffsetinblock);
+ ((char *)bp->b_data + entryoffsetinblock);
- reclen = isonum_711 (ep->length);
+ reclen = isonum_711(ep->length);
if (reclen == 0) {
/* skip to next block, if any */
- idp->curroff = roundup (idp->curroff,
- imp->logical_block_size);
+ idp->curroff =
+ (idp->curroff & ~bmask) + imp->logical_block_size;
continue;
}
@@ -640,35 +712,27 @@ cd9660_readdir(ap)
break;
}
- namlen = isonum_711 (ep->name_len);
- if (reclen < ISO_DIRECTORY_RECORD_SIZE + namlen) {
+ idp->current.d_namlen = isonum_711(ep->name_len);
+
+ if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
error = EINVAL;
/* illegal entry, stop */
break;
}
- /* XXX: be more intelligent if we can */
- idp->current.d_type = DT_UNKNOWN;
-
- idp->current.d_namlen = namlen;
- isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
- &ep->date[6]: ep->flags);
- if (isoflags & 2)
- isodirino(&idp->current.d_fileno,ep,imp);
+ if (isonum_711(ep->flags)&2)
+ idp->current.d_fileno = isodirino(ep, imp);
else
idp->current.d_fileno = dbtob(bp->b_blkno) +
- idp->curroff;
+ entryoffsetinblock;
idp->curroff += reclen;
- /*
- *
- */
+
switch (imp->iso_ftype) {
case ISO_FTYPE_RRIP:
- cd9660_rrip_getname(ep,idp->current.d_name,
- &tmplen,
+ cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
&idp->current.d_fileno,imp);
- idp->current.d_namlen = tmplen;
+ idp->current.d_namlen = (u_char)namelen;
if (idp->current.d_namlen)
error = iso_uiodir(idp,&idp->current,idp->curroff);
break;
@@ -685,10 +749,10 @@ cd9660_readdir(ap)
break;
default:
isofntrans(ep->name,idp->current.d_namlen,
- idp->current.d_name, &elen,
+ idp->current.d_name, &namelen,
imp->iso_ftype == ISO_FTYPE_9660,
- isoflags & 4);
- idp->current.d_namlen = (u_char)elen;
+ isonum_711(ep->flags)&4);
+ idp->current.d_namlen = (u_char)namelen;
if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
error = iso_shipdir(idp);
else
@@ -711,7 +775,7 @@ cd9660_readdir(ap)
if (ap->a_ncookies != NULL) {
if (error)
- FREE(cookies, M_TEMP);
+ free(cookies, M_TEMP);
else {
/*
* Work out the number of cookies actually used.
@@ -725,10 +789,9 @@ cd9660_readdir(ap)
brelse (bp);
uio->uio_offset = idp->uio_off;
- if (ap->a_eofflag)
- *ap->a_eofflag = idp->eof;
+ *ap->a_eofflag = idp->eofflag;
- FREE(idp,M_TEMP);
+ FREE(idp, M_TEMP);
return (error);
}
@@ -754,44 +817,34 @@ cd9660_readlink(ap)
ISODIR *dirp;
ISOMNT *imp;
struct buf *bp;
+ struct uio *uio;
u_short symlen;
int error;
char *symname;
ip = VTOI(ap->a_vp);
imp = ip->i_mnt;
+ uio = ap->a_uio;
if (imp->iso_ftype != ISO_FTYPE_RRIP)
- return EINVAL;
+ return (EINVAL);
/*
* Get parents directory record block that this inode included.
*/
error = bread(imp->im_devvp,
- iso_dblkno(imp, ip->i_number),
- imp->logical_block_size,
- NOCRED,
- &bp);
+ (ip->i_number >> imp->im_bshift) <<
+ (imp->im_bshift - DEV_BSHIFT),
+ imp->logical_block_size, NOCRED, &bp);
if (error) {
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Setup the directory pointer for this inode
*/
- dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask));
-#ifdef DEBUG
- printf("lbn=%d,off=%d,bsize=%d,DEV_BSIZE=%d, dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n",
- (daddr_t)(ip->i_number >> imp->im_bshift),
- ip->i_number & imp->im_bmask,
- imp->logical_block_size,
- DEV_BSIZE,
- dirp,
- bp->b_un.b_addr,
- ip->i_number,
- ip->i_number & imp->im_bmask );
-#endif
+ dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
/*
* Just make sure, we have a right one....
@@ -800,22 +853,26 @@ cd9660_readlink(ap)
if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
> (unsigned)imp->logical_block_size) {
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Now get a buffer
* Abuse a namei buffer for now.
*/
- MALLOC(symname,char *,MAXPATHLEN,M_NAMEI,M_WAITOK);
-
+ if (uio->uio_segflg == UIO_SYSSPACE)
+ symname = uio->uio_iov->iov_base;
+ else
+ MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
+
/*
* Ok, we just gathering a symbolic name in SL record.
*/
- if (cd9660_rrip_getsymname(dirp,symname,&symlen,imp) == 0) {
- FREE(symname,M_NAMEI);
+ if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
+ if (uio->uio_segflg != UIO_SYSSPACE)
+ FREE(symname, M_NAMEI);
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Don't forget before you leave from home ;-)
@@ -825,11 +882,15 @@ cd9660_readlink(ap)
/*
* return with the symbolic name to caller's.
*/
- error = uiomove(symname,symlen,ap->a_uio);
-
- FREE(symname,M_NAMEI);
-
- return error;
+ if (uio->uio_segflg != UIO_SYSSPACE) {
+ error = uiomove(symname, symlen, uio);
+ FREE(symname, M_NAMEI);
+ return (error);
+ }
+ uio->uio_resid -= symlen;
+ uio->uio_iov->iov_base += symlen;
+ uio->uio_iov->iov_len -= symlen;
+ return (0);
}
/*
@@ -845,7 +906,7 @@ cd9660_abortop(ap)
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
- return 0;
+ return (0);
}
/*
@@ -855,12 +916,14 @@ static int
cd9660_lock(ap)
struct vop_lock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- register struct iso_node *ip = VTOI(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
- ISO_ILOCK(ip);
- return 0;
+ return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
+ ap->a_p));
}
/*
@@ -870,29 +933,14 @@ static int
cd9660_unlock(ap)
struct vop_unlock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- register struct iso_node *ip = VTOI(ap->a_vp);
-
- if (!(ip->i_flag & ILOCKED))
- panic("cd9660_unlock NOT LOCKED");
- ISO_IUNLOCK(ip);
- return 0;
-}
-
-/*
- * Check for a locked inode.
- */
-static int
-cd9660_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
+ struct vnode *vp = ap->a_vp;
- if (VTOI(ap->a_vp)->i_flag & ILOCKED)
- return 1;
- return 0;
+ return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
+ &vp->v_interlock, ap->a_p));
}
/*
@@ -943,102 +991,150 @@ cd9660_print(ap)
struct vnode *a_vp;
} */ *ap;
{
+
printf("tag VT_ISOFS, isofs vnode\n");
- return 0;
+ return (0);
+}
+
+/*
+ * Check for a locked inode.
+ */
+int
+cd9660_islocked(ap)
+ struct vop_islocked_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
+{
+
+ return (lockstatus(&VTOI(ap->a_vp)->i_lock));
}
/*
- * Unsupported operation
+ * Return POSIX pathconf information applicable to cd9660 filesystems.
*/
-static int
-cd9660_enotsupp()
+int
+cd9660_pathconf(ap)
+ struct vop_pathconf_args /* {
+ struct vnode *a_vp;
+ int a_name;
+ register_t *a_retval;
+ } */ *ap;
{
- return (EOPNOTSUPP);
+ switch (ap->a_name) {
+ case _PC_LINK_MAX:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NAME_MAX:
+ if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
+ *ap->a_retval = NAME_MAX;
+ else
+ *ap->a_retval = 37;
+ return (0);
+ case _PC_PATH_MAX:
+ *ap->a_retval = PATH_MAX;
+ return (0);
+ case _PC_PIPE_BUF:
+ *ap->a_retval = PIPE_BUF;
+ return (0);
+ case _PC_CHOWN_RESTRICTED:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NO_TRUNC:
+ *ap->a_retval = 1;
+ return (0);
+ default:
+ return (EINVAL);
+ }
+ /* NOTREACHED */
}
/*
* Global vfs data structures for isofs
*/
#define cd9660_create \
- ((int (*) __P((struct vop_create_args *)))cd9660_enotsupp)
-#define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))cd9660_enotsupp)
-#define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_create_args *)))eopnotsupp)
+#define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
+#define cd9660_write ((int (*) __P((struct vop_write_args *)))eopnotsupp)
+#ifdef NFS
+#define cd9660_lease_check lease_check
+#else
+#define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
+#endif
#define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define cd9660_remove \
- ((int (*) __P((struct vop_remove_args *)))cd9660_enotsupp)
-#define cd9660_link ((int (*) __P((struct vop_link_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
+#define cd9660_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
#define cd9660_rename \
- ((int (*) __P((struct vop_rename_args *)))cd9660_enotsupp)
-#define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))cd9660_enotsupp)
-#define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
+#define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
+#define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
#define cd9660_symlink \
- ((int (*) __P((struct vop_symlink_args *)))cd9660_enotsupp)
-#define cd9660_pathconf \
- ((int (*) __P((struct vop_pathconf_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
#define cd9660_advlock \
- ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp)
-#define cd9660_blkatoff \
- ((int (*) __P((struct vop_blkatoff_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
#define cd9660_valloc ((int(*) __P(( \
struct vnode *pvp, \
int mode, \
struct ucred *cred, \
- struct vnode **vpp))) cd9660_enotsupp)
-#define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp)
+ struct vnode **vpp))) eopnotsupp)
+#define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))eopnotsupp)
#define cd9660_truncate \
- ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
#define cd9660_update \
- ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_update_args *)))eopnotsupp)
#define cd9660_bwrite \
- ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
/*
- * Global vfs data structures for nfs
+ * Global vfs data structures for cd9660
*/
vop_t **cd9660_vnodeop_p;
-static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
+struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
+
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)cd9660_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)cd9660_open }, /* open */
- { &vop_close_desc, (vop_t *)cd9660_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)cd9660_read }, /* read */
- { &vop_write_desc, (vop_t *)cd9660_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)cd9660_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)cd9660_select }, /* select */
- { &vop_mmap_desc, (vop_t *)cd9660_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)cd9660_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)cd9660_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)cd9660_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)cd9660_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)cd9660_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)cd9660_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)cd9660_strategy }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)cd9660_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)cd9660_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)cd9660_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)cd9660_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)cd9660_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)cd9660_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)cd9660_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)cd9660_open }, /* open */
+ { &vop_close_desc, (vop_t *)cd9660_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)cd9660_read }, /* read */
+ { &vop_write_desc, (vop_t *)cd9660_write }, /* write */
+ { &vop_lease_desc, (vop_t *)cd9660_lease_check },/* lease */
+ { &vop_ioctl_desc, (vop_t *)cd9660_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)cd9660_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)cd9660_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)cd9660_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)cd9660_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)cd9660_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
+ { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)cd9660_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)cd9660_readlink },/* readlink */
+ { &vop_abortop_desc, (vop_t *)cd9660_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)cd9660_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)cd9660_strategy },/* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)cd9660_pathconf },/* pathconf */
+ { &vop_advlock_desc, (vop_t *)cd9660_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)cd9660_blkatoff },/* blkatoff */
+ { &vop_valloc_desc, (vop_t *)cd9660_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)cd9660_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)cd9660_truncate },/* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_vnodeop_opv_desc =
@@ -1049,101 +1145,106 @@ VNODEOP_SET(cd9660_vnodeop_opv_desc);
* Special device vnode ops
*/
vop_t **cd9660_specop_p;
-static struct vnodeopv_entry_desc cd9660_specop_entries[] = {
+struct vnodeopv_entry_desc cd9660_specop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)spec_open }, /* open */
- { &vop_close_desc, (vop_t *)spec_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)spec_read }, /* read */
- { &vop_write_desc, (vop_t *)spec_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)spec_select }, /* select */
- { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_getpages_desc, (vop_t *)spec_getpages}, /* getpages */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)spec_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)spec_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)spec_open }, /* open */
+ { &vop_close_desc, (vop_t *)spec_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)spec_read }, /* read */
+ { &vop_write_desc, (vop_t *)spec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
+ { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)spec_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)spec_link }, /* link */
+ { &vop_rename_desc, (vop_t *)spec_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)spec_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)spec_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)spec_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
+ { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */
+ { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_specop_opv_desc =
{ &cd9660_specop_p, cd9660_specop_entries };
VNODEOP_SET(cd9660_specop_opv_desc);
+#ifdef FIFO
vop_t **cd9660_fifoop_p;
-static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
+struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)fifo_open }, /* open */
- { &vop_close_desc, (vop_t *)fifo_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)fifo_read }, /* read */
- { &vop_write_desc, (vop_t *)fifo_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)fifo_select }, /* select */
- { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)fifo_badop }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)fifo_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)fifo_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)fifo_open }, /* open */
+ { &vop_close_desc, (vop_t *)fifo_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)fifo_read }, /* read */
+ { &vop_write_desc, (vop_t *)fifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
+ { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)fifo_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)fifo_link } , /* link */
+ { &vop_rename_desc, (vop_t *)fifo_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)fifo_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)fifo_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)fifo_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
+ { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)fifo_strategy }, /* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
+ { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_fifoop_opv_desc =
{ &cd9660_fifoop_p, cd9660_fifoop_entries };
VNODEOP_SET(cd9660_fifoop_opv_desc);
+#endif /* FIFO */
diff --git a/sys/fs/cd9660/iso.h b/sys/fs/cd9660/iso.h
index 1656c23..e2a7779 100644
--- a/sys/fs/cd9660/iso.h
+++ b/sys/fs/cd9660/iso.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)iso.h 8.2 (Berkeley) 1/23/94
+ * @(#)iso.h 8.6 (Berkeley) 5/10/95
* $FreeBSD$
*/
@@ -138,37 +138,37 @@ struct iso_sierra_primary_descriptor {
struct iso_directory_record {
char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
- unsigned char extent [ISODCL (3, 10)]; /* 733 */
- unsigned char size [ISODCL (11, 18)]; /* 733 */
+ u_char extent [ISODCL (3, 10)]; /* 733 */
+ u_char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
char name_len [ISODCL (33, 33)]; /* 711 */
- char name [0];
+ char name [1]; /* XXX */
};
/* can't take sizeof(iso_directory_record), because of possible alignment
of the last entry (34 instead of 33) */
#define ISO_DIRECTORY_RECORD_SIZE 33
struct iso_extended_attributes {
- unsigned char owner [ISODCL (1, 4)]; /* 723 */
- unsigned char group [ISODCL (5, 8)]; /* 723 */
- unsigned char perm [ISODCL (9, 10)]; /* 9.5.3 */
+ u_char owner [ISODCL (1, 4)]; /* 723 */
+ u_char group [ISODCL (5, 8)]; /* 723 */
+ u_char perm [ISODCL (9, 10)]; /* 9.5.3 */
char ctime [ISODCL (11, 27)]; /* 8.4.26.1 */
char mtime [ISODCL (28, 44)]; /* 8.4.26.1 */
char xtime [ISODCL (45, 61)]; /* 8.4.26.1 */
char ftime [ISODCL (62, 78)]; /* 8.4.26.1 */
char recfmt [ISODCL (79, 79)]; /* 711 */
char recattr [ISODCL (80, 80)]; /* 711 */
- unsigned char reclen [ISODCL (81, 84)]; /* 723 */
+ u_char reclen [ISODCL (81, 84)]; /* 723 */
char system_id [ISODCL (85, 116)]; /* achars */
char system_use [ISODCL (117, 180)];
char version [ISODCL (181, 181)]; /* 711 */
char len_esc [ISODCL (182, 182)]; /* 711 */
char reserved [ISODCL (183, 246)];
- unsigned char len_au [ISODCL (247, 250)]; /* 723 */
+ u_char len_au [ISODCL (247, 250)]; /* 723 */
};
/* CD-ROM Format type */
@@ -191,7 +191,6 @@ struct iso_mnt {
int im_bmask;
int volume_space_size;
- char im_fsmnt[50];
struct netexport im_export;
char root[ISODCL (157, 190)];
@@ -205,94 +204,102 @@ struct iso_mnt {
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
-#define iso_blkoff(imp, loc) ((loc) & (imp)->im_bmask)
-#define iso_lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
-#define iso_blksize(imp, ip, lbn) ((imp)->logical_block_size)
-#define iso_lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
-#define iso_lblktodaddr(imp, lbn) btodb(iso_lblktosize(imp, lbn))
-#define iso_dblkinc(imp, lbn) ((lbn) + iso_lblktodaddr(imp, 1))
-#define iso_dblkno(imp, loc) iso_lblktodaddr(imp, iso_lblkno(imp, loc))
-int cd9660_init __P((void));
-
-struct iso_node;
-int iso_blkatoff __P((struct iso_node *ip, long offset, struct buf **bpp));
-int iso_iget __P((struct iso_node *xp, ino_t ino, int relocated,
- struct iso_node **ipp, struct iso_directory_record *isodir));
-int iso_iput __P((struct iso_node *ip));
-int iso_ilock __P((struct iso_node *ip));
-int iso_iunlock __P((struct iso_node *ip));
-int cd9660_mountroot __P((void));
+#define blkoff(imp, loc) ((loc) & (imp)->im_bmask)
+#define lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
+#define lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
+#define blksize(imp, ip, lbn) ((imp)->logical_block_size)
+
+int cd9660_vget_internal __P((struct mount *, ino_t, struct vnode **, int,
+ struct iso_directory_record *));
+int cd9660_init __P((struct vfsconf *));
+#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+
+int cd9660_mountroot __P((void));
extern vop_t **cd9660_vnodeop_p;
+extern vop_t **cd9660_specop_p;
+#ifdef FIFO
+extern vop_t **cd9660_fifoop_p;
+#endif
-static int isonum_711 __P((unsigned char *p));
-static int isonum_712 __P((char *p));
-static int isonum_721 __P((unsigned char *p));
-static int isonum_722 __P((unsigned char *p));
-static int isonum_723 __P((unsigned char *p));
-static int isonum_731 __P((unsigned char *p));
-static int isonum_732 __P((unsigned char *p));
-static int isonum_733 __P((unsigned char *p));
-
-static inline int
+static __inline int isonum_711 __P((u_char *));
+static __inline int
isonum_711(p)
- unsigned char *p;
+ u_char *p;
{
return *p;
}
-static inline int
+static __inline int isonum_712 __P((char *));
+static __inline int
isonum_712(p)
char *p;
{
return *p;
}
-static inline int
-isonum_721(p)
- unsigned char *p;
+#ifndef UNALIGNED_ACCESS
+
+static __inline int isonum_723 __P((u_char *));
+static __inline int
+isonum_723(p)
+ u_char *p;
{
- return *p|((char)p[1] << 8);
+ return *p|(p[1] << 8);
}
-static inline int
-isonum_722(p)
- unsigned char *p;
+static __inline int isonum_733 __P((u_char *));
+static __inline int
+isonum_733(p)
+ u_char *p;
{
- return ((char)*p << 8)|p[1];
+ return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
}
-static inline int
+#else /* UNALIGNED_ACCESS */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+static __inline int
isonum_723(p)
- unsigned char *p;
+ u_char *p
{
- return isonum_721(p);
+ return *(u_int16t *)p;
}
-static inline int
-isonum_731(p)
- unsigned char *p;
+static __inline int
+isonum_733(p)
+ u_char *p;
{
- return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
+ return *(u_int32t *)p;
}
-static inline int
-isonum_732(p)
- unsigned char *p;
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+static __inline int
+isonum_723(p)
+ u_char *p
{
- return (*p << 24)|(p[1] << 16)|(p[2] << 8)|p[3];
+ return *(u_int16t *)(p + 2);
}
-static inline int
+static __inline int
isonum_733(p)
- unsigned char *p;
+ u_char *p;
{
- return isonum_731(p);
+ return *(u_int32t *)(p + 4);
}
-int isofncmp __P((unsigned char *, int, unsigned char *, int));
-void isofntrans __P((unsigned char *, int, unsigned char *, unsigned short *,
- int, int));
+#endif
+
+#endif /* UNALIGNED_ACCESS */
+
+int isofncmp __P((u_char *, int, u_char *, int));
+void isofntrans __P((u_char *, int, u_char *, u_short *, int, int));
+ino_t isodirino __P((struct iso_directory_record *, struct iso_mnt *));
/*
* Associated files have a leading '='.
diff --git a/sys/fs/deadfs/dead_vnops.c b/sys/fs/deadfs/dead_vnops.c
index f22425c..6d83c61 100644
--- a/sys/fs/deadfs/dead_vnops.c
+++ b/sys/fs/deadfs/dead_vnops.c
@@ -77,11 +77,11 @@ static int dead_select __P((struct vop_select_args *));
#define dead_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
#define dead_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
static int dead_lock __P((struct vop_lock_args *));
-#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
static int dead_bmap __P((struct vop_bmap_args *));
static int dead_strategy __P((struct vop_strategy_args *));
static int dead_print __P((struct vop_print_args *));
-#define dead_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define dead_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
#define dead_pathconf ((int (*) __P((struct vop_pathconf_args *)))dead_ebadf)
#define dead_advlock ((int (*) __P((struct vop_advlock_args *)))dead_ebadf)
#define dead_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))dead_badop)
@@ -191,11 +191,20 @@ dead_read(ap)
if (chkvnlock(ap->a_vp))
panic("dead_read: lock");
+#if 0
+ /* Lite2 behaviour */
+ /*
+ * Return EOF for tty devices, EIO for others
+ */
+ if ((ap->a_vp->v_flag & VISTTY) == 0)
+ return (EIO);
+#else
/*
* Return EOF for character devices, EIO for others
*/
if (ap->a_vp->v_type != VCHR)
return (EIO);
+#endif
return (0);
}
@@ -282,12 +291,23 @@ static int
dead_lock(ap)
struct vop_lock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
- if (!chkvnlock(ap->a_vp))
+ /*
+ * Since we are not using the lock manager, we must clear
+ * the interlock here.
+ */
+ if (ap->a_flags & LK_INTERLOCK) {
+ simple_unlock(&vp->v_interlock);
+ ap->a_flags &= ~LK_INTERLOCK;
+ }
+ if (!chkvnlock(vp))
return (0);
- return (VCALL(ap->a_vp, VOFFSET(vop_lock), ap));
+ return (VCALL(vp, VOFFSET(vop_lock), ap));
}
/*
diff --git a/sys/fs/fdescfs/fdesc.h b/sys/fs/fdescfs/fdesc.h
index d754655..b4eff1f 100644
--- a/sys/fs/fdescfs/fdesc.h
+++ b/sys/fs/fdescfs/fdesc.h
@@ -61,8 +61,7 @@ typedef enum {
} fdntype;
struct fdescnode {
- struct fdescnode *fd_forw; /* Hash chain */
- struct fdescnode *fd_back;
+ LIST_ENTRY(fdescnode) fd_hash; /* Hash list */
struct vnode *fd_vnode; /* Back ptr to vnode */
fdntype fd_type; /* Type of this node */
unsigned fd_fd; /* Fd to be dup'ed */
@@ -74,7 +73,7 @@ struct fdescnode {
#define VTOFDESC(vp) ((struct fdescnode *)(vp)->v_data)
extern dev_t devctty;
-extern int fdesc_init __P((void));
+extern int fdesc_init __P((struct vfsconf *));
extern int fdesc_root __P((struct mount *, struct vnode **));
extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **));
extern vop_t **fdesc_vnodeop_p;
diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c
index 5f6703b..135052e 100644
--- a/sys/fs/fdescfs/fdesc_vfsops.c
+++ b/sys/fs/fdescfs/fdesc_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -108,7 +108,7 @@ fdesc_mount(mp, path, data, ndp, p)
/* XXX -- don't mark as local to work around fts() problems */
/*mp->mnt_flag |= MNT_LOCAL;*/
mp->mnt_data = (qaddr_t) fmp;
- getnewfsid(mp, MOUNT_FDESC);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -137,12 +137,8 @@ fdesc_unmount(mp, mntflags, p)
int flags = 0;
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
@@ -176,6 +172,7 @@ fdesc_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
/*
@@ -183,24 +180,12 @@ fdesc_root(mp, vpp)
*/
vp = VFSTOFDESC(mp)->f_root;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
static int
-fdesc_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
fdesc_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
@@ -233,7 +218,6 @@ fdesc_statfs(mp, sbp, p)
if (fdp->fd_nfiles < lim)
freefd += (lim - fdp->fd_nfiles);
- sbp->f_type = MOUNT_FDESC;
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
@@ -243,6 +227,7 @@ fdesc_statfs(mp, sbp, p)
sbp->f_files = lim + 1; /* Allow for "." */
sbp->f_ffree = freefd; /* See comments above */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -261,41 +246,15 @@ fdesc_sync(mp, waitfor, cred, p)
return (0);
}
-/*
- * Fdesc flat namespace lookup.
- * Currently unsupported.
- */
-static int
-fdesc_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-fdesc_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-fdesc_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+#define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
static struct vfsops fdesc_vfsops = {
fdesc_mount,
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index 1fe511b..795dfd8 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -77,22 +77,14 @@ FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
#endif
#define NFDCACHE 4
-#define FD_NHASH(ix) ((ix) & NFDCACHE-1)
-
-/*
- * Cache head
- */
-struct fdcache {
- struct fdescnode *fc_forw;
- struct fdescnode *fc_back;
-};
-
-static struct fdcache fdcache[NFDCACHE];
+#define FD_NHASH(ix) \
+ (&fdhashtbl[(ix) & fdhash])
+LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
+u_long fdhash;
static int fdesc_attr __P((int fd, struct vattr *vap, struct ucred *cred,
struct proc *p));
static int fdesc_badop __P((void));
-static int fdesc_enotsupp __P((void));
static int fdesc_getattr __P((struct vop_getattr_args *ap));
static struct fdcache *
fdesc_hash __P((int ix));
@@ -115,28 +107,15 @@ static int fdesc_write __P((struct vop_write_args *ap));
* Initialise cache headers
*/
int
-fdesc_init()
+fdesc_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct fdcache *fc;
devctty = makedev(nchrdev, 0);
-
- for (fc = fdcache; fc < fdcache + NFDCACHE; fc++)
- fc->fc_forw = fc->fc_back = (struct fdescnode *) fc;
+ fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
return (0);
}
-/*
- * Compute hash list for given target vnode
- */
-static struct fdcache *
-fdesc_hash(ix)
- int ix;
-{
-
- return (&fdcache[FD_NHASH(ix)]);
-}
-
int
fdesc_allocvp(ftype, ix, mp, vpp)
fdntype ftype;
@@ -144,15 +123,16 @@ fdesc_allocvp(ftype, ix, mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- struct fdcache *fc;
+ struct proc *p = curproc; /* XXX */
+ struct fdhashhead *fc;
struct fdescnode *fd;
int error = 0;
+ fc = FD_NHASH(ix);
loop:
- fc = fdesc_hash(ix);
- for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) {
+ for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
- if (vget(fd->fd_vnode, 0))
+ if (vget(fd->fd_vnode, 0, p))
goto loop;
*vpp = fd->fd_vnode;
return (error);
@@ -188,8 +168,7 @@ loop:
fd->fd_fd = -1;
fd->fd_link = 0;
fd->fd_ix = ix;
- fc = fdesc_hash(ix);
- insque(fd, fc);
+ LIST_INSERT_HEAD(fc, fd, fd_hash);
out:;
fdcache_lock &= ~FDL_LOCKED;
@@ -216,31 +195,28 @@ fdesc_lookup(ap)
{
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
- char *pname;
- struct proc *p;
- int nfiles;
- unsigned fd = 0;
+ struct componentname *cnp = ap->a_cnp;
+ char *pname = cnp->cn_nameptr;
+ struct proc *p = cnp->cn_proc;
+ int nfiles = p->p_fd->fd_nfiles;
+ unsigned fd;
int error;
struct vnode *fvp;
char *ln;
- if (ap->a_cnp->cn_nameiop == DELETE ||
- ap->a_cnp->cn_nameiop == RENAME) {
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
error = EROFS;
goto bad;
}
- pname = ap->a_cnp->cn_nameptr;
- if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
+ VOP_UNLOCK(dvp, 0, p);
+ if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
- VREF(dvp);
- VOP_LOCK(dvp);
+ VREF(dvp);
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return (0);
}
- p = ap->a_cnp->cn_proc;
- nfiles = p->p_fd->fd_nfiles;
-
switch (VTOFDESC(dvp)->fd_type) {
default:
case Flink:
@@ -250,17 +226,17 @@ fdesc_lookup(ap)
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(fvp, LK_SHARED | LK_RETRY, p);
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;
@@ -271,12 +247,12 @@ fdesc_lookup(ap)
goto bad;
*vpp = fvp;
fvp->v_type = VFIFO;
- VOP_LOCK(fvp);
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
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";
@@ -302,7 +278,7 @@ fdesc_lookup(ap)
VTOFDESC(fvp)->fd_link = ln;
*vpp = fvp;
fvp->v_type = VLNK;
- VOP_LOCK(fvp);
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
return (0);
} else {
error = ENOENT;
@@ -312,9 +288,10 @@ fdesc_lookup(ap)
/* FALL THROUGH */
case Fdevfd:
- if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
- error = fdesc_root(dvp->v_mount, vpp);
- return (error);
+ if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
+ if (error = fdesc_root(dvp->v_mount, vpp))
+ goto bad;
+ return (0);
}
fd = 0;
@@ -338,11 +315,13 @@ fdesc_lookup(ap)
if (error)
goto bad;
VTOFDESC(fvp)->fd_fd = fd;
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
*vpp = fvp;
return (0);
}
bad:;
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
*vpp = NULL;
return (error);
}
@@ -402,10 +381,10 @@ fdesc_attr(fd, vap, cred, p)
error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
if (error == 0 && vap->va_type == VDIR) {
/*
- * don't allow directories to show up because
- * that causes loops in the namespace.
+ * directories can cause loops in the namespace,
+ * so turn off the 'x' bits to avoid trouble.
*/
- vap->va_type = VFIFO;
+ vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
}
break;
@@ -591,6 +570,9 @@ fdesc_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
struct uio *uio = ap->a_uio;
@@ -598,6 +580,13 @@ fdesc_readdir(ap)
int i;
int error;
+ /*
+ * We don't allow exporting fdesc mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("fdesc_readdir: not hungry");
+
switch (VTOFDESC(ap->a_vp)->fd_type) {
case Fctty:
return (0);
@@ -814,6 +803,7 @@ static int
fdesc_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
@@ -822,6 +812,7 @@ fdesc_inactive(ap)
* Clear out the v_type field to avoid
* nasty things happening in vgone().
*/
+ VOP_UNLOCK(vp, 0, ap->a_p);
vp->v_type = VNON;
return (0);
}
@@ -833,8 +824,9 @@ fdesc_reclaim(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+ struct fdescnode *fd = VTOFDESC(vp);
- remque(VTOFDESC(vp));
+ LIST_REMOVE(fd, fd_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = 0;
@@ -907,16 +899,6 @@ fdesc_vfree(ap)
}
/*
- * /dev/fd vnode unsupported operation
- */
-static int
-fdesc_enotsupp()
-{
-
- return (EOPNOTSUPP);
-}
-
-/*
* /dev/fd "should never get here" operation
*/
static int
@@ -927,38 +909,39 @@ fdesc_badop()
/* NOTREACHED */
}
-#define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp)
-#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp)
+#define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
+#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
#define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
#define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
-#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp)
+#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
+#define fdesc_revoke vop_revoke
#define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
-#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp)
-#define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp)
-#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp)
-#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp)
-#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp)
-#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp)
+#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
+#define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
+#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
+#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
+#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
+#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
#define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
-#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
#define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
#define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
-#define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
-#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp)
+#define fdesc_islocked \
+ ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
+#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
#define fdesc_blkatoff \
- ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp)
-#define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp)
+ ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
#define fdesc_valloc ((int(*) __P(( \
struct vnode *pvp, \
int mode, \
struct ucred *cred, \
- struct vnode **vpp))) fdesc_enotsupp)
+ struct vnode **vpp))) eopnotsupp)
#define fdesc_truncate \
- ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp)
-#define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp)
-#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp)
+ ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
+#define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
+#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
static vop_t **fdesc_vnodeop_p;
static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
@@ -975,6 +958,7 @@ static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
{ &vop_write_desc, (vop_t *)fdesc_write }, /* write */
{ &vop_ioctl_desc, (vop_t *)fdesc_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fdesc_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fdesc_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fdesc_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)fdesc_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fdesc_seek }, /* seek */
diff --git a/sys/fs/fifofs/fifo.h b/sys/fs/fifofs/fifo.h
index efeaf85..6562159 100644
--- a/sys/fs/fifofs/fifo.h
+++ b/sys/fs/fifofs/fifo.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)fifo.h 8.2 (Berkeley) 2/2/94
+ * @(#)fifo.h 8.6 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -51,8 +51,10 @@ int fifo_close __P((struct vop_close_args *));
#define fifo_setattr ((int (*) __P((struct vop_setattr_args *)))fifo_ebadf)
int fifo_read __P((struct vop_read_args *));
int fifo_write __P((struct vop_write_args *));
+#define fifo_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
int fifo_ioctl __P((struct vop_ioctl_args *));
int fifo_select __P((struct vop_select_args *));
+#define fifo_revoke vop_revoke
#define fifo_mmap ((int (*) __P((struct vop_mmap_args *)))fifo_badop)
#define fifo_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define fifo_seek ((int (*) __P((struct vop_seek_args *)))fifo_badop)
@@ -65,11 +67,13 @@ int fifo_select __P((struct vop_select_args *));
#define fifo_readdir ((int (*) __P((struct vop_readdir_args *)))fifo_badop)
#define fifo_readlink ((int (*) __P((struct vop_readlink_args *)))fifo_badop)
#define fifo_abortop ((int (*) __P((struct vop_abortop_args *)))fifo_badop)
-#define fifo_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
+int fifo_inactive __P((struct vop_inactive_args *));
#define fifo_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
+#define fifo_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define fifo_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
int fifo_bmap __P((struct vop_bmap_args *));
#define fifo_strategy ((int (*) __P((struct vop_strategy_args *)))fifo_badop)
-#define fifo_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
int fifo_pathconf __P((struct vop_pathconf_args *));
int fifo_advlock __P((struct vop_advlock_args *));
#define fifo_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))fifo_badop)
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 240354f..8f915ec 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -30,12 +30,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)fifo_vnops.c 8.2 (Berkeley) 1/4/94
+ * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95
* $FreeBSD$
*/
#include <sys/param.h>
-#include <sys/kernel.h>
+#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/namei.h>
@@ -44,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>
@@ -64,8 +63,6 @@ struct fifoinfo {
};
static int fifo_ebadf __P((void));
-static int fifo_unlock __P((struct vop_unlock_args *));
-static int fifo_lock __P((struct vop_lock_args *));
static int fifo_print __P((struct vop_print_args *));
vop_t **fifo_vnodeop_p;
@@ -81,8 +78,10 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)fifo_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)fifo_read }, /* read */
{ &vop_write_desc, (vop_t *)fifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
@@ -149,8 +148,9 @@ fifo_open(ap)
struct proc *a_p;
} */ *ap;
{
- 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 char openstr[] = "fifo";
@@ -158,14 +158,14 @@ fifo_open(ap)
if ((fip = vp->v_fifoinfo) == NULL) {
MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
vp->v_fifoinfo = fip;
- error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, ap->a_p);
+ error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_p);
if (error) {
free(fip, M_VNODE);
vp->v_fifoinfo = NULL;
return (error);
}
fip->fi_readsock = rso;
- error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, ap->a_p);
+ error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_p);
if (error) {
(void)soclose(rso);
free(fip, M_VNODE);
@@ -185,60 +185,52 @@ fifo_open(ap)
wso->so_state |= SS_CANTRCVMORE;
rso->so_state |= SS_CANTSENDMORE;
}
- error = 0;
- if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
- if (fip->fi_readers == 0) {
+ if (ap->a_mode & FREAD) {
+ fip->fi_readers++;
+ if (fip->fi_readers == 1) {
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
if (fip->fi_writers > 0)
wakeup((caddr_t)&fip->fi_writers);
}
- if (fip->fi_writers == 0) {
+ }
+ if (ap->a_mode & FWRITE) {
+ fip->fi_writers++;
+ if (fip->fi_writers == 1) {
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
if (fip->fi_readers > 0)
wakeup((caddr_t)&fip->fi_readers);
}
- fip->fi_readers++;
- fip->fi_writers++;
}
- else if (ap->a_mode & FREAD) {
- fip->fi_readers++;
- if (fip->fi_readers == 1) {
- fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
- if (fip->fi_writers > 0)
- wakeup((caddr_t)&fip->fi_writers);
+ if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
+ while (fip->fi_writers == 0) {
+ VOP_UNLOCK(vp, 0, p);
+ error = tsleep((caddr_t)&fip->fi_readers,
+ PCATCH | PSOCK, openstr, 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (error)
+ goto bad;
}
- if (!(ap->a_mode & O_NONBLOCK))
- while (fip->fi_writers == 0) {
- VOP_UNLOCK(vp);
- error = tsleep((caddr_t)&fip->fi_readers,
- PCATCH | PSOCK, openstr, 0);
- VOP_LOCK(vp);
- if (error)
- break;
- }
}
- else {
- fip->fi_writers++;
- if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) {
- error = ENXIO;
- } else {
- if (fip->fi_writers == 1) {
- fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
- if (fip->fi_readers > 0)
- wakeup((caddr_t)&fip->fi_readers);
+ if (ap->a_mode & FWRITE) {
+ if (ap->a_mode & O_NONBLOCK) {
+ if (fip->fi_readers == 0) {
+ error = ENXIO;
+ goto bad;
}
+ } else {
while (fip->fi_readers == 0) {
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = tsleep((caddr_t)&fip->fi_writers,
PCATCH | PSOCK, openstr, 0);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (error)
- break;
+ goto bad;
}
}
}
- if (error)
- VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
+ return (0);
+bad:
+ VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p);
return (error);
}
@@ -255,8 +247,9 @@ fifo_read(ap)
struct ucred *a_cred;
} */ *ap;
{
- 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;
+ struct proc *p = uio->uio_procp;
int error, startresid;
#ifdef DIAGNOSTIC
@@ -268,10 +261,10 @@ fifo_read(ap)
if (ap->a_ioflag & IO_NDELAY)
rso->so_state |= SS_NBIO;
startresid = uio->uio_resid;
- VOP_UNLOCK(ap->a_vp);
- error = soreceive(rso, (struct mbuf **)0, uio,
- (struct mbuf **)0, (struct mbuf **)0, (int*)0);
- VOP_LOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
+ error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
+ (struct mbuf **)0, (int *)0);
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
/*
* Clear EOF indication after first such return.
*/
@@ -296,6 +289,7 @@ fifo_write(ap)
} */ *ap;
{
struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
+ struct proc *p = ap->a_uio->uio_procp;
int error;
#ifdef DIAGNOSTIC
@@ -304,9 +298,9 @@ fifo_write(ap)
#endif
if (ap->a_ioflag & IO_NDELAY)
wso->so_state |= SS_NBIO;
- VOP_UNLOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
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, p);
if (ap->a_ioflag & IO_NDELAY)
wso->so_state &= ~SS_NBIO;
return (error);
@@ -328,14 +322,23 @@ fifo_ioctl(ap)
} */ *ap;
{
struct file filetmp;
+ int error;
if (ap->a_command == FIONBIO)
return (0);
- if (ap->a_fflag & FREAD)
+ if (ap->a_fflag & FREAD) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- else
+ error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
+ if (error)
+ return (error);
+ }
+ if (ap->a_fflag & FWRITE) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
- return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p));
+ error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
+ if (error)
+ return (error);
+ }
+ return (0);
}
/* ARGSUSED */
@@ -350,12 +353,33 @@ fifo_select(ap)
} */ *ap;
{
struct file filetmp;
+ int ready;
- if (ap->a_fflags & FREAD)
+ if (ap->a_fflags & FREAD) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- else
+ ready = soo_select(&filetmp, ap->a_which, ap->a_p);
+ if (ready)
+ return (ready);
+ }
+ if (ap->a_fflags & FWRITE) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
- return (soo_select(&filetmp, ap->a_which, ap->a_p));
+ ready = soo_select(&filetmp, ap->a_which, ap->a_p);
+ if (ready)
+ return (ready);
+ }
+ return (0);
+}
+
+int
+fifo_inactive(ap)
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
+ return (0);
}
/*
@@ -385,31 +409,6 @@ fifo_bmap(ap)
}
/*
- * At the moment we do not do any locking.
- */
-/* ARGSUSED */
-static int
-fifo_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/* ARGSUSED */
-static int
-fifo_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/*
* Device close routine
*/
/* ARGSUSED */
@@ -426,16 +425,16 @@ fifo_close(ap)
register struct fifoinfo *fip = vp->v_fifoinfo;
int error1, error2;
- if (ap->a_fflag & FWRITE) {
- fip->fi_writers--;
- if (fip->fi_writers == 0)
- socantrcvmore(fip->fi_readsock);
- }
if (ap->a_fflag & FREAD) {
fip->fi_readers--;
if (fip->fi_readers == 0)
socantsendmore(fip->fi_writesock);
}
+ if (ap->a_fflag & FWRITE) {
+ fip->fi_writers--;
+ if (fip->fi_writers == 0)
+ socantrcvmore(fip->fi_readsock);
+ }
if (vp->v_usecount > 1)
return (0);
error1 = soclose(fip->fi_readsock);
diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c
index de4bf5e..a891ddc 100644
--- a/sys/fs/msdosfs/msdosfs_denode.c
+++ b/sys/fs/msdosfs/msdosfs_denode.c
@@ -124,7 +124,7 @@ msdosfs_hashget(dev, dirclust, diroff)
(void) tsleep((caddr_t)dep, PINOD, "msdhgt", 0);
break;
}
- if (!vget(DETOV(dep), 1))
+ if (!vget(DETOV(dep), LK_EXCLUSIVE | LK_INTERLOCK, curproc))
return dep;
break;
}
@@ -259,7 +259,7 @@ deget(pmp, dirclust, diroffset, direntptr, depp)
* can't be accessed until we've read it in and have done what we
* need to it.
*/
- VOP_LOCK(nvp);
+ vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY, curproc);
msdosfs_hashins(ldep);
/*
@@ -716,7 +716,7 @@ msdosfs_inactive(ap)
printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n",
dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
#endif
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
error = detrunc(dep, (u_long) 0, 0, NOCRED, NULL);
dep->de_flag |= DE_UPDATE;
@@ -726,7 +726,7 @@ msdosfs_inactive(ap)
TIMEVAL_TO_TIMESPEC(&time, &ts);
deupdat(dep, &ts, 0);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curproc);
dep->de_flag = 0;
/*
diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
index 60236b8..6617f9e 100644
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -54,6 +54,7 @@
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <msdosfs/bpb.h>
#include <msdosfs/direntry.h>
@@ -156,14 +157,14 @@ msdosfs_lookup(ap)
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, curproc);
+ error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
}
if (!error) {
@@ -183,9 +184,9 @@ msdosfs_lookup(ap)
}
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
}
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (error)
return error;
vdp = pdp;
@@ -345,7 +346,7 @@ notfound:;
/* dp->de_flag |= DE_UPDATE; never update dos directories */
cnp->cn_flags |= SAVENAME;
if (!lockparent)/* leave searched dir locked? */
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
return EJUSTRETURN;
}
/*
@@ -398,7 +399,7 @@ foundroot:;
}
*vpp = DETOV(tdp);
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
if (bp)
brelse(bp);
return 0;
@@ -428,7 +429,7 @@ foundroot:;
*vpp = DETOV(tdp);
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
if (bp)
brelse(bp);
return 0;
@@ -439,16 +440,16 @@ foundroot:;
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
error = deget(pmp, cluster, diroff, dep, &tdp);
if (error) {
- VOP_LOCK(pdp);
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (bp)
brelse(bp);
return error;
}
if (lockparent && (flags & ISLASTCN)
- && (error = VOP_LOCK(pdp))) {
+ && (error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc))) {
vput(DETOV(tdp));
return error;
}
@@ -464,7 +465,7 @@ foundroot:;
return error;
}
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
*vpp = DETOV(tdp);
}
if (bp)
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index 5669c63..d0c8cdb 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -130,10 +130,10 @@ msdosfs_mount(mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp))
+ if (vfs_busy(mp, LK_NOWAIT, 0, p))
return EBUSY;
error = vflush(mp, NULLVP, flags);
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
if (!error && (mp->mnt_flag & MNT_RELOAD))
/* not yet implemented */
@@ -707,7 +707,7 @@ loop:
if ((dep->de_flag & (DE_MODIFIED | DE_UPDATE)) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL)
continue;
- if (vget(vp, 1)) /* not there anymore? */
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) /* not there anymore? */
goto loop;
error = VOP_FSYNC(vp, cred, waitfor, p);
if (error)
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index bc4e12e..0f4deae 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1172,17 +1172,17 @@ msdosfs_rename(ap)
*/
if (newparent == 0) {
/* tddep and fddep point to the same denode here */
- VOP_LOCK(ap->a_fvp); /* ap->a_fdvp is already locked */
+ vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc); /* ap->a_fdvp is already locked */
error = readep(fddep->de_pmp, fdep->de_dirclust,
fdep->de_diroffset, &bp, &ep);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
bcopy(toname, ep->deName, 11);
error = bwrite(bp);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
bcopy(toname, fdep->de_Name, 11); /* update denode */
@@ -1204,7 +1204,7 @@ msdosfs_rename(ap)
* will also insure that the directory entry on disk has a
* filesize of zero.
*/
- VOP_LOCK(ap->a_fvp);
+ vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc);
bcopy(toname, fdep->de_Name, 11); /* update denode */
if (fdep->de_Attributes & ATTR_DIRECTORY) {
dirsize = fdep->de_FileSize;
@@ -1216,22 +1216,22 @@ msdosfs_rename(ap)
}
if (error) {
/* should put back filename */
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
- VOP_LOCK(ap->a_fdvp);
+ vn_lock(ap->a_fdvp, LK_EXCLUSIVE | LK_RETRY, curproc);
error = readep(fddep->de_pmp, fddep->de_fndclust,
fddep->de_fndoffset, &bp, &ep);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
goto bad;
}
ep->deName[0] = SLOT_DELETED;
error = bwrite(bp);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
goto bad;
}
if (!sourceisadirectory) {
@@ -1239,7 +1239,7 @@ msdosfs_rename(ap)
fdep->de_diroffset = tddep->de_fndoffset;
reinsert(fdep);
}
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
}
/* fdep is still locked here */
@@ -1259,19 +1259,19 @@ msdosfs_rename(ap)
NOCRED, &bp);
if (error) {
/* should really panic here, fs is corrupt */
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
dotdotp = (struct direntry *) bp->b_data + 1;
putushort(dotdotp->deStartCluster, tddep->de_StartCluster);
error = bwrite(bp);
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
if (error) {
/* should really panic here, fs is corrupt */
goto bad;
}
} else
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
bad: ;
vrele(DETOV(fdep));
vrele(DETOV(fddep));
diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h
index 7b0a22e..77c6add 100644
--- a/sys/fs/msdosfs/msdosfsmount.h
+++ b/sys/fs/msdosfs/msdosfsmount.h
@@ -169,3 +169,15 @@ struct msdosfsmount {
(((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift)
int msdosfs_init __P((void));
+
+/*
+ * Arguments to mount MSDOS filesystems.
+ */
+struct msdosfs_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 */
+};
+
diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h
index beadb42..70a81b2 100644
--- a/sys/fs/nullfs/null.h
+++ b/sys/fs/nullfs/null.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)null.h 8.2 (Berkeley) 1/21/94
+ * @(#)null.h 8.3 (Berkeley) 8/20/94
*
* $FreeBSD$
*/
@@ -52,8 +52,7 @@ struct null_mount {
* A cache of vnode references
*/
struct null_node {
- struct null_node *null_forw; /* Hash chain */
- struct null_node *null_back;
+ LIST_ENTRY(null_node) null_hash; /* Hash list */
struct vnode *null_lowervp; /* VREFed once */
struct vnode *null_vnode; /* Back pointer */
};
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index a14a7e4..4418631 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -33,13 +33,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)null_subr.c 8.4 (Berkeley) 1/21/94
+ * @(#)null_subr.c 8.7 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -48,11 +49,8 @@
#include <sys/malloc.h>
#include <miscfs/nullfs/null.h>
-extern int nullfs_init __P((void));
-
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NNULLNODECACHE 16
-#define NULL_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NNULLNODECACHE-1))
/*
* Null layer cache:
@@ -62,51 +60,32 @@ extern int nullfs_init __P((void));
* alias is removed the lower vnode is vrele'd.
*/
-/*
- * Cache head
- */
-struct null_node_cache {
- struct null_node *ac_forw;
- struct null_node *ac_back;
-};
-
-static struct null_node_cache null_node_cache[NNULLNODECACHE];
+#define NULL_NHASH(vp) \
+ (&null_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & null_node_hash])
+LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
+u_long null_node_hash;
static int null_node_alloc __P((struct mount *mp, struct vnode *lowervp,
struct vnode **vpp));
static struct vnode *
null_node_find __P((struct mount *mp, struct vnode *lowervp));
-static struct null_node_cache *
- null_node_hash __P((struct vnode *lowervp));
/*
* Initialise cache headers
*/
int
-nullfs_init()
+nullfs_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct null_node_cache *ac;
+
#ifdef NULLFS_DIAGNOSTIC
printf("nullfs_init\n"); /* printed during system boot */
#endif
-
- for (ac = null_node_cache; ac < null_node_cache + NNULLNODECACHE; ac++)
- ac->ac_forw = ac->ac_back = (struct null_node *) ac;
+ null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
return (0);
}
/*
- * Compute hash list for given lower vnode
- */
-static struct null_node_cache *
-null_node_hash(lowervp)
-struct vnode *lowervp;
-{
-
- return (&null_node_cache[NULL_NHASH(lowervp)]);
-}
-
-/*
* Return a VREF'ed alias for lower vnode if already exists, else 0.
*/
static struct vnode *
@@ -114,7 +93,8 @@ null_node_find(mp, lowervp)
struct mount *mp;
struct vnode *lowervp;
{
- struct null_node_cache *hd;
+ struct proc *p = curproc; /* XXX */
+ struct null_node_hashhead *hd;
struct null_node *a;
struct vnode *vp;
@@ -124,9 +104,9 @@ null_node_find(mp, lowervp)
* the lower vnode. If found, the increment the null_node
* reference count (but NOT the lower vnode's VREF counter).
*/
- hd = null_node_hash(lowervp);
+ hd = NULL_NHASH(lowervp);
loop:
- for (a = hd->ac_forw; a != (struct null_node *) hd; a = a->null_forw) {
+ for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
vp = NULLTOV(a);
/*
@@ -134,7 +114,7 @@ loop:
* stuff, but we don't want to lock
* the lower node.
*/
- if (vget(vp, 0)) {
+ if (vget(vp, 0, p)) {
printf ("null_node_find: vget failed.\n");
goto loop;
};
@@ -157,7 +137,7 @@ null_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
- struct null_node_cache *hd;
+ struct null_node_hashhead *hd;
struct null_node *xp;
struct vnode *othervp, *vp;
int error;
@@ -194,8 +174,8 @@ null_node_alloc(mp, lowervp, vpp)
return 0;
};
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
- hd = null_node_hash(lowervp);
- insque(xp, hd);
+ hd = NULL_NHASH(lowervp);
+ LIST_INSERT_HEAD(hd, xp, null_hash);
return 0;
}
@@ -250,9 +230,8 @@ null_node_create(mp, lowervp, newvpp)
#ifdef DIAGNOSTIC
if (lowervp->v_usecount < 1) {
/* Should never happen... */
- vprint ("null_node_create: alias ",aliasvp);
- vprint ("null_node_create: lower ",lowervp);
- printf ("null_node_create: lower has 0 usecount.\n");
+ vprint ("null_node_create: alias ", aliasvp);
+ vprint ("null_node_create: lower ", lowervp);
panic ("null_node_create: lower has 0 usecount.");
};
#endif
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index e2aeeba..339b7c1 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -46,7 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -55,7 +55,7 @@
#include <sys/malloc.h>
#include <miscfs/nullfs/null.h>
-extern int nullfs_init __P((void));
+extern int nullfs_init __P((struct vfsconf *));
static int nullfs_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -146,7 +146,7 @@ nullfs_mount(mp, path, data, ndp, p)
/*
* Unlock the node (either the lower or the alias)
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
/*
* Make sure the node alias worked
*/
@@ -166,7 +166,7 @@ nullfs_mount(mp, path, data, ndp, p)
if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) xmp;
- getnewfsid(mp, MOUNT_LOFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -212,12 +212,8 @@ nullfs_unmount(mp, mntflags, p)
printf("nullfs_unmount(mp = %x)\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
@@ -259,6 +255,7 @@ nullfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef NULLFS_DIAGNOSTIC
@@ -273,7 +270,7 @@ nullfs_root(mp, vpp)
*/
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return 0;
}
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index ec279bc..c1af96f 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -33,7 +33,13 @@
* 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: null_vnops.c,v 1.11.2000.1 1996/09/17 14:32:31 peter Exp $
+ * ...and...
+ * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*
* $FreeBSD$
*/
@@ -88,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
@@ -178,7 +192,7 @@ static int null_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW,
&null_bug_bypass, 0, "");
-static int null_bypass __P((struct vop_generic_args *ap));
+int null_bypass __P((struct vop_generic_args *ap));
static int null_bwrite __P((struct vop_bwrite_args *ap));
static int null_getattr __P((struct vop_getattr_args *ap));
static int null_inactive __P((struct vop_inactive_args *ap));
@@ -211,7 +225,7 @@ static int null_strategy __P((struct vop_strategy_args *ap));
* - all mapped vnodes are of our vnode-type (NEEDSWORK:
* problems on rmdir'ing mount points and renaming?)
*/
-static int
+int
null_bypass(ap)
struct vop_generic_args /* {
struct vnodeop_desc *a_desc;
@@ -254,7 +268,8 @@ null_bypass(ap)
* 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)->v_op != null_vnodeop_p) {
+ if (i && (*this_vp_p == NULL ||
+ (*this_vp_p)->v_op != null_vnodeop_p)) {
old_vps[i] = NULL;
} else {
old_vps[i] = *this_vp_p;
@@ -317,6 +332,105 @@ null_bypass(ap)
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.
+ */
+static int
+null_lookup(ap)
+ struct vop_lookup_args /* {
+ struct vnode * a_dvp;
+ struct vnode ** a_vpp;
+ struct componentname * a_cnp;
+ } */ *ap;
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ 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;
+ unlockargs.a_p = p;
+ vop_nounlock(&unlockargs);
+ }
+ if (vp != NULL && VOP_ISLOCKED(vp)) {
+ lockargs.a_vp = vp;
+ lockargs.a_flags = LK_SHARED;
+ lockargs.a_p = p;
+ vop_nolock(&lockargs);
+ }
+ return (error);
+}
+
+/*
+ * Setattr call. Disallow write attempts if the layer is mounted read-only.
+ */
+int
+null_setattr(ap)
+ 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;
+{
+ 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.ts_sec != VNOVAL ||
+ vap->va_mtime.ts_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.
@@ -331,19 +445,90 @@ null_getattr(ap)
} */ *ap;
{
int error;
- error = null_bypass(ap);
- if (error)
+
+ if (error = null_bypass(ap))
return (error);
/* Requires that arguments be restored. */
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
-
static int
+null_access(ap)
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
+{
+ 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;
+ }
+ }
+ 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(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ vop_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(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ vop_nounlock(ap);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
+int
null_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
/*
@@ -358,6 +543,7 @@ null_inactive(ap)
* like they do in the name lookup cache code.
* That's too much work for now.
*/
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -365,6 +551,7 @@ static int
null_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
@@ -377,14 +564,13 @@ null_reclaim(ap)
*/
/* After this assignment, this node will not be re-used. */
xp->null_lowervp = NULL;
- remque(xp);
+ LIST_REMOVE(xp, null_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele (lowervp);
return (0);
}
-
static int
null_print(ap)
struct vop_print_args /* {
@@ -396,7 +582,6 @@ null_print(ap)
return (0);
}
-
/*
* XXX - vop_strategy must be hand coded because it has no
* vnode in its arguments.
@@ -422,7 +607,6 @@ null_strategy(ap)
return (error);
}
-
/*
* XXX - like vop_strategy, vop_bwrite must be hand coded because it has no
* vnode in its arguments.
@@ -455,7 +639,12 @@ vop_t **null_vnodeop_p;
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)null_bypass },
+ { &vop_lookup_desc, (vop_t *)null_lookup },
+ { &vop_setattr_desc, (vop_t *)null_setattr },
{ &vop_getattr_desc, (vop_t *)null_getattr },
+ { &vop_access_desc, (vop_t *)null_access },
+ { &vop_lock_desc, (vop_t *)null_lock },
+ { &vop_unlock_desc, (vop_t *)null_unlock },
{ &vop_inactive_desc, (vop_t *)null_inactive },
{ &vop_reclaim_desc, (vop_t *)null_reclaim },
{ &vop_print_desc, (vop_t *)null_print },
diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c
index a980f65..74e1542 100644
--- a/sys/fs/portalfs/portal_vfsops.c
+++ b/sys/fs/portalfs/portal_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)portal_vfsops.c 8.6 (Berkeley) 1/21/94
+ * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -62,28 +62,18 @@
#include <sys/un.h>
#include <miscfs/portal/portal.h>
-static int portal_init __P((void));
static int portal_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
static int portal_start __P((struct mount *mp, int flags, struct proc *p));
static int portal_unmount __P((struct mount *mp, int mntflags,
struct proc *p));
static int portal_root __P((struct mount *mp, struct vnode **vpp));
-static int portal_quotactl __P((struct mount *mp, int cmd, uid_t uid,
- caddr_t arg, struct proc *p));
static int portal_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int portal_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
-static int portal_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int portal_fhtovp __P((struct mount *mp, struct fid *fhp,
- struct mbuf *nam, struct vnode **vpp,
- int *exflagsp, struct ucred **credanonp));
-static int portal_vptofh __P((struct vnode *vp, struct fid *fhp));
static int
-portal_init()
+portal_init(vfsp)
+ struct vfsconf *vfsp;
{
return (0);
@@ -150,7 +140,7 @@ portal_mount(mp, path, data, ndp, p)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) fmp;
- getnewfsid(mp, MOUNT_PORTAL);
+ vfs_getnewfsid(mp);
(void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -186,12 +176,8 @@ portal_unmount(mp, mntflags, p)
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
@@ -241,39 +227,26 @@ portal_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
-
/*
* Return locked reference to root.
*/
vp = VFSTOPORTAL(mp)->pm_root;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
static int
-portal_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
portal_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
struct proc *p;
{
- sbp->f_type = MOUNT_PORTAL;
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
@@ -283,6 +256,7 @@ portal_statfs(mp, sbp, p)
sbp->f_files = 1; /* Allow for "." */
sbp->f_ffree = 0; /* See comments above */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -290,48 +264,17 @@ portal_statfs(mp, sbp, p)
return (0);
}
-static int
-portal_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
-
- return (0);
-}
-
-static int
-portal_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-portal_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-portal_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+#define portal_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define portal_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define portal_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+#define portal_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define portal_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define portal_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
static struct vfsops portal_vfsops = {
portal_mount,
diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c
index 8135a5e..19b439c 100644
--- a/sys/fs/portalfs/portal_vnops.c
+++ b/sys/fs/portalfs/portal_vnops.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94
+ * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
*
* $FreeBSD$
*/
@@ -112,17 +112,25 @@ portal_lookup(ap)
struct componentname * a_cnp;
} */ *ap;
{
- char *pname = ap->a_cnp->cn_nameptr;
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode **vpp = ap->a_vpp;
+ struct vnode *dvp = ap->a_dvp;
+ char *pname = cnp->cn_nameptr;
struct portalnode *pt;
int error;
struct vnode *fvp = 0;
char *path;
int size;
- if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
- *ap->a_vpp = ap->a_dvp;
- VREF(ap->a_dvp);
- /*VOP_LOCK(ap->a_dvp);*/
+ *vpp = NULLVP;
+
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
+ return (EROFS);
+
+ if (cnp->cn_namelen == 1 && *pname == '.') {
+ *vpp = dvp;
+ VREF(dvp);
+ /*VOP_LOCK(dvp);*/
return (0);
}
@@ -134,7 +142,7 @@ portal_lookup(ap)
MALLOC(pt, struct portalnode *, sizeof(struct portalnode),
M_TEMP, M_WAITOK);
- error = getnewvnode(VT_PORTAL, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp);
+ error = getnewvnode(VT_PORTAL, dvp->v_mount, portal_vnodeop_p, &fvp);
if (error) {
FREE(pt, M_TEMP);
goto bad;
@@ -148,22 +156,20 @@ portal_lookup(ap)
*/
for (size = 0, path = pname; *path; path++)
size++;
- ap->a_cnp->cn_consume = size - ap->a_cnp->cn_namelen;
+ cnp->cn_consume = size - cnp->cn_namelen;
pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK);
pt->pt_size = size+1;
bcopy(pname, pt->pt_arg, pt->pt_size);
pt->pt_fileid = portal_fileid++;
- *ap->a_vpp = fvp;
+ *vpp = fvp;
/*VOP_LOCK(fvp);*/
return (0);
bad:;
- if (fvp) {
+ if (fvp)
vrele(fvp);
- }
- *ap->a_vpp = NULL;
return (error);
}
@@ -444,6 +450,7 @@ portal_getattr(ap)
{
struct vnode *vp = ap->a_vp;
struct vattr *vap = ap->a_vap;
+ struct timeval tv;
bzero(vap, sizeof(*vap));
vattr_null(vap);
@@ -452,8 +459,8 @@ portal_getattr(ap)
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
vap->va_size = DEV_BSIZE;
vap->va_blocksize = DEV_BSIZE;
- microtime((struct timeval *)&vap->va_atime);
- TIMEVAL_TO_TIMESPEC((struct timeval *)&vap->va_atime, (struct timespec *)&vap->va_atime);
+ microtime(&tv);
+ TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
vap->va_mtime = vap->va_atime;
vap->va_ctime = vap->va_ctime;
vap->va_gen = 0;
@@ -509,9 +516,19 @@ portal_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
+ /*
+ * We don't allow exporting portal mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("portal_readdir: not hungry");
+
return (0);
}
@@ -519,9 +536,11 @@ static int
portal_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -639,6 +658,7 @@ portal_badop()
#define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp)
#define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp)
#define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp)
+#define portal_revoke vop_revoke
#define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
#define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
@@ -651,12 +671,14 @@ portal_badop()
#define portal_readlink \
((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
#define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
-#define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define portal_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
#define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)
#define portal_strategy \
((int (*) __P((struct vop_strategy_args *)))portal_badop)
-#define portal_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define portal_islocked \
+ ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
+#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
#define portal_advlock \
((int (*) __P((struct vop_advlock_args *)))portal_enotsupp)
#define portal_blkatoff \
@@ -687,6 +709,7 @@ static struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
{ &vop_ioctl_desc, (vop_t *)portal_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)portal_select }, /* select */
{ &vop_mmap_desc, (vop_t *)portal_mmap }, /* mmap */
+ { &vop_revoke_desc, (vop_t *)portal_revoke }, /* revoke */
{ &vop_fsync_desc, (vop_t *)portal_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)portal_seek }, /* seek */
{ &vop_remove_desc, (vop_t *)portal_remove }, /* remove */
diff --git a/sys/fs/procfs/procfs.h b/sys/fs/procfs/procfs.h
index df01a39..ef0d7eb 100644
--- a/sys/fs/procfs/procfs.h
+++ b/sys/fs/procfs/procfs.h
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs.h 8.6 (Berkeley) 2/3/94
+ * @(#)procfs.h 8.9 (Berkeley) 5/14/95
*
+ * From:
* $FreeBSD$
*/
@@ -44,6 +45,7 @@
*/
typedef enum {
Proot, /* the filesystem root */
+ Pcurproc, /* symbolic link for curproc */
Pproc, /* a process-specific sub-directory */
Pfile, /* the executable file */
Pmem, /* the process's memory image */
@@ -97,9 +99,9 @@ struct pfsdent {
};
#define UIO_MX sizeof(struct pfsdent)
#define PROCFS_FILENO(pid, type) \
- (((type) == Proot) ? \
- 2 : \
- ((((pid)+1) << 3) + ((int) (type))))
+ (((type) < Pproc) ? \
+ ((type) + 2) : \
+ ((((pid)+1) << 4) + ((int) (type))))
/*
* Convert between pfsnode vnode
@@ -113,33 +115,33 @@ struct vfs_namemap {
int nm_val;
};
-extern int vfs_getuserstr __P((struct uio *, char *, int *));
-extern vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
+int vfs_getuserstr __P((struct uio *, char *, int *));
+vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
/* <machine/reg.h> */
struct reg;
struct fpreg;
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
-extern int procfs_freevp __P((struct vnode *));
-extern int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
-extern struct vnode *procfs_findtextvp __P((struct proc *));
-extern int procfs_sstep __P((struct proc *));
-extern void procfs_fix_sstep __P((struct proc *));
-extern int procfs_read_regs __P((struct proc *, struct reg *));
-extern int procfs_write_regs __P((struct proc *, struct reg *));
-extern int procfs_read_fpregs __P((struct proc *, struct fpreg *));
-extern int procfs_write_fpregs __P((struct proc *, struct fpreg *));
-extern int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_freevp __P((struct vnode *));
+int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
+struct vnode *procfs_findtextvp __P((struct proc *));
+int procfs_sstep __P((struct proc *));
+void procfs_fix_sstep __P((struct proc *));
+int procfs_read_regs __P((struct proc *, struct reg *));
+int procfs_write_regs __P((struct proc *, struct reg *));
+int procfs_read_fpregs __P((struct proc *, struct fpreg *));
+int procfs_write_fpregs __P((struct proc *, struct fpreg *));
+int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-/* check to see if the process has the "items" (regs/file) */
+/* functions to check whether or not files should be displayed */
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
diff --git a/sys/fs/procfs/procfs_ctl.c b/sys/fs/procfs/procfs_ctl.c
index 4ddf7a7..68b93dd 100644
--- a/sys/fs/procfs/procfs_ctl.c
+++ b/sys/fs/procfs/procfs_ctl.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_ctl.c 8.3 (Berkeley) 1/21/94
+ * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
@@ -51,13 +52,13 @@
#include <sys/resourcevar.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_extern.h>
-
+#include <sys/ptrace.h>
#include <miscfs/procfs/procfs.h>
+#ifndef FIX_SSTEP
+#define FIX_SSTEP(p)
+#endif
+
/*
* True iff process (p) is in trace wait state
* relative to process (curp)
@@ -67,13 +68,6 @@
(p)->p_pptr == (curp) && \
((p)->p_flag & P_TRACED))
-#ifdef notdef
-#define FIX_SSTEP(p) { \
- procfs_fix_sstep(p); \
- } \
-}
-#endif
-
#define PROCFS_CTL_ATTACH 1
#define PROCFS_CTL_DETACH 2
#define PROCFS_CTL_STEP 3
@@ -220,8 +214,10 @@ procfs_control(curp, p, op)
*/
case PROCFS_CTL_STEP:
PHOLD(p);
- procfs_sstep(p);
+ error = procfs_sstep(p);
PRELE(p);
+ if (error)
+ return (error);
break;
/*
diff --git a/sys/fs/procfs/procfs_fpregs.c b/sys/fs/procfs/procfs_fpregs.c
index a3cad5f..841cf76 100644
--- a/sys/fs/procfs/procfs_fpregs.c
+++ b/sys/fs/procfs/procfs_fpregs.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_fpregs.c 8.1 (Berkeley) 1/27/94
+ * @(#)procfs_fpregs.c 8.2 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c
index 27c44fa..40c40d8 100644
--- a/sys/fs/procfs/procfs_map.c
+++ b/sys/fs/procfs/procfs_map.c
@@ -59,7 +59,7 @@
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
#include <vm/vm_inherit.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_page.h>
diff --git a/sys/fs/procfs/procfs_mem.c b/sys/fs/procfs/procfs_mem.c
index 4e8fac6..06364e5 100644
--- a/sys/fs/procfs/procfs_mem.c
+++ b/sys/fs/procfs/procfs_mem.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_mem.c 8.4 (Berkeley) 1/21/94
+ * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
*
* $FreeBSD$
*/
@@ -55,7 +55,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_kern.h>
@@ -295,14 +295,11 @@ procfs_domem(curp, p, pfs, uio)
struct pfsnode *pfs;
struct uio *uio;
{
- int error;
if (uio->uio_resid == 0)
return (0);
- error = procfs_rwmem(p, uio);
-
- return (error);
+ return (procfs_rwmem(p, uio));
}
/*
@@ -320,5 +317,6 @@ struct vnode *
procfs_findtextvp(p)
struct proc *p;
{
+
return (p->p_textvp);
}
diff --git a/sys/fs/procfs/procfs_regs.c b/sys/fs/procfs/procfs_regs.c
index 9282a3a..56ef233 100644
--- a/sys/fs/procfs/procfs_regs.c
+++ b/sys/fs/procfs/procfs_regs.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_regs.c 8.3 (Berkeley) 1/27/94
+ * @(#)procfs_regs.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c
index 432918d..76974b5 100644
--- a/sys/fs/procfs/procfs_status.c
+++ b/sys/fs/procfs/procfs_status.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94
+ * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
@@ -142,7 +143,7 @@ procfs_dostatus(curp, p, pfs, uio)
xlen = ps - psbuf;
xlen -= uio->uio_offset;
ps = psbuf + uio->uio_offset;
- xlen = min(xlen, uio->uio_resid);
+ xlen = imin(xlen, uio->uio_resid);
if (xlen <= 0)
error = 0;
else
diff --git a/sys/fs/procfs/procfs_subr.c b/sys/fs/procfs/procfs_subr.c
index d9b3d2f..5ee78f0 100644
--- a/sys/fs/procfs/procfs_subr.c
+++ b/sys/fs/procfs/procfs_subr.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_subr.c 8.4 (Berkeley) 1/27/94
+ * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -84,18 +84,21 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
long pid;
pfstype pfs_type;
{
- int error;
+ struct proc *p = curproc; /* XXX */
struct pfsnode *pfs;
+ struct vnode *vp;
struct pfsnode **pp;
+ int error;
loop:
for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) {
+ vp = PFSTOV(pfs);
if (pfs->pfs_pid == pid &&
pfs->pfs_type == pfs_type &&
- PFSTOV(pfs)->v_mount == mp) {
- if (vget(pfs->pfs_vnode, 0))
+ vp->v_mount == mp) {
+ if (vget(vp, 0, p))
goto loop;
- *vpp = pfs->pfs_vnode;
+ *vpp = vp;
return (0);
}
}
@@ -118,17 +121,18 @@ loop:
*/
MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
- error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp);
- if (error) {
+ if (error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) {
FREE(pfs, M_TEMP);
goto out;
}
+ vp = *vpp;
+
+ vp->v_data = pfs;
- (*vpp)->v_data = pfs;
pfs->pfs_next = 0;
pfs->pfs_pid = (pid_t) pid;
pfs->pfs_type = pfs_type;
- pfs->pfs_vnode = *vpp;
+ pfs->pfs_vnode = vp;
pfs->pfs_flags = 0;
pfs->pfs_lockowner = 0;
pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
@@ -138,33 +142,41 @@ loop:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
+ vp->v_type = VDIR;
+ vp->v_flag = VROOT;
+ break;
+
+ case Pcurproc: /* /proc/curproc = lr--r--r-- */
+ pfs->pfs_mode = (VREAD) |
+ (VREAD >> 3) |
+ (VREAD >> 6);
+ vp->v_type = VLNK;
break;
case Pproc:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
+ vp->v_type = VDIR;
break;
case Pfile:
- pfs->pfs_mode = (VREAD|VWRITE);
- break;
-
case Pmem:
pfs->pfs_mode = (VREAD|VWRITE) |
(VREAD) >> 3;;
break;
case Pregs:
- pfs->pfs_mode = (VREAD|VWRITE);
- break;
-
case Pfpregs:
pfs->pfs_mode = (VREAD|VWRITE);
+ vp->v_type = VREG;
break;
case Pctl:
+ case Pnote:
+ case Pnotepg:
pfs->pfs_mode = (VWRITE);
+ vp->v_type = VREG;
break;
case Ptype:
@@ -173,14 +185,7 @@ loop:
pfs->pfs_mode = (VREAD) |
(VREAD >> 3) |
(VREAD >> 6);
- break;
-
- case Pnote:
- pfs->pfs_mode = (VWRITE);
- break;
-
- case Pnotepg:
- pfs->pfs_mode = (VWRITE);
+ vp->v_type = VREG;
break;
default:
@@ -316,8 +321,7 @@ vfs_getuserstr(uio, buf, buflenp)
return (EMSGSIZE);
xlen = uio->uio_resid;
- error = uiomove(buf, xlen, uio);
- if (error)
+ if (error = uiomove(buf, xlen, uio))
return (error);
/* allow multiple writes without seeks */
@@ -339,6 +343,7 @@ vfs_findname(nm, buf, buflen)
char *buf;
int buflen;
{
+
for (; nm->nm_name; nm++)
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
return (nm);
diff --git a/sys/fs/procfs/procfs_vfsops.c b/sys/fs/procfs/procfs_vfsops.c
index 433b391..5387126 100644
--- a/sys/fs/procfs/procfs_vfsops.c
+++ b/sys/fs/procfs/procfs_vfsops.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_vfsops.c 8.4 (Berkeley) 1/21/94
+ * @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95
*
* $FreeBSD$
*/
@@ -56,24 +56,14 @@
#include <miscfs/procfs/procfs.h>
#include <vm/vm.h> /* for PAGE_SIZE */
-static int procfs_fhtovp __P((struct mount *mp, struct fid *fhp,
- struct mbuf *nam, struct vnode **vpp,
- int *exflagsp, struct ucred **credanonp));
-static int procfs_init __P((void));
+static int procfs_init __P((struct vfsconf *vfsp));
static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
-static int procfs_quotactl __P((struct mount *mp, int cmds, uid_t uid,
- caddr_t arg, struct proc *p));
static int procfs_start __P((struct mount *mp, int flags, struct proc *p));
static int procfs_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int procfs_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
static int procfs_unmount __P((struct mount *mp, int mntflags,
struct proc *p));
-static int procfs_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int procfs_vptofh __P((struct vnode *vp, struct fid *fhp));
/*
* VFS Operations.
@@ -101,7 +91,7 @@ procfs_mount(mp, path, data, ndp, p)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = 0;
- getnewfsid(mp, MOUNT_PROCFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -125,12 +115,8 @@ procfs_unmount(mp, mntflags, p)
int error;
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;
- }
error = vflush(mp, 0, flags);
if (error)
@@ -144,24 +130,10 @@ procfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- struct pfsnode *pfs;
- struct vnode *vp;
- int error;
-
- error = procfs_allocvp(mp, &vp, (pid_t) 0, Proot);
- if (error)
- return (error);
-
- vp->v_type = VDIR;
- vp->v_flag = VROOT;
- pfs = VTOPFS(vp);
- *vpp = vp;
- return (0);
+ return (procfs_allocvp(mp, vpp, 0, Proot));
}
-/*
- */
/* ARGSUSED */
static int
procfs_start(mp, flags, p)
@@ -182,7 +154,6 @@ procfs_statfs(mp, sbp, p)
struct statfs *sbp;
struct proc *p;
{
- sbp->f_type = MOUNT_PROCFS;
sbp->f_bsize = PAGE_SIZE;
sbp->f_iosize = PAGE_SIZE;
sbp->f_blocks = 1; /* avoid divide by zero in some df's */
@@ -192,6 +163,7 @@ procfs_statfs(mp, sbp, p)
sbp->f_ffree = maxproc - nprocs; /* approx */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -200,68 +172,25 @@ procfs_statfs(mp, sbp, p)
return (0);
}
-
-static int
-procfs_quotactl(mp, cmds, uid, arg, p)
- struct mount *mp;
- int cmds;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
static int
-procfs_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
+procfs_init(vfsp)
+ struct vfsconf *vfsp;
{
return (0);
}
-static int
-procfs_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-procfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EINVAL);
-}
-
-static int
-procfs_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return EINVAL;
-}
-
-static int
-procfs_init()
-{
-
- return (0);
-}
+#define procfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))einval)
+#define procfs_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define procfs_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+#define procfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define procfs_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define procfs_vptofh ((int (*) __P((struct vnode *, struct fid *)))einval)
static struct vfsops procfs_vfsops = {
procfs_mount,
diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c
index f497563..85be3ea 100644
--- a/sys/fs/procfs/procfs_vnops.c
+++ b/sys/fs/procfs/procfs_vnops.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
+ * Copyright (c) 1993, 1995 Jan-Simon Pendry
+ * Copyright (c) 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_vnops.c 8.6 (Berkeley) 2/7/94
+ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
* $FreeBSD$
*/
@@ -55,8 +55,9 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/resourcevar.h>
-#include <miscfs/procfs/procfs.h>
#include <vm/vm.h> /* for PAGE_SIZE */
+#include <machine/reg.h>
+#include <miscfs/procfs/procfs.h>
static int procfs_abortop __P((struct vop_abortop_args *));
static int procfs_access __P((struct vop_access_args *));
@@ -78,29 +79,30 @@ static int procfs_setattr __P((struct vop_setattr_args *));
* process-specific sub-directories. It is
* used in procfs_lookup and procfs_readdir
*/
-static struct pfsnames {
- u_short d_namlen;
- char d_name[PROCFS_NAMELEN];
- pfstype d_pfstype;
- int (*d_valid) __P((struct proc *));
-} procent[] = {
+struct proc_target {
+ u_char pt_type;
+ u_char pt_namlen;
+ char *pt_name;
+ pfstype pt_pfstype;
+ int (*pt_valid) __P((struct proc *p));
+} proc_targets[] = {
#define N(s) sizeof(s)-1, s
- /* namlen, nam, type validp */
- { N("."), Pproc, NULL },
- { N(".."), Proot, NULL },
- { N("file"), Pfile, procfs_validfile },
- { N("mem"), Pmem, NULL },
- { N("regs"), Pregs, procfs_validregs },
- { N("fpregs"), Pfpregs, procfs_validfpregs },
- { N("ctl"), Pctl, NULL },
- { N("status"), Pstatus, NULL },
- { N("note"), Pnote, NULL },
- { N("notepg"), Pnotepg, NULL },
- { N("map"), Pmap, procfs_validmap },
- { N("etype"), Ptype, procfs_validtype },
+ /* name type validp */
+ { DT_DIR, N("."), Pproc, NULL },
+ { DT_DIR, N(".."), Proot, NULL },
+ { DT_REG, N("file"), Pfile, procfs_validfile },
+ { DT_REG, N("mem"), Pmem, NULL },
+ { DT_REG, N("regs"), Pregs, procfs_validregs },
+ { DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
+ { DT_REG, N("ctl"), Pctl, NULL },
+ { DT_REG, N("status"), Pstatus, NULL },
+ { DT_REG, N("note"), Pnote, NULL },
+ { DT_REG, N("notepg"), Pnotepg, NULL },
+ { DT_REG, N("map"), Pmap, procfs_validmap },
+ { DT_REG, N("etype"), Ptype, procfs_validtype },
#undef N
};
-#define Nprocent (sizeof(procent)/sizeof(procent[0]))
+static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
static pid_t atopid __P((const char *, u_int));
@@ -117,7 +119,12 @@ static pid_t atopid __P((const char *, u_int));
*/
static int
procfs_open(ap)
- struct vop_open_args *ap;
+ struct vop_open_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
@@ -126,11 +133,10 @@ procfs_open(ap)
if (PFIND(pfs->pfs_pid) == 0)
return (ENOENT); /* was ESRCH, jsp */
- if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
- ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
+ if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) ||
+ (pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))
return (EBUSY);
-
if (ap->a_mode & FWRITE)
pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
@@ -152,7 +158,12 @@ procfs_open(ap)
*/
static int
procfs_close(ap)
- struct vop_close_args *ap;
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
@@ -174,14 +185,51 @@ procfs_close(ap)
*/
static int
procfs_ioctl(ap)
- struct vop_ioctl_args *ap;
+ struct vop_ioctl_args /* {
+ struct vnode *a_vp;
+ int a_command;
+ caddr_t a_data;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
return (ENOTTY);
}
/*
- * _inactive is called when the pfsnode
+ * do block mapping for pfsnode (vp).
+ * since we don't use the buffer cache
+ * for procfs this function should never
+ * be called. in any case, it's not clear
+ * what part of the kernel ever makes use
+ * of this function. for sanity, this is the
+ * usual no-op bmap, although returning
+ * (EIO) would be a reasonable alternative.
+ */
+int
+procfs_bmap(ap)
+ struct vop_bmap_args /* {
+ struct vnode *a_vp;
+ daddr_t a_bn;
+ struct vnode **a_vpp;
+ daddr_t *a_bnp;
+ int *a_runp;
+ } */ *ap;
+{
+
+ if (ap->a_vpp != NULL)
+ *ap->a_vpp = ap->a_vp;
+ if (ap->a_bnp != NULL)
+ *ap->a_bnp = ap->a_bn;
+ if (ap->a_runp != NULL)
+ *ap->a_runp = 0;
+ return (0);
+}
+
+/*
+ * procfs_inactive is called when the pfsnode
* is vrele'd and the reference count goes
* to zero. (vp) will be on the vnode free
* list, so to get it back vget() must be
@@ -194,16 +242,20 @@ procfs_ioctl(ap)
* chances are that the process will still be
* there and PFIND is not free.
*
- * (vp) is not locked on entry or exit.
+ * (vp) is locked on entry, but must be unlocked on exit.
*/
static int
procfs_inactive(ap)
- struct vop_inactive_args *ap;
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
- struct pfsnode *pfs = VTOPFS(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct pfsnode *pfs = VTOPFS(vp);
+ VOP_UNLOCK(vp, 0, ap->a_p);
if (PFIND(pfs->pfs_pid) == 0)
- vgone(ap->a_vp);
+ vgone(vp);
return (0);
}
@@ -217,12 +269,12 @@ procfs_inactive(ap)
*/
static int
procfs_reclaim(ap)
- struct vop_reclaim_args *ap;
+ struct vop_reclaim_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
- int error;
- error = procfs_freevp(ap->a_vp);
- return (error);
+ return (procfs_freevp(ap->a_vp));
}
/*
@@ -269,13 +321,14 @@ procfs_pathconf(ap)
*/
static int
procfs_print(ap)
- struct vop_print_args *ap;
+ struct vop_print_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
- printf("tag VT_PROCFS, pid %lu, mode %x, flags %lx\n",
- pfs->pfs_pid,
- pfs->pfs_mode, pfs->pfs_flags);
+ printf("tag VT_PROCFS, type %s, pid %d, mode %x, flags %x\n",
+ pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
return (0);
}
@@ -287,7 +340,10 @@ procfs_print(ap)
*/
static int
procfs_abortop(ap)
- struct vop_abortop_args *ap;
+ struct vop_abortop_args /* {
+ struct vnode *a_dvp;
+ struct componentname *a_cnp;
+ } */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
@@ -316,7 +372,12 @@ procfs_badop()
*/
static int
procfs_getattr(ap)
- struct vop_getattr_args *ap;
+ struct vop_getattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
struct vattr *vap = ap->a_vap;
@@ -329,6 +390,7 @@ procfs_getattr(ap)
*/
switch (pfs->pfs_type) {
case Proot:
+ case Pcurproc:
procp = 0;
break;
@@ -353,6 +415,21 @@ procfs_getattr(ap)
vap->va_bytes = vap->va_size = 0;
/*
+ * Make all times be current TOD.
+ * It would be possible to get the process start
+ * time from the p_stat structure, but there's
+ * no "file creation" time stamp anyway, and the
+ * p_stat structure is not addressible if u. gets
+ * swapped out for that process.
+ */
+ {
+ struct timeval tv;
+ microtime(&tv);
+ TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
+ }
+ vap->va_atime = vap->va_mtime = vap->va_ctime;
+
+ /*
* If the process has exercised some setuid or setgid
* privilege, then rip away read/write permission so
* that only root can gain access.
@@ -376,21 +453,6 @@ procfs_getattr(ap)
}
/*
- * Make all times be current TOD.
- * It would be possible to get the process start
- * time from the p_stat structure, but there's
- * no "file creation" time stamp anyway, and the
- * p_stat structure is not addressible if u. gets
- * swapped out for that process.
- */
- {
- struct timeval tv;
- microtime(&tv);
- TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
- }
- vap->va_atime = vap->va_mtime = vap->va_ctime;
-
- /*
* now do the object specific fields
*
* The size could be set from struct reg, but it's hardly
@@ -402,17 +464,30 @@ procfs_getattr(ap)
switch (pfs->pfs_type) {
case Proot:
- vap->va_nlink = nprocs + 3;
+ /*
+ * Set nlink to 1 to tell fts(3) we don't actually know.
+ */
+ vap->va_nlink = 1;
+ vap->va_uid = 0;
+ vap->va_gid = 0;
+ vap->va_size = vap->va_bytes = DEV_BSIZE;
+ break;
+
+ case Pcurproc: {
+ char buf[16]; /* should be enough */
+ vap->va_nlink = 1;
vap->va_uid = 0;
vap->va_gid = 0;
- vap->va_bytes = vap->va_size = DEV_BSIZE;
+ vap->va_size = vap->va_bytes =
+ sprintf(buf, "%ld", (long)curproc->p_pid);
break;
+ }
case Pproc:
- vap->va_nlink = Nprocent;
+ vap->va_nlink = nproc_targets;
vap->va_uid = procp->p_ucred->cr_uid;
vap->va_gid = procp->p_ucred->cr_gid;
- vap->va_bytes = vap->va_size = DEV_BSIZE;
+ vap->va_size = vap->va_bytes = DEV_BSIZE;
break;
case Pfile:
@@ -436,7 +511,15 @@ procfs_getattr(ap)
case Ptype:
case Pmap:
case Pregs:
+ vap->va_bytes = vap->va_size = sizeof(struct reg);
+ vap->va_nlink = 1;
+ vap->va_uid = procp->p_ucred->cr_uid;
+ vap->va_gid = procp->p_ucred->cr_gid;
+ break;
+
case Pfpregs:
+ vap->va_bytes = vap->va_size = sizeof(struct fpreg);
+
case Pctl:
case Pstatus:
case Pnote:
@@ -455,7 +538,12 @@ procfs_getattr(ap)
static int
procfs_setattr(ap)
- struct vop_setattr_args *ap;
+ struct vop_setattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
/*
* just fake out attribute setting
@@ -484,7 +572,12 @@ procfs_setattr(ap)
*/
static int
procfs_access(ap)
- struct vop_access_args *ap;
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct vattr *vap;
struct vattr vattr;
@@ -494,8 +587,9 @@ procfs_access(ap)
* If you're the super-user,
* you always get access.
*/
- if (ap->a_cred->cr_uid == (uid_t) 0)
+ if (ap->a_cred->cr_uid == 0)
return (0);
+
vap = &vattr;
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
if (error)
@@ -510,7 +604,7 @@ procfs_access(ap)
gid_t *gp;
int i;
- (ap->a_mode) >>= 3;
+ ap->a_mode >>= 3;
gp = ap->a_cred->cr_groups;
for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++)
if (vap->va_gid == *gp)
@@ -537,18 +631,23 @@ found:
*/
static int
procfs_lookup(ap)
- struct vop_lookup_args *ap;
+ struct vop_lookup_args /* {
+ struct vnode * a_dvp;
+ struct vnode ** a_vpp;
+ struct componentname * a_cnp;
+ } */ *ap;
{
struct componentname *cnp = ap->a_cnp;
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
+ struct proc *curp = cnp->cn_proc;
int error = 0;
+ struct proc_target *pt;
+ struct vnode *fvp;
pid_t pid;
- struct vnode *nvp;
struct pfsnode *pfs;
- struct proc *procp;
- pfstype pfs_type;
+ struct proc *p;
int i;
*vpp = NULL;
@@ -559,7 +658,7 @@ procfs_lookup(ap)
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- /*VOP_LOCK(dvp);*/
+ /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
return (0);
}
@@ -570,72 +669,52 @@ procfs_lookup(ap)
return (EIO);
if (CNEQ(cnp, "curproc", 7))
- pid = cnp->cn_proc->p_pid;
- else
- pid = atopid(pname, cnp->cn_namelen);
- if (pid == NO_PID)
- return (ENOENT);
+ return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc));
- procp = PFIND(pid);
- if (procp == 0)
- return (ENOENT);
-
- error = procfs_allocvp(dvp->v_mount, &nvp, pid, Pproc);
- if (error)
- return (error);
+ pid = atopid(pname, cnp->cn_namelen);
+ if (pid == NO_PID)
+ break;
- nvp->v_type = VDIR;
- pfs = VTOPFS(nvp);
+ p = PFIND(pid);
+ if (p == 0)
+ break;
- *vpp = nvp;
- return (0);
+ return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
case Pproc:
- if (cnp->cn_flags & ISDOTDOT) {
- error = procfs_root(dvp->v_mount, vpp);
- return (error);
- }
-
- procp = PFIND(pfs->pfs_pid);
- if (procp == 0)
- return (ENOENT);
+ if (cnp->cn_flags & ISDOTDOT)
+ return (procfs_root(dvp->v_mount, vpp));
- for (i = 0; i < Nprocent; i++) {
- struct pfsnames *dp = &procent[i];
+ p = PFIND(pfs->pfs_pid);
+ if (p == 0)
+ break;
- if (cnp->cn_namelen == dp->d_namlen &&
- bcmp(pname, dp->d_name, dp->d_namlen) == 0 &&
- (dp->d_valid == NULL || (*dp->d_valid)(procp))) {
- pfs_type = dp->d_pfstype;
+ for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
+ if (cnp->cn_namelen == pt->pt_namlen &&
+ bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
+ (pt->pt_valid == NULL || (*pt->pt_valid)(p)))
goto found;
- }
}
- return (ENOENT);
+ break;
found:
- if (pfs_type == Pfile) {
- nvp = procfs_findtextvp(procp);
- if (nvp) {
- VREF(nvp);
- VOP_LOCK(nvp);
- } else {
- error = ENXIO;
- }
- } else {
- error = procfs_allocvp(dvp->v_mount, &nvp,
- pfs->pfs_pid, pfs_type);
- if (error)
- return (error);
-
- nvp->v_type = VREG;
- pfs = VTOPFS(nvp);
+ if (pt->pt_pfstype == Pfile) {
+ fvp = procfs_findtextvp(p);
+ /* We already checked that it exists. */
+ VREF(fvp);
+ vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curp);
+ *vpp = fvp;
+ return (0);
}
- *vpp = nvp;
- return (error);
+
+ return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
+ pt->pt_pfstype));
default:
return (ENOTDIR);
}
+
+ return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
}
/*
@@ -645,6 +724,7 @@ int
procfs_validfile(p)
struct proc *p;
{
+
return (procfs_findtextvp(p) != NULLVP);
}
@@ -662,7 +742,14 @@ procfs_validfile(p)
*/
static int
procfs_readdir(ap)
- struct vop_readdir_args *ap;
+ struct vop_readdir_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
+ } */ *ap;
{
struct uio *uio = ap->a_uio;
struct pfsdent d;
@@ -672,6 +759,13 @@ procfs_readdir(ap)
int count;
int i;
+ /*
+ * We don't allow exporting procfs mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("procfs_readdir: not hungry");
+
pfs = VTOPFS(ap->a_vp);
if (uio->uio_resid < UIO_MX)
@@ -693,39 +787,28 @@ procfs_readdir(ap)
*/
case Pproc: {
struct proc *p;
+ struct proc_target *pt;
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
- while (uio->uio_resid >= UIO_MX) {
- struct pfsnames *dt;
-
- if (i >= Nprocent)
- break;
-
- dt = &procent[i];
-
- /* see if we should show this one. */
- if (dt->d_valid && (*dt->d_valid)(p) == 0) {
- i++;
+ for (pt = &proc_targets[i];
+ uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
+ if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
continue;
- }
dp->d_reclen = UIO_MX;
- dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, dt->d_pfstype);
- dp->d_type = DT_REG;
- dp->d_namlen = dt->d_namlen;
- bcopy(dt->d_name, dp->d_name, sizeof(dt->d_name)-1);
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
+ dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype);
+ dp->d_namlen = pt->pt_namlen;
+ bcopy(pt->pt_name, dp->d_name, pt->pt_namlen + 1);
+ dp->d_type = pt->pt_type;
+
+ if (error = uiomove((caddr_t)dp, UIO_MX, uio))
break;
- count += UIO_MX;
- i++;
}
break;
-
}
/*
@@ -738,63 +821,61 @@ procfs_readdir(ap)
*/
case Proot: {
- int pcnt;
#ifdef PROCFS_ZOMBIE
int doingzomb = 0;
#endif
+ int pcnt = 0;
volatile struct proc *p = allproc.lh_first;
-#define PROCFS_XFILES 3 /* number of other entries, like "curproc" */
- pcnt = PROCFS_XFILES;
-
- while (p && uio->uio_resid >= UIO_MX) {
+ again:
+ for (; p && uio->uio_resid >= UIO_MX; i++, pcnt++) {
bzero((char *) dp, UIO_MX);
- dp->d_type = DT_DIR;
dp->d_reclen = UIO_MX;
switch (i) {
- case 0:
+ case 0: /* `.' */
+ case 1: /* `..' */
dp->d_fileno = PROCFS_FILENO(0, Proot);
- dp->d_namlen = sprintf(dp->d_name, ".");
- break;
-
- case 1:
- dp->d_fileno = PROCFS_FILENO(0, Proot);
- dp->d_namlen = sprintf(dp->d_name, "..");
+ dp->d_namlen = i + 1;
+ bcopy("..", dp->d_name, dp->d_namlen);
+ dp->d_name[i + 1] = '\0';
+ dp->d_type = DT_DIR;
break;
case 2:
- /* ship out entry for "curproc" */
- dp->d_fileno = PROCFS_FILENO(PID_MAX+1, Pproc);
- dp->d_namlen = sprintf(dp->d_name, "curproc");
+ dp->d_fileno = PROCFS_FILENO(0, Pcurproc);
+ dp->d_namlen = 7;
+ bcopy("curproc", dp->d_name, 8);
+ dp->d_type = DT_LNK;
break;
default:
- if (pcnt >= i) {
- dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
- dp->d_namlen = sprintf(dp->d_name, "%ld", (long) p->p_pid);
+ while (pcnt < i) {
+ pcnt++;
+ p = p->p_list.le_next;
+ if (!p)
+ goto done;
}
-
+ dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
+ dp->d_namlen = sprintf(dp->d_name, "%ld",
+ (long)p->p_pid);
+ dp->d_type = DT_REG;
p = p->p_list.le_next;
-
-#ifdef PROCFS_ZOMBIE
- if (p == 0 && doingzomb == 0) {
- doingzomb = 1;
- p = zombproc.lh_first;
- }
-#endif
-
- if (pcnt++ < i)
- continue;
-
break;
}
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
+
+ if (error = uiomove((caddr_t)dp, UIO_MX, uio))
break;
- count += UIO_MX;
- i++;
}
+ done:
+
+#ifdef PROCFS_ZOMBIE
+ if (p == 0 && doingzomb == 0) {
+ doingzomb = 1;
+ p = zombproc.lh_first;
+ goto again;
+ }
+#endif
break;
@@ -811,6 +892,25 @@ procfs_readdir(ap)
}
/*
+ * readlink reads the link of `curproc'
+ */
+int
+procfs_readlink(ap)
+ struct vop_readlink_args *ap;
+{
+ struct uio *uio = ap->a_uio;
+ char buf[16]; /* should be enough */
+ int len;
+
+ if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pcurproc))
+ return (EINVAL);
+
+ len = sprintf(buf, "%ld", (long)curproc->p_pid);
+
+ return (uiomove((caddr_t)buf, len, ap->a_uio));
+}
+
+/*
* convert decimal ascii to pid_t
*/
static pid_t
@@ -838,6 +938,7 @@ atopid(b, len)
#define procfs_write procfs_rw
#define procfs_select ((int (*) __P((struct vop_select_args *))) procfs_badop)
#define procfs_mmap ((int (*) __P((struct vop_mmap_args *))) procfs_badop)
+#define procfs_revoke vop_revoke
#define procfs_fsync ((int (*) __P((struct vop_fsync_args *))) procfs_badop)
#define procfs_seek ((int (*) __P((struct vop_seek_args *))) procfs_badop)
#define procfs_remove ((int (*) __P((struct vop_remove_args *))) procfs_badop)
@@ -849,7 +950,6 @@ atopid(b, len)
#define procfs_readlink ((int (*) __P((struct vop_readlink_args *))) procfs_badop)
#define procfs_lock ((int (*) __P((struct vop_lock_args *))) nullop)
#define procfs_unlock ((int (*) __P((struct vop_unlock_args *))) nullop)
-#define procfs_bmap ((int (*) __P((struct vop_bmap_args *))) procfs_badop)
#define procfs_strategy ((int (*) __P((struct vop_strategy_args *))) procfs_badop)
#define procfs_islocked ((int (*) __P((struct vop_islocked_args *))) nullop)
#define procfs_advlock ((int (*) __P((struct vop_advlock_args *))) procfs_badop)
@@ -859,6 +959,9 @@ atopid(b, len)
#define procfs_truncate ((int (*) __P((struct vop_truncate_args *))) procfs_badop)
#define procfs_update ((int (*) __P((struct vop_update_args *))) nullop)
+/*
+ * procfs vnode operations.
+ */
vop_t **procfs_vnodeop_p;
static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
@@ -875,6 +978,7 @@ static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
{ &vop_ioctl_desc, (vop_t *)procfs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)procfs_select }, /* select */
{ &vop_mmap_desc, (vop_t *)procfs_mmap }, /* mmap */
+ { &vop_revoke_desc, (vop_t *)procfs_revoke }, /* revoke */
{ &vop_fsync_desc, (vop_t *)procfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)procfs_seek }, /* seek */
{ &vop_remove_desc, (vop_t *)procfs_remove }, /* remove */
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 049f41e..2e8cc04 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)spec_vnops.c 8.6 (Berkeley) 4/9/94
+ * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -79,8 +79,10 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)spec_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)spec_read }, /* read */
{ &vop_write_desc, (vop_t *)spec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
@@ -148,9 +150,10 @@ spec_open(ap)
struct proc *a_p;
} */ *ap;
{
+ struct proc *p = ap->a_p;
struct vnode *bvp, *vp = ap->a_vp;
dev_t bdev, dev = (dev_t)vp->v_rdev;
- register int maj = major(dev);
+ int maj = major(dev);
int error;
/*
@@ -171,7 +174,9 @@ spec_open(ap)
* When running in very secure mode, do not allow
* opens for writing of any disk character devices.
*/
- if (securelevel >= 2 && isdisk(dev, VCHR))
+ if (securelevel >= 2
+ && cdevsw[maj]->d_bdev
+ && cdevsw[maj]->d_bdev->d_flags == D_DISK)
return (EPERM);
/*
* When running in secure mode, do not allow opens
@@ -189,9 +194,20 @@ spec_open(ap)
return (EPERM);
}
}
- VOP_UNLOCK(vp);
- error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);
- VOP_LOCK(vp);
+#if 0
+ /*
+ * Lite2 stuff. We will almost certainly do this
+ * differently with devfs. The only use of this flag
+ * is in dead_read to make ttys return EOF instead of
+ * EIO when they are dead. Pre-lite2 FreeBSD returns
+ * EOF for all character devices.
+ */
+ if (cdevsw[maj]->d_type == D_TTY)
+ vp->v_flag |= VISTTY;
+#endif
+ VOP_UNLOCK(vp, 0, p);
+ error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, p);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -204,7 +220,7 @@ spec_open(ap)
* opens for writing of any disk block devices.
*/
if (securelevel >= 2 && ap->a_cred != FSCRED &&
- (ap->a_mode & FWRITE) && isdisk(dev, VBLK))
+ (ap->a_mode & FWRITE) && bdevsw[maj]->d_flags == D_DISK)
return (EPERM);
/*
* Do not allow opens of block devices that are
@@ -213,9 +229,7 @@ spec_open(ap)
error = vfs_mountedon(vp);
if (error)
return (error);
- return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));
- default:
- break;
+ return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, p));
}
return (0);
}
@@ -257,10 +271,10 @@ spec_read(ap)
switch (vp->v_type) {
case VCHR:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = (*cdevsw[major(vp->v_rdev)]->d_read)
(vp->v_rdev, uio, ap->a_ioflag);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -335,10 +349,10 @@ spec_write(ap)
switch (vp->v_type) {
case VCHR:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = (*cdevsw[major(vp->v_rdev)]->d_write)
(vp->v_rdev, uio, ap->a_ioflag);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -408,7 +422,7 @@ spec_ioctl(ap)
case VBLK:
if (ap->a_command == 0 && (int)ap->a_data == B_TAPE)
- if (bdevsw[major(dev)]->d_flags & B_TAPE)
+ if (bdevsw[major(dev)]->d_flags == D_TAPE)
return (0);
else
return (1);
@@ -498,6 +512,18 @@ loop:
return (0);
}
+int
+spec_inactive(ap)
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
+ return (0);
+}
+
/*
* Just call the device strategy routine
*/
@@ -539,31 +565,6 @@ spec_bmap(ap)
}
/*
- * At the moment we do not do any locking.
- */
-/* ARGSUSED */
-int
-spec_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/* ARGSUSED */
-int
-spec_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/*
* Device close routine
*/
/* ARGSUSED */
@@ -577,6 +578,7 @@ spec_close(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
dev_t dev = vp->v_rdev;
d_close_t *devclose;
int mode, error;
@@ -631,8 +633,11 @@ spec_close(ap)
(vp->v_flag & VXLOCK) == 0)
return (0);
- if (vp->v_object)
- vnode_pager_uncache(vp);
+ if (vp->v_object) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ vnode_pager_uncache(vp, p);
+ VOP_UNLOCK(vp, 0, p);
+ }
devclose = bdevsw[major(dev)]->d_close;
mode = S_IFBLK;
diff --git a/sys/fs/umapfs/umap.h b/sys/fs/umapfs/umap.h
index db1efd4..54ae097 100644
--- a/sys/fs/umapfs/umap.h
+++ b/sys/fs/umapfs/umap.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap.h 8.3 (Berkeley) 1/21/94
+ * @(#)umap.h 8.4 (Berkeley) 8/20/94
*
* $FreeBSD$
*/
@@ -67,8 +67,7 @@ struct umap_mount {
* A cache of vnode references
*/
struct umap_node {
- struct umap_node *umap_forw; /* Hash chain */
- struct umap_node *umap_back;
+ LIST_ENTRY(umap_node) umap_hash; /* Hash list */
struct vnode *umap_lowervp; /* Aliased vnode - VREFed once */
struct vnode *umap_vnode; /* Back pointer to vnode/umap_node */
};
diff --git a/sys/fs/umapfs/umap_subr.c b/sys/fs/umapfs/umap_subr.c
index 8333943..3b3629d 100644
--- a/sys/fs/umapfs/umap_subr.c
+++ b/sys/fs/umapfs/umap_subr.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -33,13 +33,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_subr.c 8.6 (Berkeley) 1/26/94
+ * @(#)umap_subr.c 8.9 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -48,11 +49,8 @@
#include <sys/malloc.h>
#include <miscfs/umapfs/umap.h>
-extern int umapfs_init __P((void));
-
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NUMAPNODECACHE 16
-#define UMAP_NHASH(vp) ((((u_long) vp)>>LOG2_SIZEVNODE) & (NUMAPNODECACHE-1))
/*
* Null layer cache:
@@ -62,52 +60,33 @@ extern int umapfs_init __P((void));
* alias is removed the target vnode is vrele'd.
*/
-/*
- * Cache head
- */
-struct umap_node_cache {
- struct umap_node *ac_forw;
- struct umap_node *ac_back;
-};
-
-static struct umap_node_cache umap_node_cache[NUMAPNODECACHE];
+#define UMAP_NHASH(vp) \
+ (&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash])
+LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
+u_long umap_node_hash;
static u_long umap_findid __P((u_long id, u_long map[][2], int nentries));
static int umap_node_alloc __P((struct mount *mp, struct vnode *lowervp,
struct vnode **vpp));
static struct vnode *
umap_node_find __P((struct mount *mp, struct vnode *targetvp));
-static struct umap_node_cache *
- umap_node_hash __P((struct vnode *targetvp));
/*
* Initialise cache headers
*/
int
-umapfs_init()
+umapfs_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct umap_node_cache *ac;
+
#ifdef UMAPFS_DIAGNOSTIC
printf("umapfs_init\n"); /* printed during system boot */
#endif
-
- for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++)
- ac->ac_forw = ac->ac_back = (struct umap_node *) ac;
+ umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
return (0);
}
/*
- * Compute hash list for given target vnode
- */
-static struct umap_node_cache *
-umap_node_hash(targetvp)
- struct vnode *targetvp;
-{
-
- return (&umap_node_cache[UMAP_NHASH(targetvp)]);
-}
-
-/*
* umap_findid is called by various routines in umap_vnodeops.c to
* find a user or group id in a map.
*/
@@ -163,7 +142,8 @@ umap_node_find(mp, targetvp)
struct mount *mp;
struct vnode *targetvp;
{
- struct umap_node_cache *hd;
+ struct proc *p = curproc; /* XXX */
+ struct umap_node_hashhead *hd;
struct umap_node *a;
struct vnode *vp;
@@ -177,10 +157,9 @@ umap_node_find(mp, targetvp)
* the target vnode. If found, the increment the umap_node
* reference count (but NOT the target vnode's VREF counter).
*/
- hd = umap_node_hash(targetvp);
-
- loop:
- for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) {
+ hd = UMAP_NHASH(targetvp);
+loop:
+ for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) {
if (a->umap_lowervp == targetvp &&
a->umap_vnode->v_mount == mp) {
vp = UMAPTOV(a);
@@ -189,7 +168,7 @@ umap_node_find(mp, targetvp)
* stuff, but we don't want to lock
* the lower node.
*/
- if (vget(vp, 0)) {
+ if (vget(vp, 0, p)) {
#ifdef UMAPFS_DIAGNOSTIC
printf ("umap_node_find: vget failed.\n");
#endif
@@ -217,7 +196,7 @@ umap_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
- struct umap_node_cache *hd;
+ struct umap_node_hashhead *hd;
struct umap_node *xp;
struct vnode *othervp, *vp;
int error;
@@ -257,8 +236,8 @@ umap_node_alloc(mp, lowervp, vpp)
return (0);
}
VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */
- hd = umap_node_hash(lowervp);
- insque(xp, hd);
+ hd = UMAP_NHASH(lowervp);
+ LIST_INSERT_HEAD(hd, xp, umap_hash);
return (0);
}
diff --git a/sys/fs/umapfs/umap_vfsops.c b/sys/fs/umapfs/umap_vfsops.c
index 517c291..897e2ce 100644
--- a/sys/fs/umapfs/umap_vfsops.c
+++ b/sys/fs/umapfs/umap_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94
+ * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -46,6 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -54,7 +55,7 @@
#include <sys/malloc.h>
#include <miscfs/umapfs/umap.h>
-extern int umapfs_init __P((void));
+extern int umapfs_init __P((struct vfsconf *));
static int umapfs_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -187,7 +188,7 @@ umapfs_mount(mp, path, data, ndp, p)
/*
* Unlock the node (either the lower or the alias)
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
/*
* Make sure the node alias worked
*/
@@ -207,7 +208,7 @@ umapfs_mount(mp, path, data, ndp, p)
if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) amp;
- getnewfsid(mp, MOUNT_LOFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -253,12 +254,8 @@ umapfs_unmount(mp, mntflags, p)
printf("umapfs_unmount(mp = %x)\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
@@ -300,6 +297,7 @@ umapfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef UMAPFS_DIAGNOSTIC
@@ -314,7 +312,7 @@ umapfs_root(mp, vpp)
*/
vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
@@ -429,4 +427,3 @@ static struct vfsops umap_vfsops = {
};
VFS_SET(umap_vfsops, umap, MOUNT_UMAP, VFCF_LOOPBACK);
-
diff --git a/sys/fs/umapfs/umap_vnops.c b/sys/fs/umapfs/umap_vnops.c
index 7c14cda..17064f4 100644
--- a/sys/fs/umapfs/umap_vnops.c
+++ b/sys/fs/umapfs/umap_vnops.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_vnops.c 8.3 (Berkeley) 1/5/94
+ * @(#)umap_vnops.c 8.6 (Berkeley) 5/22/95
* $FreeBSD$
*/
@@ -336,10 +336,52 @@ umap_getattr(ap)
return (0);
}
+/*
+ * 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
+umap_lock(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ vop_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
+umap_unlock(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ vop_nounlock(ap);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
static int
umap_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
/*
@@ -349,6 +391,7 @@ umap_inactive(ap)
* cache and reusable.
*
*/
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -364,7 +407,7 @@ umap_reclaim(ap)
/* After this assignment, this node will not be re-used. */
xp->umap_lowervp = NULL;
- remque(xp);
+ LIST_REMOVE(xp, umap_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele(lowervp);
@@ -487,6 +530,8 @@ static struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)umap_bypass },
{ &vop_getattr_desc, (vop_t *)umap_getattr },
+ { &vop_lock_desc, (vop_t *)umap_lock },
+ { &vop_unlock_desc, (vop_t *)umap_unlock },
{ &vop_inactive_desc, (vop_t *)umap_inactive },
{ &vop_reclaim_desc, (vop_t *)umap_reclaim },
{ &vop_print_desc, (vop_t *)umap_print },
diff --git a/sys/fs/unionfs/union.h b/sys/fs/unionfs/union.h
index 9c740d3..c956921 100644
--- a/sys/fs/unionfs/union.h
+++ b/sys/fs/unionfs/union.h
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union.h 8.2 (Berkeley) 2/17/94
+ * @(#)union.h 8.9 (Berkeley) 12/10/94
* $FreeBSD$
*/
@@ -75,10 +75,14 @@ struct union_node {
struct vnode *un_uppervp; /* overlaying object */
struct vnode *un_lowervp; /* underlying object */
struct vnode *un_dirvp; /* Parent dir of uppervp */
+ struct vnode *un_pvp; /* Parent vnode */
char *un_path; /* saved component name */
int un_hash; /* saved un_path hash value */
int un_openl; /* # of opens on lowervp */
- int un_flags;
+ unsigned int un_flags;
+ struct vnode **un_dircache; /* cached union stack */
+ off_t un_uppersz; /* size of upper object */
+ off_t un_lowersz; /* size of lower object */
#ifdef DIAGNOSTIC
pid_t un_pid;
#endif
@@ -88,16 +92,23 @@ struct union_node {
#define UN_LOCKED 0x02
#define UN_ULOCK 0x04 /* Upper node is locked */
#define UN_KLOCK 0x08 /* Keep upper node locked on vput */
+#define UN_CACHED 0x10 /* In union cache */
extern int union_allocvp __P((struct vnode **, struct mount *,
struct vnode *, struct vnode *,
struct componentname *, struct vnode *,
- struct vnode *));
+ struct vnode *, int));
extern int union_freevp __P((struct vnode *));
-extern int union_copyfile __P((struct proc *, struct ucred *,
- struct vnode *, struct vnode *));
+extern int union_copyfile __P((struct vnode *, struct vnode *,
+ struct ucred *, struct proc *));
+extern int union_copyup __P((struct union_node *, int, struct ucred *,
+ struct proc *));
+extern int union_dowhiteout __P((struct union_node *, struct ucred *,
+ struct proc *));
extern int union_mkshadow __P((struct union_mount *, struct vnode *,
struct componentname *, struct vnode **));
+extern int union_mkwhiteout __P((struct union_mount *, struct vnode *,
+ struct componentname *, char *));
extern int union_vn_create __P((struct vnode **, struct union_node *,
struct proc *));
extern int union_vn_close __P((struct vnode *, int, struct ucred *,
@@ -108,6 +119,7 @@ extern void union_removed_upper __P((struct union_node *un));
extern struct vnode *union_lowervp __P((struct vnode *));
extern void union_newlower __P((struct union_node *, struct vnode *));
extern void union_newupper __P((struct union_node *, struct vnode *));
+extern void union_newsize __P((struct vnode *, off_t, off_t));
#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
index 6549f7d..63e25e6 100644
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_subr.c 8.4 (Berkeley) 2/17/94
+ * @(#)union_subr.c 8.20 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -48,6 +48,9 @@
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <vm/vm.h> /* for vnode_pager_setsize */
#include <miscfs/union/union.h>
#include <sys/proc.h>
@@ -118,31 +121,38 @@ union_updatevp(un, uppervp, lowervp)
{
int ohash = UNION_HASH(un->un_uppervp, un->un_lowervp);
int nhash = UNION_HASH(uppervp, lowervp);
+ int docache = (lowervp != NULLVP || uppervp != NULLVP);
+ int lhash, hhash, uhash;
- if (ohash != nhash) {
- /*
- * Ensure locking is ordered from lower to higher
- * to avoid deadlocks.
- */
- if (nhash < ohash) {
- int t = ohash;
- ohash = nhash;
- nhash = t;
- }
+ /*
+ * Ensure locking is ordered from lower to higher
+ * to avoid deadlocks.
+ */
+ if (nhash < ohash) {
+ lhash = nhash;
+ uhash = ohash;
+ } else {
+ lhash = ohash;
+ uhash = nhash;
+ }
- while (union_list_lock(ohash))
+ if (lhash != uhash)
+ while (union_list_lock(lhash))
continue;
- while (union_list_lock(nhash))
- continue;
+ while (union_list_lock(uhash))
+ continue;
- LIST_REMOVE(un, un_cache);
- union_list_unlock(ohash);
- } else {
- while (union_list_lock(nhash))
- continue;
+ if (ohash != nhash || !docache) {
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
}
+ if (ohash != nhash)
+ union_list_unlock(ohash);
+
if (un->un_lowervp != lowervp) {
if (un->un_lowervp) {
vrele(un->un_lowervp);
@@ -156,6 +166,7 @@ union_updatevp(un, uppervp, lowervp)
}
}
un->un_lowervp = lowervp;
+ un->un_lowersz = VNOVAL;
}
if (un->un_uppervp != uppervp) {
@@ -163,10 +174,13 @@ union_updatevp(un, uppervp, lowervp)
vrele(un->un_uppervp);
un->un_uppervp = uppervp;
+ un->un_uppersz = VNOVAL;
}
- if (ohash != nhash)
+ if (docache && (ohash != nhash)) {
LIST_INSERT_HEAD(&unhead[nhash], un, un_cache);
+ un->un_flags |= UN_CACHED;
+ }
union_list_unlock(nhash);
}
@@ -190,6 +204,47 @@ union_newupper(un, uppervp)
}
/*
+ * Keep track of size changes in the underlying vnodes.
+ * If the size changes, then callback to the vm layer
+ * giving priority to the upper layer size.
+ */
+void
+union_newsize(vp, uppersz, lowersz)
+ struct vnode *vp;
+ off_t uppersz, lowersz;
+{
+ struct union_node *un;
+ off_t sz;
+
+ /* only interested in regular files */
+ if (vp->v_type != VREG)
+ return;
+
+ un = VTOUNION(vp);
+ sz = VNOVAL;
+
+ if ((uppersz != VNOVAL) && (un->un_uppersz != uppersz)) {
+ un->un_uppersz = uppersz;
+ if (sz == VNOVAL)
+ sz = un->un_uppersz;
+ }
+
+ if ((lowersz != VNOVAL) && (un->un_lowersz != lowersz)) {
+ un->un_lowersz = lowersz;
+ if (sz == VNOVAL)
+ sz = un->un_lowersz;
+ }
+
+ if (sz != VNOVAL) {
+#ifdef UNION_DIAGNOSTIC
+ printf("union: %s size now %ld\n",
+ uppersz != VNOVAL ? "upper" : "lower", (long) sz);
+#endif
+ vnode_pager_setsize(vp, sz);
+ }
+}
+
+/*
* allocate a union_node/vnode pair. the vnode is
* referenced and locked. the new vnode is returned
* via (vpp). (mp) is the mountpoint of the union filesystem,
@@ -221,19 +276,22 @@ union_newupper(un, uppervp)
* the vnode free list.
*/
int
-union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
+union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp, docache)
struct vnode **vpp;
struct mount *mp;
- struct vnode *undvp;
+ struct vnode *undvp; /* parent union vnode */
struct vnode *dvp; /* may be null */
struct componentname *cnp; /* may be null */
struct vnode *uppervp; /* may be null */
struct vnode *lowervp; /* may be null */
+ int docache;
{
int error;
struct union_node *un = 0;
struct vnode *xlowervp = NULLVP;
- int hash = 0;
+ struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
+ int hash;
+ int vflag;
int try;
if (uppervp == NULLVP && lowervp == NULLVP)
@@ -244,8 +302,22 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
lowervp = NULLVP;
}
+ /* detect the root vnode (and aliases) */
+ vflag = 0;
+ if ((uppervp == um->um_uppervp) &&
+ ((lowervp == NULLVP) || lowervp == um->um_lowervp)) {
+ if (lowervp == NULLVP) {
+ lowervp = um->um_lowervp;
+ if (lowervp != NULLVP)
+ VREF(lowervp);
+ }
+ vflag = VROOT;
+ }
+
loop:
- for (try = 0; try < 3; try++) {
+ if (!docache) {
+ un = 0;
+ } else for (try = 0; try < 3; try++) {
switch (try) {
case 0:
if (lowervp == NULLVP)
@@ -276,7 +348,8 @@ loop:
(un->un_uppervp == uppervp ||
un->un_uppervp == NULLVP) &&
(UNIONTOV(un)->v_mount == mp)) {
- if (vget(UNIONTOV(un), 0)) {
+ if (vget(UNIONTOV(un), 0,
+ cnp ? cnp->cn_proc : NULL)) {
union_list_unlock(hash);
goto loop;
}
@@ -359,8 +432,7 @@ loop:
*/
if (lowervp != un->un_lowervp) {
union_newlower(un, lowervp);
- if (cnp && (lowervp != NULLVP) &&
- (lowervp->v_type == VREG)) {
+ if (cnp && (lowervp != NULLVP)) {
un->un_hash = cnp->cn_hash;
un->un_path = malloc(cnp->cn_namelen+1,
M_TEMP, M_WAITOK);
@@ -377,14 +449,16 @@ loop:
return (0);
}
- /*
- * otherwise lock the vp list while we call getnewvnode
- * since that can block.
- */
- hash = UNION_HASH(uppervp, lowervp);
+ if (docache) {
+ /*
+ * otherwise lock the vp list while we call getnewvnode
+ * since that can block.
+ */
+ hash = UNION_HASH(uppervp, lowervp);
- if (union_list_lock(hash))
- goto loop;
+ if (union_list_lock(hash))
+ goto loop;
+ }
error = getnewvnode(VT_UNION, mp, union_vnodeop_p, vpp);
if (error) {
@@ -403,6 +477,7 @@ loop:
MALLOC((*vpp)->v_data, void *, sizeof(struct union_node),
M_TEMP, M_WAITOK);
+ (*vpp)->v_flag |= vflag;
if (uppervp)
(*vpp)->v_type = uppervp->v_type;
else
@@ -410,7 +485,13 @@ loop:
un = VTOUNION(*vpp);
un->un_vnode = *vpp;
un->un_uppervp = uppervp;
+ un->un_uppersz = VNOVAL;
un->un_lowervp = lowervp;
+ un->un_lowersz = VNOVAL;
+ un->un_pvp = undvp;
+ if (undvp != NULLVP)
+ VREF(undvp);
+ un->un_dircache = 0;
un->un_openl = 0;
un->un_flags = UN_LOCKED;
if (un->un_uppervp)
@@ -421,7 +502,7 @@ loop:
else
un->un_pid = -1;
#endif
- if (cnp && (lowervp != NULLVP) && (lowervp->v_type == VREG)) {
+ if (cnp && (lowervp != NULLVP)) {
un->un_hash = cnp->cn_hash;
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
@@ -434,13 +515,17 @@ loop:
un->un_dirvp = 0;
}
- LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
+ if (docache) {
+ LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
+ un->un_flags |= UN_CACHED;
+ }
if (xlowervp)
vrele(xlowervp);
out:
- union_list_unlock(hash);
+ if (docache)
+ union_list_unlock(hash);
return (error);
}
@@ -451,13 +536,18 @@ union_freevp(vp)
{
struct union_node *un = VTOUNION(vp);
- LIST_REMOVE(un, un_cache);
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
- if (un->un_uppervp)
+ if (un->un_pvp != NULLVP)
+ vrele(un->un_pvp);
+ if (un->un_uppervp != NULLVP)
vrele(un->un_uppervp);
- if (un->un_lowervp)
+ if (un->un_lowervp != NULLVP)
vrele(un->un_lowervp);
- if (un->un_dirvp)
+ if (un->un_dirvp != NULLVP)
vrele(un->un_dirvp);
if (un->un_path)
free(un->un_path, M_TEMP);
@@ -474,11 +564,11 @@ union_freevp(vp)
* and (tvp) are locked on entry and exit.
*/
int
-union_copyfile(p, cred, fvp, tvp)
- struct proc *p;
- struct ucred *cred;
+union_copyfile(fvp, tvp, cred, p)
struct vnode *fvp;
struct vnode *tvp;
+ struct ucred *cred;
+ struct proc *p;
{
char *buf;
struct uio uio;
@@ -497,12 +587,12 @@ union_copyfile(p, cred, fvp, tvp)
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_offset = 0;
- VOP_UNLOCK(fvp); /* XXX */
- LEASE_CHECK(fvp, p, cred, LEASE_READ);
- VOP_LOCK(fvp); /* XXX */
- VOP_UNLOCK(tvp); /* XXX */
- LEASE_CHECK(tvp, p, cred, LEASE_WRITE);
- VOP_LOCK(tvp); /* XXX */
+ VOP_UNLOCK(fvp, 0, p); /* XXX */
+ VOP_LEASE(fvp, p, cred, LEASE_READ);
+ vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
+ VOP_UNLOCK(tvp, 0, p); /* XXX */
+ VOP_LEASE(tvp, p, cred, LEASE_WRITE);
+ vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
@@ -542,6 +632,123 @@ union_copyfile(p, cred, fvp, tvp)
}
/*
+ * (un) is assumed to be locked on entry and remains
+ * locked on exit.
+ */
+int
+union_copyup(un, docopy, cred, p)
+ struct union_node *un;
+ int docopy;
+ struct ucred *cred;
+ struct proc *p;
+{
+ int error;
+ struct vnode *lvp, *uvp;
+
+ error = union_vn_create(&uvp, un, p);
+ if (error)
+ return (error);
+
+ /* at this point, uppervp is locked */
+ union_newupper(un, uvp);
+ un->un_flags |= UN_ULOCK;
+
+ lvp = un->un_lowervp;
+
+ if (docopy) {
+ /*
+ * XX - should not ignore errors
+ * from VOP_CLOSE
+ */
+ vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = VOP_OPEN(lvp, FREAD, cred, p);
+ if (error == 0) {
+ error = union_copyfile(lvp, uvp, cred, p);
+ VOP_UNLOCK(lvp, 0, p);
+ (void) VOP_CLOSE(lvp, FREAD, cred, p);
+ }
+#ifdef UNION_DIAGNOSTIC
+ if (error == 0)
+ uprintf("union: copied up %s\n", un->un_path);
+#endif
+
+ }
+ un->un_flags &= ~UN_ULOCK;
+ VOP_UNLOCK(uvp, 0, p);
+ union_vn_close(uvp, FWRITE, cred, p);
+ vn_lock(uvp, LK_EXCLUSIVE | LK_RETRY, p);
+ un->un_flags |= UN_ULOCK;
+
+ /*
+ * Subsequent IOs will go to the top layer, so
+ * call close on the lower vnode and open on the
+ * upper vnode to ensure that the filesystem keeps
+ * its references counts right. This doesn't do
+ * the right thing with (cred) and (FREAD) though.
+ * Ignoring error returns is not right, either.
+ */
+ if (error == 0) {
+ int i;
+
+ for (i = 0; i < un->un_openl; i++) {
+ (void) VOP_CLOSE(lvp, FREAD, cred, p);
+ (void) VOP_OPEN(uvp, FREAD, cred, p);
+ }
+ un->un_openl = 0;
+ }
+
+ return (error);
+
+}
+
+static int
+union_relookup(um, dvp, vpp, cnp, cn, path, pathlen)
+ struct union_mount *um;
+ struct vnode *dvp;
+ struct vnode **vpp;
+ struct componentname *cnp;
+ struct componentname *cn;
+ char *path;
+ int pathlen;
+{
+ int error;
+
+ /*
+ * A new componentname structure must be faked up because
+ * there is no way to know where the upper level cnp came
+ * from or what it is being used for. This must duplicate
+ * some of the work done by NDINIT, some of the work done
+ * by namei, some of the work done by lookup and some of
+ * the work done by VOP_LOOKUP when given a CREATE flag.
+ * Conclusion: Horrible.
+ *
+ * The pathname buffer will be FREEed by VOP_MKDIR.
+ */
+ cn->cn_namelen = pathlen;
+ cn->cn_pnbuf = malloc(cn->cn_namelen+1, M_NAMEI, M_WAITOK);
+ bcopy(path, cn->cn_pnbuf, cn->cn_namelen);
+ cn->cn_pnbuf[cn->cn_namelen] = '\0';
+
+ cn->cn_nameiop = CREATE;
+ cn->cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
+ cn->cn_proc = cnp->cn_proc;
+ if (um->um_op == UNMNT_ABOVE)
+ cn->cn_cred = cnp->cn_cred;
+ else
+ cn->cn_cred = um->um_cred;
+ cn->cn_nameptr = cn->cn_pnbuf;
+ cn->cn_hash = cnp->cn_hash;
+ cn->cn_consume = cnp->cn_consume;
+
+ VREF(dvp);
+ error = relookup(dvp, vpp, cn);
+ if (!error)
+ vrele(dvp);
+
+ return (error);
+}
+
+/*
* Create a shadow directory in the upper layer.
* The new vnode is returned locked.
*
@@ -565,6 +772,19 @@ union_mkshadow(um, dvp, cnp, vpp)
struct proc *p = cnp->cn_proc;
struct componentname cn;
+ error = union_relookup(um, dvp, vpp, cnp, &cn,
+ cnp->cn_nameptr, cnp->cn_namelen);
+ if (error)
+ return (error);
+
+ if (*vpp) {
+ VOP_ABORTOP(dvp, &cn);
+ VOP_UNLOCK(dvp, 0, p);
+ vrele(*vpp);
+ *vpp = NULLVP;
+ return (EEXIST);
+ }
+
/*
* policy: when creating the shadow directory in the
* upper layer, create it owned by the user who did
@@ -573,55 +793,62 @@ union_mkshadow(um, dvp, cnp, vpp)
* mkdir syscall). (jsp, kb)
*/
- /*
- * A new componentname structure must be faked up because
- * there is no way to know where the upper level cnp came
- * from or what it is being used for. This must duplicate
- * some of the work done by NDINIT, some of the work done
- * by namei, some of the work done by lookup and some of
- * the work done by VOP_LOOKUP when given a CREATE flag.
- * Conclusion: Horrible.
- *
- * The pathname buffer will be FREEed by VOP_MKDIR.
- */
- cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
- bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen);
- cn.cn_pnbuf[cnp->cn_namelen] = '\0';
+ VATTR_NULL(&va);
+ va.va_type = VDIR;
+ va.va_mode = um->um_cmode;
- cn.cn_nameiop = CREATE;
- cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
- cn.cn_proc = cnp->cn_proc;
- if (um->um_op == UNMNT_ABOVE)
- cn.cn_cred = cnp->cn_cred;
- else
- cn.cn_cred = um->um_cred;
- cn.cn_nameptr = cn.cn_pnbuf;
- cn.cn_namelen = cnp->cn_namelen;
- cn.cn_hash = cnp->cn_hash;
- cn.cn_consume = cnp->cn_consume;
+ /* VOP_LEASE: dvp is locked */
+ VOP_LEASE(dvp, p, cn.cn_cred, LEASE_WRITE);
- VREF(dvp);
- error = relookup(dvp, vpp, &cn);
- if (error)
+ error = VOP_MKDIR(dvp, vpp, &cn, &va);
+ return (error);
+}
+
+/*
+ * Create a whiteout entry in the upper layer.
+ *
+ * (um) points to the union mount structure for access to the
+ * the mounting process's credentials.
+ * (dvp) is the directory in which to create the whiteout.
+ * it is locked on entry and exit.
+ * (cnp) is the componentname to be created.
+ */
+int
+union_mkwhiteout(um, dvp, cnp, path)
+ struct union_mount *um;
+ struct vnode *dvp;
+ struct componentname *cnp;
+ char *path;
+{
+ int error;
+ struct vattr va;
+ struct proc *p = cnp->cn_proc;
+ struct vnode *wvp;
+ struct componentname cn;
+
+ VOP_UNLOCK(dvp, 0, p);
+ error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
+ if (error) {
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
- vrele(dvp);
+ }
- if (*vpp) {
+ if (wvp) {
VOP_ABORTOP(dvp, &cn);
- VOP_UNLOCK(dvp);
- vrele(*vpp);
- *vpp = NULLVP;
+ vrele(dvp);
+ vrele(wvp);
return (EEXIST);
}
- VATTR_NULL(&va);
- va.va_type = VDIR;
- va.va_mode = um->um_cmode;
+ /* VOP_LEASE: dvp is locked */
+ VOP_LEASE(dvp, p, p->p_ucred, LEASE_WRITE);
+
+ error = VOP_WHITEOUT(dvp, &cn, CREATE);
+ if (error)
+ VOP_ABORTOP(dvp, &cn);
- /* LEASE_CHECK: dvp is locked */
- LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
+ vrele(dvp);
- error = VOP_MKDIR(dvp, vpp, &cn, &va);
return (error);
}
@@ -699,9 +926,8 @@ union_vn_create(vpp, un, p)
VATTR_NULL(vap);
vap->va_type = VREG;
vap->va_mode = cmode;
- LEASE_CHECK(un->un_dirvp, p, cred, LEASE_WRITE);
- error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
- if (error)
+ VOP_LEASE(un->un_dirvp, p, cred, LEASE_WRITE);
+ if (error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap))
return (error);
error = VOP_OPEN(vp, fmode, cred, p);
@@ -722,6 +948,7 @@ union_vn_close(vp, fmode, cred, p)
struct ucred *cred;
struct proc *p;
{
+
if (fmode & FWRITE)
--vp->v_writecount;
return (VOP_CLOSE(vp, fmode, cred, p));
@@ -731,24 +958,137 @@ void
union_removed_upper(un)
struct union_node *un;
{
+ struct proc *p = curproc; /* XXX */
+
+ union_newupper(un, NULLVP);
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
+
if (un->un_flags & UN_ULOCK) {
un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp);
+ VOP_UNLOCK(un->un_uppervp, 0, p);
}
-
- union_newupper(un, NULLVP);
}
+#if 0
struct vnode *
union_lowervp(vp)
struct vnode *vp;
{
struct union_node *un = VTOUNION(vp);
- if (un->un_lowervp && (vp->v_type == un->un_lowervp->v_type)) {
- if (vget(un->un_lowervp, 0))
- return (NULLVP);
+ if ((un->un_lowervp != NULLVP) &&
+ (vp->v_type == un->un_lowervp->v_type)) {
+ if (vget(un->un_lowervp, 0) == 0)
+ return (un->un_lowervp);
}
- return (un->un_lowervp);
+ return (NULLVP);
+}
+#endif
+
+/*
+ * determine whether a whiteout is needed
+ * during a remove/rmdir operation.
+ */
+int
+union_dowhiteout(un, cred, p)
+ struct union_node *un;
+ struct ucred *cred;
+ struct proc *p;
+{
+ struct vattr va;
+
+ if (un->un_lowervp != NULLVP)
+ return (1);
+
+ if (VOP_GETATTR(un->un_uppervp, &va, cred, p) == 0 &&
+ (va.va_flags & OPAQUE))
+ return (1);
+
+ return (0);
+}
+
+static void
+union_dircache_r(vp, vppp, cntp)
+ struct vnode *vp;
+ struct vnode ***vppp;
+ int *cntp;
+{
+ struct union_node *un;
+
+ if (vp->v_op != union_vnodeop_p) {
+ if (vppp) {
+ VREF(vp);
+ *(*vppp)++ = vp;
+ if (--(*cntp) == 0)
+ panic("union: dircache table too small");
+ } else {
+ (*cntp)++;
+ }
+
+ return;
+ }
+
+ un = VTOUNION(vp);
+ if (un->un_uppervp != NULLVP)
+ union_dircache_r(un->un_uppervp, vppp, cntp);
+ if (un->un_lowervp != NULLVP)
+ union_dircache_r(un->un_lowervp, vppp, cntp);
+}
+
+struct vnode *
+union_dircache(vp, p)
+ struct vnode *vp;
+ struct proc *p;
+{
+ int cnt;
+ struct vnode *nvp;
+ struct vnode **vpp;
+ struct vnode **dircache;
+ struct union_node *un;
+ int error;
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ dircache = VTOUNION(vp)->un_dircache;
+
+ nvp = NULLVP;
+
+ if (dircache == 0) {
+ cnt = 0;
+ union_dircache_r(vp, 0, &cnt);
+ cnt++;
+ dircache = (struct vnode **)
+ malloc(cnt * sizeof(struct vnode *),
+ M_TEMP, M_WAITOK);
+ vpp = dircache;
+ union_dircache_r(vp, &vpp, &cnt);
+ *vpp = NULLVP;
+ vpp = dircache + 1;
+ } else {
+ vpp = dircache;
+ do {
+ if (*vpp++ == VTOUNION(vp)->un_uppervp)
+ break;
+ } while (*vpp != NULLVP);
+ }
+
+ if (*vpp == NULLVP)
+ goto out;
+
+ vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, p);
+ VREF(*vpp);
+ error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, 0, *vpp, NULLVP, 0);
+ if (error)
+ goto out;
+
+ VTOUNION(vp)->un_dircache = 0;
+ un = VTOUNION(nvp);
+ un->un_dircache = dircache;
+
+out:
+ VOP_UNLOCK(vp, 0, p);
+ return (nvp);
}
diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c
index a1a6a0d..0295961 100644
--- a/sys/fs/unionfs/union_vfsops.c
+++ b/sys/fs/unionfs/union_vfsops.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994 Jan-Simon Pendry.
+ * Copyright (c) 1994, 1995 The Regents of the University of California.
+ * Copyright (c) 1994, 1995 Jan-Simon Pendry.
* All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_vfsops.c 8.7 (Berkeley) 3/5/94
+ * @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -56,7 +56,7 @@
#include <sys/queue.h>
#include <miscfs/union/union.h>
-extern int union_init __P((void));
+extern int union_init __P((struct vfsconf *));
extern int union_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -92,7 +92,7 @@ union_mount(mp, path, data, ndp, p)
struct union_args args;
struct vnode *lowerrootvp = NULLVP;
struct vnode *upperrootvp = NULLVP;
- struct union_mount *um;
+ struct union_mount *um = 0;
struct ucred *cred = 0;
struct ucred *scred;
struct vattr va;
@@ -118,34 +118,6 @@ union_mount(mp, path, data, ndp, p)
}
/*
- * Take a copy of the process's credentials. This isn't
- * quite right since the euid will always be zero and we
- * want to get the "real" users credentials. So fix up
- * the uid field after taking the copy.
- */
- cred = crdup(p->p_ucred);
- cred->cr_uid = p->p_cred->p_ruid;
-
- /*
- * Ensure the *real* user has write permission on the
- * mounted-on directory. This allows the mount_union
- * command to be made setuid root so allowing anyone
- * to do union mounts onto any directory on which they
- * have write permission and which they also own.
- */
- error = VOP_GETATTR(mp->mnt_vnodecovered, &va, cred, p);
- if (error)
- goto bad;
- if ((va.va_uid != cred->cr_uid) &&
- (cred->cr_uid != 0)) {
- error = EACCES;
- goto bad;
- }
- error = VOP_ACCESS(mp->mnt_vnodecovered, VWRITE, cred, p);
- if (error)
- goto bad;
-
- /*
* Get argument
*/
error = copyin(data, (caddr_t)&args, sizeof(struct union_args));
@@ -156,18 +128,10 @@ union_mount(mp, path, data, ndp, p)
VREF(lowerrootvp);
/*
- * Find upper node. Use the real process credentials,
- * not the effective ones since this will have come
- * through a setuid process (mount_union). All this
- * messing around with permissions is entirely bogus
- * and should be removed by allowing any user straight
- * past the mount system call.
+ * Find upper node.
*/
- scred = p->p_ucred;
- p->p_ucred = cred;
NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT,
UIO_USERSPACE, args.target, p);
- p->p_ucred = scred;
error = namei(ndp);
if (error)
@@ -218,7 +182,18 @@ union_mount(mp, path, data, ndp, p)
goto bad;
}
- um->um_cred = cred;
+ /*
+ * Unless the mount is readonly, ensure that the top layer
+ * supports whiteout operations
+ */
+ if ((mp->mnt_flag & MNT_RDONLY) == 0) {
+ error = VOP_WHITEOUT(um->um_uppervp, (struct componentname *) 0, LOOKUP);
+ if (error)
+ goto bad;
+ }
+
+ um->um_cred = p->p_ucred;
+ crhold(um->um_cred);
um->um_cmode = UN_DIRMODE &~ p->p_fd->fd_cmask;
/*
@@ -246,24 +221,18 @@ union_mount(mp, path, data, ndp, p)
*/
mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
- /*
- * This is a user mount. Privilege check for unmount
- * will be done in union_unmount.
- */
- mp->mnt_flag |= MNT_USER;
-
mp->mnt_data = (qaddr_t) um;
- getnewfsid(mp, MOUNT_UNION);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
switch (um->um_op) {
case UNMNT_ABOVE:
- cp = "<above>";
+ cp = "<above>:";
break;
case UNMNT_BELOW:
- cp = "<below>";
+ cp = "<below>:";
break;
case UNMNT_REPLACE:
cp = "";
@@ -287,6 +256,8 @@ union_mount(mp, path, data, ndp, p)
return (0);
bad:
+ if (um)
+ free(um, M_UFSMNT);
if (cred)
crfree(cred);
if (upperrootvp)
@@ -323,40 +294,55 @@ union_unmount(mp, mntflags, p)
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
struct vnode *um_rootvp;
int error;
+ int freeing;
int flags = 0;
#ifdef UNION_DIAGNOSTIC
printf("union_unmount(mp = %x)\n", mp);
#endif
- /* only the mounter, or superuser can unmount */
- if ((p->p_cred->p_ruid != um->um_cred->cr_uid) &&
- (error = suser(p->p_ucred, &p->p_acflag)))
+ if (mntflags & MNT_FORCE)
+ flags |= FORCECLOSE;
+
+ if (error = union_root(mp, &um_rootvp))
return (error);
- if (mntflags & MNT_FORCE) {
- /* union can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
- flags |= FORCECLOSE;
+ /*
+ * Keep flushing vnodes from the mount list.
+ * This is needed because of the un_pvp held
+ * reference to the parent vnode.
+ * If more vnodes have been freed on a given pass,
+ * the try again. The loop will iterate at most
+ * (d) times, where (d) is the maximum tree depth
+ * in the filesystem.
+ */
+ for (freeing = 0; vflush(mp, um_rootvp, flags) != 0;) {
+ struct vnode *vp;
+ int n;
+
+ /* count #vnodes held on mount list */
+ for (n = 0, vp = mp->mnt_vnodelist.lh_first;
+ vp != NULLVP;
+ vp = vp->v_mntvnodes.le_next)
+ n++;
+
+ /* if this is unchanged then stop */
+ if (n == freeing)
+ break;
+
+ /* otherwise try once more time */
+ freeing = n;
}
- error = union_root(mp, &um_rootvp);
- if (error)
- return (error);
+ /* At this point the root vnode should have a single reference */
if (um_rootvp->v_usecount > 1) {
vput(um_rootvp);
return (EBUSY);
}
- error = vflush(mp, um_rootvp, flags);
- if (error) {
- vput(um_rootvp);
- return (error);
- }
#ifdef UNION_DIAGNOSTIC
- vprint("alias root of lower", um_rootvp);
-#endif
+ vprint("union root", um_rootvp);
+#endif
/*
* Discard references to upper and lower target vnodes.
*/
@@ -385,16 +371,11 @@ union_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
int error;
int loselock;
-#ifdef UNION_DIAGNOSTIC
- printf("union_root(mp = %x, lvp = %x, uvp = %x)\n", mp,
- um->um_lowervp,
- um->um_uppervp);
-#endif
-
/*
* Return locked reference to root.
*/
@@ -403,7 +384,7 @@ union_root(mp, vpp)
VOP_ISLOCKED(um->um_uppervp)) {
loselock = 1;
} else {
- VOP_LOCK(um->um_uppervp);
+ vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
loselock = 0;
}
if (um->um_lowervp)
@@ -413,16 +394,17 @@ union_root(mp, vpp)
(struct vnode *) 0,
(struct componentname *) 0,
um->um_uppervp,
- um->um_lowervp);
+ um->um_lowervp,
+ 1);
if (error) {
- if (!loselock)
- VOP_UNLOCK(um->um_uppervp);
- vrele(um->um_uppervp);
+ if (loselock)
+ vrele(um->um_uppervp);
+ else
+ vput(um->um_uppervp);
if (um->um_lowervp)
vrele(um->um_lowervp);
} else {
- (*vpp)->v_flag |= VROOT;
if (loselock)
VTOUNION(*vpp)->un_flags &= ~UN_ULOCK;
}
@@ -431,18 +413,6 @@ union_root(mp, vpp)
}
int
-union_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
union_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
@@ -485,7 +455,6 @@ union_statfs(mp, sbp, p)
if (error)
return (error);
- sbp->f_type = MOUNT_UNION;
sbp->f_flags = mstat.f_flags;
sbp->f_bsize = mstat.f_bsize;
sbp->f_iosize = mstat.f_iosize;
@@ -496,18 +465,23 @@ union_statfs(mp, sbp, p)
* kind of sense. none of this makes sense though.
*/
- if (mstat.f_bsize != lbsize) {
+ if (mstat.f_bsize != lbsize)
sbp->f_blocks = sbp->f_blocks * lbsize / mstat.f_bsize;
- sbp->f_bfree = sbp->f_bfree * lbsize / mstat.f_bsize;
- sbp->f_bavail = sbp->f_bavail * lbsize / mstat.f_bsize;
- }
+
+ /*
+ * The "total" fields count total resources in all layers,
+ * the "free" fields count only those resources which are
+ * free in the upper layer (since only the upper layer
+ * is writeable).
+ */
sbp->f_blocks += mstat.f_blocks;
- sbp->f_bfree += mstat.f_bfree;
- sbp->f_bavail += mstat.f_bavail;
+ sbp->f_bfree = mstat.f_bfree;
+ sbp->f_bavail = mstat.f_bavail;
sbp->f_files += mstat.f_files;
- sbp->f_ffree += mstat.f_ffree;
+ sbp->f_ffree = mstat.f_ffree;
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -515,51 +489,21 @@ union_statfs(mp, sbp, p)
return (0);
}
-int
-union_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
-
- /*
- * XXX - Assumes no data cached at union layer.
- */
- return (0);
-}
-
-int
-union_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
-union_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fidp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
-union_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+/*
+ * XXX - Assumes no data cached at union layer.
+ */
+#define union_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+
+#define union_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define union_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define union_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define union_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define union_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
struct vfsops union_vfsops = {
union_mount,
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 5940243..4a66dc0 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 1992, 1993, 1994 The Regents of the University of California.
- * Copyright (c) 1992, 1993, 1994 Jan-Simon Pendry.
- * All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
+ * Copyright (c) 1992, 1993, 1994, 1995
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry.
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_vnops.c 8.6 (Berkeley) 2/17/94
+ * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
* $FreeBSD$
*/
@@ -43,7 +43,7 @@
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/time.h>
-#include <sys/kernel.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@@ -51,16 +51,12 @@
#include <sys/malloc.h>
#include <sys/buf.h>
#include <sys/queue.h>
+#include <sys/lock.h>
#include <miscfs/union/union.h>
-/* FIXUP throws the lock on the uppervp vnode if the union_node is already
- * locked and the uppervp vnode is not. Before, this was thrown regardless
- * of the state of the union_node which resulted in locked vnodes which
- * were never unlocked (since the union would never be unlocked).
- */
-#define FIXUP(un) { \
- if (((un)->un_flags & (UN_LOCKED|UN_ULOCK)) == UN_LOCKED) { \
- union_fixup(un); \
+#define FIXUP(un, p) { \
+ if (((un)->un_flags & UN_ULOCK) == 0) { \
+ union_fixup(un, p); \
} \
}
@@ -70,7 +66,7 @@ extern int union_advlock __P((struct vop_advlock_args *ap));
extern int union_bmap __P((struct vop_bmap_args *ap));
extern int union_close __P((struct vop_close_args *ap));
extern int union_create __P((struct vop_create_args *ap));
-static void union_fixup __P((struct union_node *un));
+static void union_fixup __P((struct union_node *un, struct proc *p));
extern int union_fsync __P((struct vop_fsync_args *ap));
extern int union_getattr __P((struct vop_getattr_args *ap));
extern int union_inactive __P((struct vop_inactive_args *ap));
@@ -79,7 +75,7 @@ extern int union_islocked __P((struct vop_islocked_args *ap));
extern int union_link __P((struct vop_link_args *ap));
extern int union_lock __P((struct vop_lock_args *ap));
extern int union_lookup __P((struct vop_lookup_args *ap));
-static int union_lookup1 __P((struct vnode *udvp, struct vnode *dvp,
+static int union_lookup1 __P((struct vnode *udvp, struct vnode **dvpp,
struct vnode **vpp,
struct componentname *cnp));
extern int union_mkdir __P((struct vop_mkdir_args *ap));
@@ -100,29 +96,34 @@ extern int union_select __P((struct vop_select_args *ap));
extern int union_setattr __P((struct vop_setattr_args *ap));
extern int union_strategy __P((struct vop_strategy_args *ap));
extern int union_symlink __P((struct vop_symlink_args *ap));
-extern int union_unlock __P((struct vop_lock_args *ap));
+extern int union_unlock __P((struct vop_unlock_args *ap));
extern int union_write __P((struct vop_read_args *ap));
static void
-union_fixup(un)
+union_fixup(un, p)
struct union_node *un;
+ struct proc *p;
{
- VOP_LOCK(un->un_uppervp);
+ vn_lock(un->un_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
un->un_flags |= UN_ULOCK;
}
static int
-union_lookup1(udvp, dvp, vpp, cnp)
+union_lookup1(udvp, dvpp, vpp, cnp)
struct vnode *udvp;
- struct vnode *dvp;
+ struct vnode **dvpp;
struct vnode **vpp;
struct componentname *cnp;
{
int error;
+ struct proc *p = cnp->cn_proc;
struct vnode *tdvp;
+ struct vnode *dvp;
struct mount *mp;
+ dvp = *dvpp;
+
/*
* If stepping up the directory tree, check for going
* back across the mount point, in which case do what
@@ -130,21 +131,18 @@ union_lookup1(udvp, dvp, vpp, cnp)
* hierarchy.
*/
if (cnp->cn_flags & ISDOTDOT) {
- for (;;) {
+ while ((dvp != udvp) && (dvp->v_flag & VROOT)) {
/*
* Don't do the NOCROSSMOUNT check
* at this level. By definition,
* union fs deals with namespaces, not
* filesystems.
*/
- if ((dvp->v_flag & VROOT) == 0)
- break;
-
tdvp = dvp;
- dvp = dvp->v_mount->mnt_vnodecovered;
+ *dvpp = dvp = dvp->v_mount->mnt_vnodecovered;
vput(tdvp);
VREF(dvp);
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
}
}
@@ -158,7 +156,7 @@ union_lookup1(udvp, dvp, vpp, cnp)
* here to allow it to be unlocked again (phew) in union_lookup.
*/
if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN))
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
dvp = tdvp;
@@ -170,13 +168,11 @@ union_lookup1(udvp, dvp, vpp, cnp)
while (dvp != udvp && (dvp->v_type == VDIR) &&
(mp = dvp->v_mountedhere)) {
- if (mp->mnt_flag & MNT_MLOCK) {
- mp->mnt_flag |= MNT_MWAIT;
- (void) tsleep((caddr_t) mp, PVFS, "unlkup", 0);
+ if (vfs_busy(mp, 0, 0, p))
continue;
- }
error = VFS_ROOT(mp, &tdvp);
+ vfs_unbusy(mp, p);
if (error) {
vput(dvp);
return (error);
@@ -206,9 +202,28 @@ union_lookup(ap)
struct vnode *dvp = ap->a_dvp;
struct union_node *dun = VTOUNION(dvp);
struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
int lockparent = cnp->cn_flags & LOCKPARENT;
struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
- struct ucred *saved_cred = 0;
+ struct ucred *saved_cred;
+ int iswhiteout;
+ struct vattr va;
+
+#ifdef notyet
+ if (cnp->cn_namelen == 3 &&
+ cnp->cn_nameptr[2] == '.' &&
+ cnp->cn_nameptr[1] == '.' &&
+ cnp->cn_nameptr[0] == '.') {
+ dvp = *ap->a_vpp = LOWERVP(ap->a_dvp);
+ if (dvp == NULLVP)
+ return (ENOENT);
+ VREF(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (!lockparent || !(cnp->cn_flags & ISLASTCN))
+ VOP_UNLOCK(ap->a_dvp, 0, p);
+ return (0);
+ }
+#endif
cnp->cn_flags |= LOCKPARENT;
@@ -216,6 +231,7 @@ union_lookup(ap)
lowerdvp = dun->un_lowervp;
uppervp = NULLVP;
lowervp = NULLVP;
+ iswhiteout = 0;
/*
* do the lookup in the upper level.
@@ -223,9 +239,9 @@ union_lookup(ap)
* then assume that something special is going
* on and just return that vnode.
*/
- if (upperdvp) {
- FIXUP(dun);
- uerror = union_lookup1(um->um_uppervp, upperdvp,
+ if (upperdvp != NULLVP) {
+ FIXUP(dun, p);
+ uerror = union_lookup1(um->um_uppervp, &upperdvp,
&uppervp, cnp);
/*if (uppervp == upperdvp)
dun->un_flags |= UN_KLOCK;*/
@@ -236,6 +252,16 @@ union_lookup(ap)
cnp->cn_flags &= ~LOCKPARENT;
return (uerror);
}
+ if (uerror == ENOENT || uerror == EJUSTRETURN) {
+ if (cnp->cn_flags & ISWHITEOUT) {
+ iswhiteout = 1;
+ } else if (lowerdvp != NULLVP) {
+ lerror = VOP_GETATTR(upperdvp, &va,
+ cnp->cn_cred, cnp->cn_proc);
+ if (lerror == 0 && (va.va_flags & OPAQUE))
+ iswhiteout = 1;
+ }
+ }
} else {
uerror = ENOENT;
}
@@ -247,10 +273,10 @@ union_lookup(ap)
* back from the upper layer and return the lower vnode
* instead.
*/
- if (lowerdvp) {
+ if (lowerdvp != NULLVP && !iswhiteout) {
int nameiop;
- VOP_LOCK(lowerdvp);
+ vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, p);
/*
* Only do a LOOKUP on the bottom node, since
@@ -262,17 +288,17 @@ union_lookup(ap)
saved_cred = cnp->cn_cred;
cnp->cn_cred = um->um_cred;
}
- lerror = union_lookup1(um->um_lowervp, lowerdvp,
+ lerror = union_lookup1(um->um_lowervp, &lowerdvp,
&lowervp, cnp);
if (um->um_op == UNMNT_BELOW)
cnp->cn_cred = saved_cred;
cnp->cn_nameiop = nameiop;
if (lowervp != lowerdvp)
- VOP_UNLOCK(lowerdvp);
+ VOP_UNLOCK(lowerdvp, 0, p);
if (cnp->cn_consume != 0) {
- if (uppervp) {
+ if (uppervp != NULLVP) {
if (uppervp == upperdvp)
vrele(uppervp);
else
@@ -286,6 +312,14 @@ union_lookup(ap)
}
} else {
lerror = ENOENT;
+ if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) {
+ lowervp = LOWERVP(dun->un_pvp);
+ if (lowervp != NULLVP) {
+ VREF(lowervp);
+ vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, p);
+ lerror = 0;
+ }
+ }
}
if (!lockparent)
@@ -326,13 +360,13 @@ union_lookup(ap)
if (uerror != 0 /* && (lerror == 0) */ ) {
if (lowervp->v_type == VDIR) { /* case 2b. */
dun->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(upperdvp);
+ VOP_UNLOCK(upperdvp, 0, p);
uerror = union_mkshadow(um, upperdvp, cnp, &uppervp);
- VOP_LOCK(upperdvp);
+ vn_lock(upperdvp, LK_EXCLUSIVE | LK_RETRY, p);
dun->un_flags |= UN_ULOCK;
if (uerror) {
- if (lowervp) {
+ if (lowervp != NULLVP) {
vput(lowervp);
lowervp = NULLVP;
}
@@ -341,21 +375,21 @@ union_lookup(ap)
}
}
- if (lowervp)
- VOP_UNLOCK(lowervp);
+ if (lowervp != NULLVP)
+ VOP_UNLOCK(lowervp, 0, p);
error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
- uppervp, lowervp);
+ uppervp, lowervp, 1);
if (error) {
- if (uppervp)
+ if (uppervp != NULLVP)
vput(uppervp);
- if (lowervp)
+ if (lowervp != NULLVP)
vrele(lowervp);
} else {
if (*ap->a_vpp != dvp)
if (!lockparent || !(cnp->cn_flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
return (error);
@@ -372,28 +406,26 @@ union_create(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
+ struct mount *mp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
+ mp = ap->a_dvp->v_mount;
vput(ap->a_dvp);
- error = VOP_CREATE(dvp, &vp, ap->a_cnp, ap->a_vap);
+ error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
if (error)
return (error);
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, cnp, vp,
+ NULLVP, 1);
if (error)
vput(vp);
return (error);
@@ -404,6 +436,25 @@ union_create(ap)
}
int
+union_whiteout(ap)
+ struct vop_whiteout_args /* {
+ struct vnode *a_dvp;
+ struct componentname *a_cnp;
+ int a_flags;
+ } */ *ap;
+{
+ struct union_node *un = VTOUNION(ap->a_dvp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+
+ if (un->un_uppervp == NULLVP)
+ return (EOPNOTSUPP);
+
+ FIXUP(un, p);
+ return (VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags));
+}
+
+int
union_mknod(ap)
struct vop_mknod_args /* {
struct vnode *a_dvp;
@@ -414,29 +465,27 @@ union_mknod(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
+ struct mount *mp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
+ mp = ap->a_dvp->v_mount;
vput(ap->a_dvp);
- error = VOP_MKNOD(dvp, &vp, ap->a_cnp, ap->a_vap);
+ error = VOP_MKNOD(dvp, &vp, cnp, ap->a_vap);
if (error)
return (error);
- if (vp) {
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ if (vp != NULLVP) {
+ error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
+ cnp, vp, NULLVP, 1);
if (error)
vput(vp);
}
@@ -476,77 +525,7 @@ union_open(ap)
*/
tvp = un->un_lowervp;
if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
- struct vnode *vp;
- int i;
-
- /*
- * Open the named file in the upper layer. Note that
- * the file may have come into existence *since* the
- * lookup was done, since the upper layer may really
- * be a loopback mount of some other filesystem...
- * so open the file with exclusive create and barf if
- * it already exists.
- * XXX - perhaps should re-lookup the node (once more
- * with feeling) and simply open that. Who knows.
- */
- error = union_vn_create(&vp, un, p);
- if (error)
- return (error);
-
- /* at this point, uppervp is locked */
- union_newupper(un, vp);
- un->un_flags |= UN_ULOCK;
-
- /*
- * Now, if the file is being opened with truncation,
- * then the (new) upper vnode is ready to fly,
- * otherwise the data from the lower vnode must be
- * copied to the upper layer first. This only works
- * for regular files (check is made above).
- */
- if ((mode & O_TRUNC) == 0) {
- /*
- * XXX - should not ignore errors
- * from VOP_CLOSE
- */
- VOP_LOCK(tvp);
- error = VOP_OPEN(tvp, FREAD, cred, p);
- if (error == 0) {
- error = union_copyfile(p, cred,
- tvp, un->un_uppervp);
- VOP_UNLOCK(tvp);
- (void) VOP_CLOSE(tvp, FREAD, cred, p);
- } else {
- VOP_UNLOCK(tvp);
- }
-
-#ifdef UNION_DIAGNOSTIC
- if (!error)
- uprintf("union: copied up %s\n",
- un->un_path);
-#endif
- }
-
- un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp);
- union_vn_close(un->un_uppervp, FWRITE, cred, p);
- VOP_LOCK(un->un_uppervp);
- un->un_flags |= UN_ULOCK;
-
- /*
- * Subsequent IOs will go to the top layer, so
- * call close on the lower vnode and open on the
- * upper vnode to ensure that the filesystem keeps
- * its references counts right. This doesn't do
- * the right thing with (cred) and (FREAD) though.
- * Ignoring error returns is not righ, either.
- */
- for (i = 0; i < un->un_openl; i++) {
- (void) VOP_CLOSE(tvp, FREAD, cred, p);
- (void) VOP_OPEN(un->un_uppervp, FREAD, cred, p);
- }
- un->un_openl = 0;
-
+ error = union_copyup(un, (mode&O_TRUNC) == 0, cred, p);
if (error == 0)
error = VOP_OPEN(un->un_uppervp, mode, cred, p);
return (error);
@@ -556,14 +535,14 @@ union_open(ap)
* Just open the lower vnode
*/
un->un_openl++;
- VOP_LOCK(tvp);
+ vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_OPEN(tvp, mode, cred, p);
- VOP_UNLOCK(tvp);
+ VOP_UNLOCK(tvp, 0, p);
return (error);
}
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_OPEN(tvp, mode, cred, p);
@@ -582,9 +561,7 @@ union_close(ap)
struct union_node *un = VTOUNION(ap->a_vp);
struct vnode *vp;
- if (un->un_uppervp) {
- vp = un->un_uppervp;
- } else {
+ if ((vp = un->un_uppervp) == NULLVP) {
#ifdef UNION_DIAGNOSTIC
if (un->un_openl <= 0)
panic("union: un_openl cnt");
@@ -593,7 +570,8 @@ union_close(ap)
vp = un->un_lowervp;
}
- return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));
+ ap->a_vp = vp;
+ return (VCALL(vp, VOFFSET(vop_close), ap));
}
/*
@@ -615,27 +593,29 @@ union_access(ap)
} */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
int error = EACCES;
struct vnode *vp;
- vp = un->un_uppervp;
- if (vp) {
- FIXUP(un);
- return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p));
+ if ((vp = un->un_uppervp) != NULLVP) {
+ FIXUP(un, p);
+ ap->a_vp = vp;
+ return (VCALL(vp, VOFFSET(vop_access), ap));
}
- vp = un->un_lowervp;
- if (vp) {
- VOP_LOCK(vp);
- error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p);
+ if ((vp = un->un_lowervp) != NULLVP) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_access), ap);
if (error == 0) {
struct union_mount *um = MOUNTTOUNIONMOUNT(vp->v_mount);
- if (um->um_op == UNMNT_BELOW)
- error = VOP_ACCESS(vp, ap->a_mode,
- um->um_cred, ap->a_p);
+ if (um->um_op == UNMNT_BELOW) {
+ ap->a_cred = um->um_cred;
+ error = VCALL(vp, VOFFSET(vop_access), ap);
+ }
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
}
@@ -644,7 +624,8 @@ union_access(ap)
}
/*
- * We handle getattr only to change the fsid.
+ * We handle getattr only to change the fsid and
+ * track object sizes
*/
int
union_getattr(ap)
@@ -658,6 +639,7 @@ union_getattr(ap)
int error;
struct union_node *un = VTOUNION(ap->a_vp);
struct vnode *vp = un->un_uppervp;
+ struct proc *p = ap->a_p;
struct vattr *vap;
struct vattr va;
@@ -675,10 +657,21 @@ union_getattr(ap)
vp = un->un_uppervp;
if (vp != NULLVP) {
- FIXUP(un);
+ /*
+ * It's not clear whether VOP_GETATTR is to be
+ * called with the vnode locked or not. stat() calls
+ * it with (vp) locked, and fstat calls it with
+ * (vp) unlocked.
+ * In the mean time, compensate here by checking
+ * the union_node's lock flag.
+ */
+ if (un->un_flags & UN_LOCKED)
+ FIXUP(un, p);
+
error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
if (error)
return (error);
+ union_newsize(ap->a_vp, vap->va_size, VNOVAL);
}
if (vp == NULLVP) {
@@ -691,17 +684,16 @@ union_getattr(ap)
}
if (vp != NULLVP) {
- VOP_LOCK(vp);
error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
- VOP_UNLOCK(vp);
if (error)
return (error);
+ union_newsize(ap->a_vp, VNOVAL, vap->va_size);
}
if ((vap != ap->a_vap) && (vap->va_type == VDIR))
ap->a_vap->va_nlink += vap->va_nlink;
- vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
+ ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
@@ -715,6 +707,7 @@ union_setattr(ap)
} */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
int error;
/*
@@ -724,21 +717,11 @@ union_setattr(ap)
*/
if ((un->un_uppervp == NULLVP) &&
/* assert(un->un_lowervp != NULLVP) */
- (un->un_lowervp->v_type == VREG) &&
- (ap->a_vap->va_size == 0)) {
- struct vnode *vp;
-
- error = union_vn_create(&vp, un, ap->a_p);
+ (un->un_lowervp->v_type == VREG)) {
+ error = union_copyup(un, (ap->a_vap->va_size != 0),
+ ap->a_cred, ap->a_p);
if (error)
return (error);
-
- /* at this point, uppervp is locked */
- union_newupper(un, vp);
-
- VOP_UNLOCK(vp);
- union_vn_close(un->un_uppervp, FWRITE, ap->a_cred, ap->a_p);
- VOP_LOCK(vp);
- un->un_flags |= UN_ULOCK;
}
/*
@@ -746,9 +729,11 @@ union_setattr(ap)
* otherwise return read-only filesystem error.
*/
if (un->un_uppervp != NULLVP) {
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_SETATTR(un->un_uppervp, ap->a_vap,
ap->a_cred, ap->a_p);
+ if ((error == 0) && (ap->a_vap->va_size != VNOVAL))
+ union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL);
} else {
error = EROFS;
}
@@ -766,16 +751,36 @@ union_read(ap)
} */ *ap;
{
int error;
+ struct proc *p = ap->a_uio->uio_procp;
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
+ FIXUP(VTOUNION(ap->a_vp), p);
error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
+
+ /*
+ * XXX
+ * perhaps the size of the underlying object has changed under
+ * our feet. take advantage of the offset information present
+ * in the uio structure.
+ */
+ if (error == 0) {
+ struct union_node *un = VTOUNION(ap->a_vp);
+ off_t cur = ap->a_uio->uio_offset;
+
+ if (vp == un->un_uppervp) {
+ if (cur > un->un_uppersz)
+ union_newsize(ap->a_vp, cur, VNOVAL);
+ } else {
+ if (cur > un->un_lowersz)
+ union_newsize(ap->a_vp, VNOVAL, cur);
+ }
+ }
return (error);
}
@@ -790,21 +795,47 @@ union_write(ap)
} */ *ap;
{
int error;
- struct vnode *vp = OTHERVP(ap->a_vp);
- int dolock = (vp == LOWERVP(ap->a_vp));
+ struct vnode *vp;
+ struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_uio->uio_procp;
- if (dolock)
- VOP_LOCK(vp);
- else
- FIXUP(VTOUNION(ap->a_vp));
+ vp = UPPERVP(ap->a_vp);
+ if (vp == NULLVP)
+ panic("union: missing upper layer in write");
+
+ FIXUP(un, p);
error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
- if (dolock)
- VOP_UNLOCK(vp);
+
+ /*
+ * the size of the underlying object may be changed by the
+ * write.
+ */
+ if (error == 0) {
+ off_t cur = ap->a_uio->uio_offset;
+
+ if (cur > un->un_uppersz)
+ union_newsize(ap->a_vp, cur, VNOVAL);
+ }
return (error);
}
int
+union_lease(ap)
+ struct vop_lease_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ struct ucred *a_cred;
+ int a_flag;
+ } */ *ap;
+{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
+
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_lease), ap));
+}
+
+int
union_ioctl(ap)
struct vop_ioctl_args /* {
struct vnode *a_vp;
@@ -815,9 +846,10 @@ union_ioctl(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_IOCTL(OTHERVP(ap->a_vp), ap->a_command, ap->a_data,
- ap->a_fflag, ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_ioctl), ap));
}
int
@@ -830,9 +862,28 @@ union_select(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_SELECT(OTHERVP(ap->a_vp), ap->a_which, ap->a_fflags,
- ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_select), ap));
+}
+
+int
+union_revoke(ap)
+ struct vop_revoke_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ if (UPPERVP(vp))
+ VOP_REVOKE(UPPERVP(vp), ap->a_flags);
+ if (LOWERVP(vp))
+ VOP_REVOKE(LOWERVP(vp), ap->a_flags);
+ vgone(vp);
+ return (0);
}
int
@@ -844,9 +895,10 @@ union_mmap(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_MMAP(OTHERVP(ap->a_vp), ap->a_fflags,
- ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_mmap), ap));
}
int
@@ -859,19 +911,19 @@ union_fsync(ap)
} */ *ap;
{
int error = 0;
+ struct proc *p = ap->a_p;
struct vnode *targetvp = OTHERVP(ap->a_vp);
- if (targetvp) {
+ if (targetvp != NULLVP) {
int dolock = (targetvp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(targetvp);
+ vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_FSYNC(targetvp, ap->a_cred,
- ap->a_waitfor, ap->a_p);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
if (dolock)
- VOP_UNLOCK(targetvp);
+ VOP_UNLOCK(targetvp, 0, p);
}
return (error);
@@ -886,8 +938,10 @@ union_seek(ap)
struct ucred *a_cred;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_SEEK(OTHERVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_seek), ap));
}
int
@@ -901,34 +955,37 @@ union_remove(ap)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dun->un_uppervp && un->un_uppervp) {
+ if (dun->un_uppervp == NULLVP)
+ panic("union remove: null upper vnode");
+
+ if (un->un_uppervp != NULLVP) {
struct vnode *dvp = dun->un_uppervp;
struct vnode *vp = un->un_uppervp;
- FIXUP(dun);
+ FIXUP(dun, p);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- FIXUP(un);
+ FIXUP(un, p);
VREF(vp);
un->un_flags |= UN_KLOCK;
vput(ap->a_vp);
- error = VOP_REMOVE(dvp, vp, ap->a_cnp);
+ if (union_dowhiteout(un, cnp->cn_cred, cnp->cn_proc))
+ cnp->cn_flags |= DOWHITEOUT;
+ error = VOP_REMOVE(dvp, vp, cnp);
if (!error)
union_removed_upper(un);
-
- /*
- * XXX: should create a whiteout here
- */
} else {
- /*
- * XXX: should create a whiteout here
- */
+ FIXUP(dun, p);
+ error = union_mkwhiteout(
+ MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
+ dun->un_uppervp, ap->a_cnp, un->un_path);
vput(ap->a_dvp);
vput(ap->a_vp);
- error = EROFS;
}
return (error);
@@ -942,34 +999,51 @@ union_link(ap)
struct componentname *a_cnp;
} */ *ap;
{
- int error;
- struct union_node *dun = VTOUNION(ap->a_vp);
- struct union_node *un = VTOUNION(ap->a_tdvp);
-
- if (dun->un_uppervp && un->un_uppervp) {
- struct vnode *dvp = dun->un_uppervp;
- struct vnode *vp = un->un_uppervp;
+ int error = 0;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct union_node *un;
+ struct vnode *vp;
+ struct vnode *tdvp;
- FIXUP(dun);
- VREF(dvp);
- dun->un_flags |= UN_KLOCK;
- vput(ap->a_vp);
- FIXUP(un);
- VREF(vp);
- vrele(ap->a_tdvp);
+ un = VTOUNION(ap->a_tdvp);
- error = VOP_LINK(dvp, vp, ap->a_cnp);
+ if (ap->a_tdvp->v_op != ap->a_vp->v_op) {
+ vp = ap->a_vp;
} else {
- /*
- * XXX: need to copy to upper layer
- * and do the link there.
- */
- vput(ap->a_vp);
- vrele(ap->a_tdvp);
+ struct union_node *tun = VTOUNION(ap->a_vp);
+ if (tun->un_uppervp == NULLVP) {
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (un->un_uppervp == tun->un_dirvp) {
+ un->un_flags &= ~UN_ULOCK;
+ VOP_UNLOCK(un->un_uppervp, 0, p);
+ }
+ error = union_copyup(tun, 1, cnp->cn_cred, p);
+ if (un->un_uppervp == tun->un_dirvp) {
+ vn_lock(un->un_uppervp,
+ LK_EXCLUSIVE | LK_RETRY, p);
+ un->un_flags |= UN_ULOCK;
+ }
+ VOP_UNLOCK(ap->a_vp, 0, p);
+ }
+ vp = tun->un_uppervp;
+ }
+
+ tdvp = un->un_uppervp;
+ if (tdvp == NULLVP)
error = EROFS;
+
+ if (error) {
+ vput(ap->a_tdvp);
+ return (error);
}
- return (error);
+ FIXUP(un, p);
+ VREF(tdvp);
+ un->un_flags |= UN_KLOCK;
+ vput(ap->a_tdvp);
+
+ return (VOP_LINK(vp, tdvp, cnp));
}
int
@@ -993,11 +1067,16 @@ union_rename(ap)
if (fdvp->v_op == union_vnodeop_p) { /* always true */
struct union_node *un = VTOUNION(fdvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /*
+ * this should never happen in normal
+ * operation but might if there was
+ * a problem creating the top-level shadow
+ * directory.
+ */
+ error = EXDEV;
goto bad;
}
- FIXUP(un);
fdvp = un->un_uppervp;
VREF(fdvp);
vrele(ap->a_fdvp);
@@ -1006,11 +1085,14 @@ union_rename(ap)
if (fvp->v_op == union_vnodeop_p) { /* always true */
struct union_node *un = VTOUNION(fvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /* XXX: should do a copyup */
+ error = EXDEV;
goto bad;
}
- FIXUP(un);
+ if (un->un_lowervp != NULLVP)
+ ap->a_fcnp->cn_flags |= DOWHITEOUT;
+
fvp = un->un_uppervp;
VREF(fvp);
vrele(ap->a_fvp);
@@ -1019,7 +1101,13 @@ union_rename(ap)
if (tdvp->v_op == union_vnodeop_p) {
struct union_node *un = VTOUNION(tdvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /*
+ * this should never happen in normal
+ * operation but might if there was
+ * a problem creating the top-level shadow
+ * directory.
+ */
+ error = EXDEV;
goto bad;
}
@@ -1029,16 +1117,14 @@ union_rename(ap)
vput(ap->a_tdvp);
}
- if (tvp && tvp->v_op == union_vnodeop_p) {
+ if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) {
struct union_node *un = VTOUNION(tvp);
- if (un->un_uppervp == NULLVP) {
- error = EROFS;
- goto bad;
- }
tvp = un->un_uppervp;
- VREF(tvp);
- un->un_flags |= UN_KLOCK;
+ if (tvp != NULLVP) {
+ VREF(tvp);
+ un->un_flags |= UN_KLOCK;
+ }
vput(ap->a_tvp);
}
@@ -1048,7 +1134,7 @@ bad:
vrele(fdvp);
vrele(fvp);
vput(tdvp);
- if (tvp)
+ if (tvp != NULLVP)
vput(tvp);
return (error);
@@ -1065,27 +1151,26 @@ union_mkdir(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
- vput(ap->a_dvp);
- error = VOP_MKDIR(dvp, &vp, ap->a_cnp, ap->a_vap);
- if (error)
+ VOP_UNLOCK(ap->a_dvp, 0, p);
+ error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap);
+ if (error) {
+ vrele(ap->a_dvp);
return (error);
+ }
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp,
+ NULLVP, cnp, vp, NULLVP, 1);
+ vrele(ap->a_dvp);
if (error)
vput(vp);
return (error);
@@ -1106,34 +1191,37 @@ union_rmdir(ap)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dun->un_uppervp && un->un_uppervp) {
+ if (dun->un_uppervp == NULLVP)
+ panic("union rmdir: null upper vnode");
+
+ if (un->un_uppervp != NULLVP) {
struct vnode *dvp = dun->un_uppervp;
struct vnode *vp = un->un_uppervp;
- FIXUP(dun);
+ FIXUP(dun, p);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- FIXUP(un);
+ FIXUP(un, p);
VREF(vp);
un->un_flags |= UN_KLOCK;
vput(ap->a_vp);
+ if (union_dowhiteout(un, cnp->cn_cred, cnp->cn_proc))
+ cnp->cn_flags |= DOWHITEOUT;
error = VOP_RMDIR(dvp, vp, ap->a_cnp);
if (!error)
union_removed_upper(un);
-
- /*
- * XXX: should create a whiteout here
- */
} else {
- /*
- * XXX: should create a whiteout here
- */
+ FIXUP(dun, p);
+ error = union_mkwhiteout(
+ MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
+ dun->un_uppervp, ap->a_cnp, un->un_path);
vput(ap->a_dvp);
vput(ap->a_vp);
- error = EROFS;
}
return (error);
@@ -1151,17 +1239,18 @@ union_symlink(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- error = VOP_SYMLINK(dvp, &vp, ap->a_cnp,
- ap->a_vap, ap->a_target);
+ error = VOP_SYMLINK(dvp, &vp, cnp, ap->a_vap, ap->a_target);
*ap->a_vpp = NULLVP;
return (error);
}
@@ -1183,17 +1272,21 @@ union_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
- int error = 0;
struct union_node *un = VTOUNION(ap->a_vp);
+ struct vnode *uvp = un->un_uppervp;
+ struct proc *p = ap->a_uio->uio_procp;
- if (un->un_uppervp) {
- FIXUP(un);
- error = VOP_READDIR(un->un_uppervp, ap->a_uio, ap->a_cred, NULL, NULL, NULL);
- }
+ if (uvp == NULLVP)
+ return (0);
- return (error);
+ FIXUP(un, p);
+ ap->a_vp = uvp;
+ return (VCALL(uvp, VOFFSET(vop_readdir), ap));
}
int
@@ -1205,16 +1298,19 @@ union_readlink(ap)
} */ *ap;
{
int error;
+ struct uio *uio = ap->a_uio;
+ struct proc *p = uio->uio_procp;
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_READLINK(vp, ap->a_uio, ap->a_cred);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_readlink), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1227,6 +1323,8 @@ union_abortop(ap)
} */ *ap;
{
int error;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
struct vnode *vp = OTHERVP(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_dvp);
int islocked = un->un_flags & UN_LOCKED;
@@ -1234,13 +1332,14 @@ union_abortop(ap)
if (islocked) {
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_dvp));
+ FIXUP(VTOUNION(ap->a_dvp), p);
}
- error = VOP_ABORTOP(vp, ap->a_cnp);
+ ap->a_dvp = vp;
+ error = VCALL(vp, VOFFSET(vop_abortop), ap);
if (islocked && dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1249,8 +1348,13 @@ int
union_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
+ struct union_node *un = VTOUNION(vp);
+ struct vnode **vpp;
/*
* Do nothing (and _don't_ bypass).
@@ -1265,12 +1369,17 @@ union_inactive(ap)
* That's too much work for now.
*/
-#ifdef UNION_DIAGNOSTIC
- struct union_node *un = VTOUNION(ap->a_vp);
+ if (un->un_dircache != 0) {
+ for (vpp = un->un_dircache; *vpp != NULLVP; vpp++)
+ vrele(*vpp);
+ free(un->un_dircache, M_TEMP);
+ un->un_dircache = 0;
+ }
- if (un->un_flags & UN_LOCKED)
- panic("union: inactivating locked node");
-#endif
+ VOP_UNLOCK(vp, 0, p);
+
+ if ((un->un_flags & UN_CACHED) == 0)
+ vgone(vp);
return (0);
}
@@ -1292,24 +1401,39 @@ union_lock(ap)
struct vop_lock_args *ap;
{
struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
+ int flags = ap->a_flags;
struct union_node *un;
+ int error;
-start:
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t)vp, PINOD, "unnlk1", 0);
- }
+ vop_nolock(ap);
+ /*
+ * Need to do real lockmgr-style locking here.
+ * in the mean time, draining won't work quite right,
+ * which could lead to a few race conditions.
+ * the following test was here, but is not quite right, we
+ * still need to take the lock:
+ if ((flags & LK_TYPE_MASK) == LK_DRAIN)
+ return (0);
+ */
+ flags &= ~LK_INTERLOCK;
+start:
un = VTOUNION(vp);
- if (un->un_uppervp) {
- if ((un->un_flags & UN_ULOCK) == 0) {
+ if (un->un_uppervp != NULLVP) {
+ if (((un->un_flags & UN_ULOCK) == 0) &&
+ (vp->v_usecount != 0)) {
+ error = vn_lock(un->un_uppervp, flags, p);
+ if (error)
+ return (error);
un->un_flags |= UN_ULOCK;
- VOP_LOCK(un->un_uppervp);
}
#ifdef DIAGNOSTIC
- if (un->un_flags & UN_KLOCK)
- panic("union: dangling upper lock");
+ if (un->un_flags & UN_KLOCK) {
+ vprint("union: dangling klock", vp);
+ panic("union: dangling upper lock (%lx)", vp);
+ }
#endif
}
@@ -1320,7 +1444,7 @@ start:
panic("union: locking against myself");
#endif
un->un_flags |= UN_WANT;
- (void) tsleep((caddr_t) &un->un_flags, PINOD, "unnlk2", 0);
+ tsleep((caddr_t)&un->un_flags, PINOD, "unionlk2", 0);
goto start;
}
@@ -1335,11 +1459,27 @@ start:
return (0);
}
+/*
+ * When operations want to vput() a union node yet retain a lock on
+ * the upper vnode (say, to do some further operations like link(),
+ * mkdir(), ...), they set UN_KLOCK on the union node, then call
+ * vput() which calls VOP_UNLOCK() and comes here. union_unlock()
+ * unlocks the union node (leaving the upper vnode alone), clears the
+ * KLOCK flag, and then returns to vput(). The caller then does whatever
+ * is left to do with the upper vnode, and ensures that it gets unlocked.
+ *
+ * If UN_KLOCK isn't set, then the upper vnode is unlocked here.
+ */
int
union_unlock(ap)
- struct vop_lock_args *ap;
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
#ifdef DIAGNOSTIC
if ((un->un_flags & UN_LOCKED) == 0)
@@ -1352,7 +1492,7 @@ union_unlock(ap)
un->un_flags &= ~UN_LOCKED;
if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK)
- VOP_UNLOCK(un->un_uppervp);
+ VOP_UNLOCK(un->un_uppervp, 0, p);
un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
@@ -1364,6 +1504,7 @@ union_unlock(ap)
#ifdef DIAGNOSTIC
un->un_pid = 0;
#endif
+ vop_nounlock(ap);
return (0);
}
@@ -1380,16 +1521,18 @@ union_bmap(ap)
} */ *ap;
{
int error;
+ struct proc *p = curproc; /* XXX */
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_BMAP(vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp, ap->a_runb);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_bmap), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1404,6 +1547,11 @@ union_print(ap)
printf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n",
vp, UPPERVP(vp), LOWERVP(vp));
+ if (UPPERVP(vp) != NULLVP)
+ vprint("union: upper", UPPERVP(vp));
+ if (LOWERVP(vp) != NULLVP)
+ vprint("union: lower", LOWERVP(vp));
+
return (0);
}
@@ -1426,16 +1574,18 @@ union_pathconf(ap)
} */ *ap;
{
int error;
+ struct proc *p = curproc; /* XXX */
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_PATHCONF(vp, ap->a_name, ap->a_retval);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_pathconf), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1450,9 +1600,10 @@ union_advlock(ap)
int a_flags;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_ADVLOCK(OTHERVP(ap->a_vp), ap->a_id, ap->a_op,
- ap->a_fl, ap->a_flags));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_advlock), ap));
}
@@ -1496,6 +1647,7 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
{ &vop_lookup_desc, (vop_t *)union_lookup }, /* lookup */
{ &vop_create_desc, (vop_t *)union_create }, /* create */
+ { &vop_whiteout_desc, (vop_t *)union_whiteout }, /* whiteout */
{ &vop_mknod_desc, (vop_t *)union_mknod }, /* mknod */
{ &vop_open_desc, (vop_t *)union_open }, /* open */
{ &vop_close_desc, (vop_t *)union_close }, /* close */
@@ -1504,8 +1656,10 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)union_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)union_read }, /* read */
{ &vop_write_desc, (vop_t *)union_write }, /* write */
+ { &vop_lease_desc, (vop_t *)union_lease }, /* lease */
{ &vop_ioctl_desc, (vop_t *)union_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)union_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)union_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)union_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)union_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)union_seek }, /* seek */
diff --git a/sys/gnu/ext2fs/ext2_bmap.c b/sys/gnu/ext2fs/ext2_bmap.c
index e17b5b7..aef2b83 100644
--- a/sys/gnu/ext2fs/ext2_bmap.c
+++ b/sys/gnu/ext2fs/ext2_bmap.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94
+ * @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
* $FreeBSD$
*/
@@ -63,9 +63,9 @@ int
ufs_bmap(ap)
struct vop_bmap_args /* {
struct vnode *a_vp;
- daddr_t a_bn;
+ ufs_daddr_t a_bn;
struct vnode **a_vpp;
- daddr_t *a_bnp;
+ ufs_daddr_t *a_bnp;
int *a_runp;
int *a_runb;
} */ *ap;
@@ -100,8 +100,8 @@ ufs_bmap(ap)
int
ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
struct vnode *vp;
- register daddr_t bn;
- daddr_t *bnp;
+ ufs_daddr_t bn;
+ ufs_daddr_t *bnp;
struct indir *ap;
int *nump;
int *runp;
@@ -113,7 +113,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
struct mount *mp;
struct vnode *devvp;
struct indir a[NIADDR+1], *xap;
- daddr_t daddr;
+ ufs_daddr_t daddr;
long metalbn;
int error, maxrun = 0, num;
@@ -209,12 +209,13 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
}
}
- daddr = ((daddr_t *)bp->b_data)[xap->in_off];
+ daddr = ((ufs_daddr_t *)bp->b_data)[xap->in_off];
if (num == 1 && daddr && runp) {
for (bn = xap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
- is_sequential(ump, ((daddr_t *)bp->b_data)[bn - 1],
- ((daddr_t *)bp->b_data)[bn]);
+ is_sequential(ump,
+ ((ufs_daddr_t *)bp->b_data)[bn - 1],
+ ((ufs_daddr_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = xap->in_off;
if (runb && bn) {
@@ -245,7 +246,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
int
ufs_getlbns(vp, bn, ap, nump)
struct vnode *vp;
- register daddr_t bn;
+ ufs_daddr_t bn;
struct indir *ap;
int *nump;
{
diff --git a/sys/gnu/ext2fs/ext2_extern.h b/sys/gnu/ext2fs/ext2_extern.h
index f07b7b7..de6cd08f 100644
--- a/sys/gnu/ext2fs/ext2_extern.h
+++ b/sys/gnu/ext2fs/ext2_extern.h
@@ -56,7 +56,7 @@ int ext2_blkatoff __P((struct vop_blkatoff_args *));
void ext2_blkfree __P((struct inode *, daddr_t, long));
daddr_t ext2_blkpref __P((struct inode *, daddr_t, int, daddr_t *, daddr_t));
int ext2_bmap __P((struct vop_bmap_args *));
-int ext2_init __P((void));
+int ext2_init __P((struct vfsconf *));
int ext2_reallocblks __P((struct vop_reallocblks_args *));
int ext2_reclaim __P((struct vop_reclaim_args *));
void ext2_setblock __P((struct ext2_sb_info *, u_char *, daddr_t));
diff --git a/sys/gnu/ext2fs/ext2_ihash.c b/sys/gnu/ext2fs/ext2_ihash.c
index a51af00..ea83308 100644
--- a/sys/gnu/ext2fs/ext2_ihash.c
+++ b/sys/gnu/ext2fs/ext2_ihash.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1982, 1986, 1989, 1991, 1993
+ * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93
+ * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
* $FreeBSD$
*/
@@ -47,9 +47,10 @@
/*
* Structures associated with inode cacheing.
*/
-struct inode **ihashtbl;
+LIST_HEAD(ihashhead, inode) *ihashtbl;
u_long ihash; /* size of hash table - 1 */
-#define INOHASH(device, inum) (((device) + (inum)) & ihash)
+#define INOHASH(device, inum) (&ihashtbl[((device) + (inum)) & ihash])
+struct simplelock ufs_ihash_slock;
/*
* Initialize inode hash table.
@@ -59,6 +60,7 @@ ufs_ihashinit()
{
ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash);
+ simple_lock_init(&ufs_ihash_slock);
}
/*
@@ -66,19 +68,21 @@ ufs_ihashinit()
* to it. If it is in core, return it, even if it is locked.
*/
struct vnode *
-ufs_ihashlookup(device, inum)
- dev_t device;
+ufs_ihashlookup(dev, inum)
+ dev_t dev;
ino_t inum;
{
- register struct inode *ip;
+ struct inode *ip;
- for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
- if (ip == NULL)
- return (NULL);
- if (inum == ip->i_number && device == ip->i_dev)
- return (ITOV(ip));
- }
- /* NOTREACHED */
+ simple_lock(&ufs_ihash_slock);
+ for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next)
+ if (inum == ip->i_number && dev == ip->i_dev)
+ break;
+ simple_unlock(&ufs_ihash_slock);
+
+ if (ip)
+ return (ITOV(ip));
+ return (NULLVP);
}
/*
@@ -86,36 +90,28 @@ ufs_ihashlookup(device, inum)
* to it. If it is in core, but locked, wait for it.
*/
struct vnode *
-ufs_ihashget(device, inum)
- dev_t device;
+ufs_ihashget(dev, inum)
+ dev_t dev;
ino_t inum;
{
- register struct inode *ip;
+ struct proc *p = curproc; /* XXX */
+ struct inode *ip;
struct vnode *vp;
- for (;;)
- for (ip = ihashtbl[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) {
- if( curproc->p_pid != ip->i_lockholder) {
- ip->i_flag |= IN_WANTED;
- (void) tsleep(ip, PINOD, "uihget", 0);
- break;
- } else if (ip->i_flag & IN_RECURSE) {
- ip->i_lockcount++;
- } else {
- panic("ufs_ihashget: recursive lock not expected -- pid %d\n", ip->i_lockholder);
- }
- }
- vp = ITOV(ip);
- if (!vget(vp, 1))
- return (vp);
- break;
- }
+loop:
+ simple_lock(&ufs_ihash_slock);
+ for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
+ if (inum == ip->i_number && dev == ip->i_dev) {
+ vp = ITOV(ip);
+ simple_lock(&vp->v_interlock);
+ simple_unlock(&ufs_ihash_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
+ goto loop;
+ return (vp);
}
- /* NOTREACHED */
+ }
+ simple_unlock(&ufs_ihash_slock);
+ return (NULL);
}
/*
@@ -125,26 +121,16 @@ void
ufs_ihashins(ip)
struct inode *ip;
{
- struct inode **ipp, *iq;
+ struct proc *p = curproc; /* XXX */
+ struct ihashhead *ipp;
- ipp = &ihashtbl[INOHASH(ip->i_dev, ip->i_number)];
- iq = *ipp;
- if (iq)
- iq->i_prev = &ip->i_next;
- ip->i_next = iq;
- ip->i_prev = ipp;
- *ipp = ip;
- if ((ip->i_flag & IN_LOCKED) &&
- ((ip->i_flag & IN_RECURSE) == 0 ||
- (!curproc || (curproc && (ip->i_lockholder != curproc->p_pid)))))
- panic("ufs_ihashins: already locked");
- if (curproc) {
- ip->i_lockcount += 1;
- ip->i_lockholder = curproc->p_pid;
- } else {
- ip->i_lockholder = -1;
- }
- ip->i_flag |= IN_LOCKED;
+ /* lock the inode, then put it on the appropriate hash list */
+ lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
+
+ simple_lock(&ufs_ihash_slock);
+ ipp = INOHASH(ip->i_dev, ip->i_number);
+ LIST_INSERT_HEAD(ipp, ip, i_hash);
+ simple_unlock(&ufs_ihash_slock);
}
/*
@@ -152,16 +138,13 @@ ufs_ihashins(ip)
*/
void
ufs_ihashrem(ip)
- register struct inode *ip;
+ struct inode *ip;
{
- register struct inode *iq;
-
- iq = ip->i_next;
- if (iq)
- iq->i_prev = ip->i_prev;
- *ip->i_prev = iq;
+ simple_lock(&ufs_ihash_slock);
+ LIST_REMOVE(ip, i_hash);
#ifdef DIAGNOSTIC
- ip->i_next = NULL;
- ip->i_prev = NULL;
+ ip->i_hash.le_next = NULL;
+ ip->i_hash.le_prev = NULL;
#endif
+ simple_unlock(&ufs_ihash_slock);
}
diff --git a/sys/gnu/ext2fs/ext2_inode.c b/sys/gnu/ext2fs/ext2_inode.c
index d3b7038..788f5eb 100644
--- a/sys/gnu/ext2fs/ext2_inode.c
+++ b/sys/gnu/ext2fs/ext2_inode.c
@@ -77,9 +77,9 @@ static int ext2_indirtrunc __P((struct inode *, daddr_t, daddr_t, daddr_t, int,
long *));
int
-ext2_init()
+ext2_init(struct vfsconf *vfsp)
{
- return (ufs_init());
+ return (ufs_init(vfsp));
}
/*
@@ -118,16 +118,16 @@ ext2_update(ap)
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
return (0);
if (ip->i_flag & IN_ACCESS)
- ip->i_atime.tv_sec = ap->a_access->tv_sec;
+ ip->i_atime = ap->a_access->tv_sec;
if (ip->i_flag & IN_UPDATE) {
- ip->i_mtime.tv_sec = ap->a_modify->tv_sec;
+ ip->i_mtime = ap->a_modify->tv_sec;
ip->i_modrev++;
}
if (ip->i_flag & IN_CHANGE) {
#if !defined(__FreeBSD__)
get_time(&time);
#endif
- ip->i_ctime.tv_sec = time.tv_sec;
+ ip->i_ctime = time.tv_sec;
}
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
fs = ip->i_e2fs;
diff --git a/sys/gnu/ext2fs/ext2_inode_cnv.c b/sys/gnu/ext2fs/ext2_inode_cnv.c
index fbc743b..a39e7b9 100644
--- a/sys/gnu/ext2fs/ext2_inode_cnv.c
+++ b/sys/gnu/ext2fs/ext2_inode_cnv.c
@@ -66,17 +66,17 @@ ext2_print_dinode( di )
di->di_uid, di->di_gid, di->di_size);
printf( "Links: %3d Blockcount: %d\n",
di->di_nlink, di->di_blocks);
- printf( "ctime: 0x%x", di->di_ctime.tv_sec);
+ printf( "ctime: 0x%x", di->di_ctime);
#if !defined(__FreeBSD__)
- print_time(" -- %s\n", di->di_ctime.tv_sec);
+ print_time(" -- %s\n", di->di_ctime);
#endif
- printf( "atime: 0x%x", di->di_atime.tv_sec);
+ printf( "atime: 0x%x", di->di_atime);
#if !defined(__FreeBSD__)
- print_time(" -- %s\n", di->di_atime.tv_sec);
+ print_time(" -- %s\n", di->di_atime);
#endif
- printf( "mtime: 0x%x", di->di_mtime.tv_sec);
+ printf( "mtime: 0x%x", di->di_mtime);
#if !defined(__FreeBSD__)
- print_time(" -- %s\n", di->di_mtime.tv_sec);
+ print_time(" -- %s\n", di->di_mtime);
#endif
printf( "BLOCKS: ");
for(i=0; i < (di->di_blocks <= 24 ? ((di->di_blocks+1)/2): 12); i++)
@@ -110,9 +110,9 @@ ext2_ei2di(ei, di)
*/
di->di_mode = ei->i_links_count ? ei->i_mode : 0;
di->di_size = ei->i_size;
- di->di_atime.tv_sec = ei->i_atime;
- di->di_mtime.tv_sec = ei->i_mtime;
- di->di_ctime.tv_sec = ei->i_ctime;
+ di->di_atime = ei->i_atime;
+ di->di_mtime = ei->i_mtime;
+ di->di_ctime = ei->i_ctime;
di->di_flags = 0;
di->di_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0;
di->di_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0;
@@ -143,11 +143,11 @@ ext2_di2ei(di, ei)
Godmar thinks: if dtime is nonzero, ext2 says this inode
has been deleted, this would correspond to a zero link count
*/
- ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime.tv_sec;
+ ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime;
ei->i_size = di->di_size;
- ei->i_atime = di->di_atime.tv_sec;
- ei->i_mtime = di->di_mtime.tv_sec;
- ei->i_ctime = di->di_ctime.tv_sec;
+ ei->i_atime = di->di_atime;
+ ei->i_mtime = di->di_mtime;
+ ei->i_ctime = di->di_ctime;
ei->i_flags = di->di_flags;
ei->i_flags = 0;
ei->i_flags |= (di->di_flags & APPEND) ? EXT2_APPEND_FL: 0;
diff --git a/sys/gnu/ext2fs/ext2_lookup.c b/sys/gnu/ext2fs/ext2_lookup.c
index baeaa52..eabd40e 100644
--- a/sys/gnu/ext2fs/ext2_lookup.c
+++ b/sys/gnu/ext2fs/ext2_lookup.c
@@ -274,6 +274,7 @@ ext2_lookup(ap)
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
+ struct proc *p = cnp->cn_proc;
int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize;
@@ -318,14 +319,14 @@ ext2_lookup(ap)
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, p);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
/*
* Check that the capability number did not change
@@ -336,9 +337,9 @@ ext2_lookup(ap)
return (0);
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
- if (error = VOP_LOCK(pdp))
+ if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
return (error);
vdp = pdp;
dp = VTOI(pdp);
@@ -548,7 +549,7 @@ searchloop:
*/
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (EJUSTRETURN);
}
/*
@@ -625,7 +626,7 @@ found:
}
*vpp = tdp;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (0);
}
@@ -650,7 +651,7 @@ found:
*vpp = tdp;
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (0);
}
@@ -675,13 +676,13 @@ found:
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp); /* race to get the inode */
+ VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) {
- VOP_LOCK(pdp);
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
if (lockparent && (flags & ISLASTCN) &&
- (error = VOP_LOCK(pdp))) {
+ (error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
vput(tdp);
return (error);
}
@@ -693,7 +694,7 @@ found:
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp))
return (error);
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
*vpp = tdp;
}
diff --git a/sys/gnu/ext2fs/ext2_mount.h b/sys/gnu/ext2fs/ext2_mount.h
index d7b7b28..87041a6 100644
--- a/sys/gnu/ext2fs/ext2_mount.h
+++ b/sys/gnu/ext2fs/ext2_mount.h
@@ -30,13 +30,34 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufsmount.h 8.2 (Berkeley) 1/12/94
+ * @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
* $FreeBSD$
*/
#ifndef _UFS_UFS_UFSMOUNT_H_
#define _UFS_UFS_UFSMOUNT_H_
+/*
+ * Arguments to mount UFS-based filesystems
+ */
+struct ufs_args {
+ char *fspec; /* block special device to mount */
+ struct export_args export; /* network export information */
+};
+
+#ifdef MFS
+/*
+ * Arguments to mount MFS
+ */
+struct mfs_args {
+ char *fspec; /* name to export for statfs */
+ struct export_args export; /* if exported MFSes are supported */
+ caddr_t base; /* base of file system in memory */
+ u_long size; /* size of file system */
+};
+#endif /* MFS */
+
+#ifdef KERNEL
struct buf;
struct inode;
struct nameidata;
@@ -51,6 +72,7 @@ struct ufsmount {
struct mount *um_mountp; /* filesystem vfs structure */
dev_t um_dev; /* device mounted */
struct vnode *um_devvp; /* block device mounted vnode */
+
union { /* pointer to superblock */
struct lfs *lfs; /* LFS */
struct fs *fs; /* FFS */
@@ -60,6 +82,7 @@ struct ufsmount {
#define um_lfs ufsmount_u.lfs
#define um_e2fs ufsmount_u.e2fs
#define um_e2fsb ufsmount_u.e2fs->s_es
+
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
u_long um_nindir; /* indirect ptrs per block */
@@ -69,7 +92,9 @@ struct ufsmount {
time_t um_itime[MAXQUOTAS]; /* inode quota time limit */
char um_qflags[MAXQUOTAS]; /* quota specific flags */
struct netexport um_export; /* export information */
+ int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */
};
+
/*
* Flags describing the state of quotas.
*/
@@ -83,8 +108,9 @@ struct ufsmount {
* Macros to access file system parameters in the ufsmount structure.
* Used by ufs_bmap.
*/
-#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
-#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
-#define MNINDIR(ump) ((ump)->um_nindir)
+#define MNINDIR(ump) ((ump)->um_nindir)
+#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
+#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
+#endif /* KERNEL */
#endif
diff --git a/sys/gnu/ext2fs/ext2_vfsops.c b/sys/gnu/ext2fs/ext2_vfsops.c
index d7c3e03..f01c059 100644
--- a/sys/gnu/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/ext2fs/ext2_vfsops.c
@@ -221,10 +221,10 @@ ext2_mount(mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp))
+ if (vfs_busy(mp, LK_NOWAIT, 0, p))
return (EBUSY);
error = ext2_flushfiles(mp, flags, p);
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
if (!error && (mp->mnt_flag & MNT_RELOAD))
error = ext2_reload(mp, ndp->ni_cnd.cn_cred, p);
@@ -515,7 +515,7 @@ loop:
/*
* Step 5: invalidate all cached file data.
*/
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
if (vinvalbuf(vp, 0, cred, p, 0, 0))
panic("ext2_reload: dirty2");
@@ -727,17 +727,12 @@ ext2_flushfiles(mp, flags, p)
int flags;
struct proc *p;
{
-#if !defined(__FreeBSD__)
- extern int doforce;
-#endif
register struct ufsmount *ump;
int error;
#if QUOTA
int i;
#endif
- if (!doforce)
- flags &= ~FORCECLOSE;
ump = VFSTOUFS(mp);
#if QUOTA
if (mp->mnt_flag & MNT_QUOTA) {
@@ -872,7 +867,7 @@ loop:
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL)
continue;
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
if (error = VOP_FSYNC(vp, cred, waitfor, p))
allerror = error;
diff --git a/sys/gnu/ext2fs/fs.h b/sys/gnu/ext2fs/fs.h
index 28071d4..03f137c 100644
--- a/sys/gnu/ext2fs/fs.h
+++ b/sys/gnu/ext2fs/fs.h
@@ -152,6 +152,6 @@ extern u_char *fragtbl[];
* I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
*/
#define DEVVP(inode) (VFSTOUFS(ITOV(inode)->v_mount)->um_devvp)
-#define lock_super(devvp) VOP_LOCK(devvp)
-#define unlock_super(devvp) VOP_UNLOCK(devvp)
+#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curproc)
+#define unlock_super(devvp) VOP_UNLOCK(devvp, 0, curproc)
diff --git a/sys/gnu/ext2fs/inode.h b/sys/gnu/ext2fs/inode.h
index dc19d34..438471f 100644
--- a/sys/gnu/ext2fs/inode.h
+++ b/sys/gnu/ext2fs/inode.h
@@ -35,42 +35,33 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)inode.h 8.4 (Berkeley) 1/21/94
+ * @(#)inode.h 8.9 (Berkeley) 5/14/95
* $FreeBSD$
*/
#ifndef _UFS_UFS_INODE_H_
#define _UFS_UFS_INODE_H_
+#include <ufs/ufs/dir.h>
#include <ufs/ufs/dinode.h>
/*
- * Theoretically, directories can be more than 2Gb in length, however, in
- * practice this seems unlikely. So, we define the type doff_t as a long
- * to keep down the cost of doing lookup on a 32-bit machine. If you are
- * porting to a 64-bit architecture, you should make doff_t the same as off_t.
- */
-#define doff_t long
-
-/*
- * The inode is used to describe each active (or recently active)
- * file in the UFS filesystem. It is composed of two types of
- * information. The first part is the information that is needed
- * only while the file is active (such as the identity of the file
- * and linkage to speed its lookup). The second part is the
- * permanent meta-data associated with the file which is read
- * in from the permanent dinode from long term storage when the
- * file becomes active, and is put back when the file is no longer
- * being used.
+ * The inode is used to describe each active (or recently active) file in the
+ * UFS filesystem. It is composed of two types of information. The first part
+ * is the information that is needed only while the file is active (such as
+ * the identity of the file and linkage to speed its lookup). The second part
+ * is the permanent meta-data associated with the file which is read in
+ * from the permanent dinode from long term storage when the file becomes
+ * active, and is put back when the file is no longer being used.
*/
struct inode {
- struct inode *i_next; /* Hash chain forward. */
- struct inode **i_prev; /* Hash chain back. */
- struct vnode *i_vnode; /* Vnode associated with this inode. */
- struct vnode *i_devvp; /* Vnode for block I/O. */
- u_long i_flag; /* I* flags. */
- dev_t i_dev; /* Device associated with the inode. */
- ino_t i_number; /* The identity of the inode. */
+ LIST_ENTRY(inode) i_hash;/* Hash chain. */
+ struct vnode *i_vnode;/* Vnode associated with this inode. */
+ struct vnode *i_devvp;/* Vnode for block I/O. */
+ u_int32_t i_flag; /* flags, see below */
+ dev_t i_dev; /* Device associated with the inode. */
+ ino_t i_number; /* The identity of the inode. */
+
union { /* Associated filesystem. */
struct fs *fs; /* FFS */
struct lfs *lfs; /* LFS */
@@ -79,22 +70,21 @@ struct inode {
#define i_fs inode_u.fs
#define i_lfs inode_u.lfs
#define i_e2fs inode_u.e2fs
- struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
- u_quad_t i_modrev; /* Revision level for lease. */
- struct lockf *i_lockf; /* Head of byte-level lock list. */
- pid_t i_lockholder; /* DEBUG: holder of inode lock. */
- pid_t i_lockwaiter; /* DEBUG: latest blocked for inode lock. */
+ struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
+ u_quad_t i_modrev; /* Revision level for NFS lease. */
+ struct lockf *i_lockf;/* Head of byte-level lock list. */
+ struct lock i_lock; /* Inode lock. */
/*
* Side effects; used during directory lookup.
*/
- long i_count; /* Size of free slot in directory. */
- doff_t i_endoff; /* End of useful stuff in directory. */
- 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. */
- u_long i_reclen; /* Size of found directory entry. */
- int i_lockcount; /* Process lock count (recursion) */
- long i_spare[10]; /* Spares to round up to 128 bytes. */
+ int32_t i_count; /* Size of free slot in directory. */
+ doff_t i_endoff; /* End of useful stuff in directory. */
+ 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. */
+ u_int32_t i_reclen; /* Size of found directory entry. */
+ int i_lockcount; /* Process lock count (recursion) */
+ int i_spare[10]; /* XXX spare storage (for ext2fs) */
/*
* The on-disk dinode itself.
*/
@@ -102,8 +92,10 @@ struct inode {
};
#define i_atime i_din.di_atime
+#define i_atimensec i_din.di_atimensec
#define i_blocks i_din.di_blocks
#define i_ctime i_din.di_ctime
+#define i_ctimensec i_din.di_ctimensec
#define i_db i_din.di_db
#define i_flags i_din.di_flags
#define i_gen i_din.di_gen
@@ -111,6 +103,7 @@ struct inode {
#define i_ib i_din.di_ib
#define i_mode i_din.di_mode
#define i_mtime i_din.di_mtime
+#define i_mtimensec i_din.di_mtimensec
#define i_nlink i_din.di_nlink
#define i_rdev i_din.di_rdev
#define i_shortlink i_din.di_shortlink
@@ -120,15 +113,12 @@ struct inode {
/* These flags are kept in i_flag. */
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
-#define IN_EXLOCK 0x0004 /* File has exclusive lock. */
-#define IN_LOCKED 0x0008 /* Inode lock. */
-#define IN_LWAIT 0x0010 /* Process waiting on file lock. */
-#define IN_MODIFIED 0x0020 /* Inode has been modified. */
-#define IN_RENAME 0x0040 /* Inode is being renamed. */
-#define IN_SHLOCK 0x0080 /* File has shared lock. */
-#define IN_UPDATE 0x0100 /* Modification time update request. */
-#define IN_WANTED 0x0200 /* Inode is wanted by a process. */
-#define IN_RECURSE 0x0400 /* Recursion expected */
+#define IN_UPDATE 0x0004 /* Modification time update request. */
+#define IN_MODIFIED 0x0008 /* Inode has been modified. */
+#define IN_RENAME 0x0010 /* Inode is being renamed. */
+#define IN_SHLOCK 0x0020 /* File has shared lock. */
+#define IN_EXLOCK 0x0040 /* File has exclusive lock. */
+#define IN_RECURSE 0x0080 /* Recursion expected */
#ifdef KERNEL
/*
@@ -136,7 +126,7 @@ struct inode {
* ufs_getlbns and used by truncate and bmap code.
*/
struct indir {
- daddr_t in_lbn; /* Logical block number. */
+ ufs_daddr_t in_lbn; /* Logical block number. */
int in_off; /* Offset in buffer. */
int in_exists; /* Flag if the block exists. */
};
@@ -155,25 +145,25 @@ struct indir {
if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \
(ip)->i_flag |= IN_MODIFIED; \
if ((ip)->i_flag & IN_ACCESS) \
- (ip)->i_atime.tv_sec \
+ (ip)->i_atime \
= ((t1) == &time ? tv_sec : (t1)->tv_sec); \
if ((ip)->i_flag & IN_UPDATE) { \
- (ip)->i_mtime.tv_sec \
+ (ip)->i_mtime \
= ((t2) == &time ? tv_sec : (t2)->tv_sec); \
(ip)->i_modrev++; \
} \
if ((ip)->i_flag & IN_CHANGE) \
- (ip)->i_ctime.tv_sec = tv_sec; \
+ (ip)->i_ctime = tv_sec; \
(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \
} \
}
/* This overlays the fid structure (see mount.h). */
struct ufid {
- u_short ufid_len; /* Length of structure. */
- u_short ufid_pad; /* Force long alignment. */
- ino_t ufid_ino; /* File number (ino). */
- long ufid_gen; /* Generation number. */
+ u_int16_t ufid_len; /* Length of structure. */
+ u_int16_t ufid_pad; /* Force 32-bit alignment. */
+ ino_t ufid_ino; /* File number (ino). */
+ int32_t ufid_gen; /* Generation number. */
};
#endif /* KERNEL */
diff --git a/sys/gnu/fs/ext2fs/ext2_bmap.c b/sys/gnu/fs/ext2fs/ext2_bmap.c
index e17b5b7..aef2b83 100644
--- a/sys/gnu/fs/ext2fs/ext2_bmap.c
+++ b/sys/gnu/fs/ext2fs/ext2_bmap.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94
+ * @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
* $FreeBSD$
*/
@@ -63,9 +63,9 @@ int
ufs_bmap(ap)
struct vop_bmap_args /* {
struct vnode *a_vp;
- daddr_t a_bn;
+ ufs_daddr_t a_bn;
struct vnode **a_vpp;
- daddr_t *a_bnp;
+ ufs_daddr_t *a_bnp;
int *a_runp;
int *a_runb;
} */ *ap;
@@ -100,8 +100,8 @@ ufs_bmap(ap)
int
ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
struct vnode *vp;
- register daddr_t bn;
- daddr_t *bnp;
+ ufs_daddr_t bn;
+ ufs_daddr_t *bnp;
struct indir *ap;
int *nump;
int *runp;
@@ -113,7 +113,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
struct mount *mp;
struct vnode *devvp;
struct indir a[NIADDR+1], *xap;
- daddr_t daddr;
+ ufs_daddr_t daddr;
long metalbn;
int error, maxrun = 0, num;
@@ -209,12 +209,13 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
}
}
- daddr = ((daddr_t *)bp->b_data)[xap->in_off];
+ daddr = ((ufs_daddr_t *)bp->b_data)[xap->in_off];
if (num == 1 && daddr && runp) {
for (bn = xap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
- is_sequential(ump, ((daddr_t *)bp->b_data)[bn - 1],
- ((daddr_t *)bp->b_data)[bn]);
+ is_sequential(ump,
+ ((ufs_daddr_t *)bp->b_data)[bn - 1],
+ ((ufs_daddr_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = xap->in_off;
if (runb && bn) {
@@ -245,7 +246,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
int
ufs_getlbns(vp, bn, ap, nump)
struct vnode *vp;
- register daddr_t bn;
+ ufs_daddr_t bn;
struct indir *ap;
int *nump;
{
diff --git a/sys/gnu/fs/ext2fs/ext2_extern.h b/sys/gnu/fs/ext2fs/ext2_extern.h
index f07b7b7..de6cd08f 100644
--- a/sys/gnu/fs/ext2fs/ext2_extern.h
+++ b/sys/gnu/fs/ext2fs/ext2_extern.h
@@ -56,7 +56,7 @@ int ext2_blkatoff __P((struct vop_blkatoff_args *));
void ext2_blkfree __P((struct inode *, daddr_t, long));
daddr_t ext2_blkpref __P((struct inode *, daddr_t, int, daddr_t *, daddr_t));
int ext2_bmap __P((struct vop_bmap_args *));
-int ext2_init __P((void));
+int ext2_init __P((struct vfsconf *));
int ext2_reallocblks __P((struct vop_reallocblks_args *));
int ext2_reclaim __P((struct vop_reclaim_args *));
void ext2_setblock __P((struct ext2_sb_info *, u_char *, daddr_t));
diff --git a/sys/gnu/fs/ext2fs/ext2_inode.c b/sys/gnu/fs/ext2fs/ext2_inode.c
index d3b7038..788f5eb 100644
--- a/sys/gnu/fs/ext2fs/ext2_inode.c
+++ b/sys/gnu/fs/ext2fs/ext2_inode.c
@@ -77,9 +77,9 @@ static int ext2_indirtrunc __P((struct inode *, daddr_t, daddr_t, daddr_t, int,
long *));
int
-ext2_init()
+ext2_init(struct vfsconf *vfsp)
{
- return (ufs_init());
+ return (ufs_init(vfsp));
}
/*
@@ -118,16 +118,16 @@ ext2_update(ap)
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
return (0);
if (ip->i_flag & IN_ACCESS)
- ip->i_atime.tv_sec = ap->a_access->tv_sec;
+ ip->i_atime = ap->a_access->tv_sec;
if (ip->i_flag & IN_UPDATE) {
- ip->i_mtime.tv_sec = ap->a_modify->tv_sec;
+ ip->i_mtime = ap->a_modify->tv_sec;
ip->i_modrev++;
}
if (ip->i_flag & IN_CHANGE) {
#if !defined(__FreeBSD__)
get_time(&time);
#endif
- ip->i_ctime.tv_sec = time.tv_sec;
+ ip->i_ctime = time.tv_sec;
}
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
fs = ip->i_e2fs;
diff --git a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c b/sys/gnu/fs/ext2fs/ext2_inode_cnv.c
index fbc743b..a39e7b9 100644
--- a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c
+++ b/sys/gnu/fs/ext2fs/ext2_inode_cnv.c
@@ -66,17 +66,17 @@ ext2_print_dinode( di )
di->di_uid, di->di_gid, di->di_size);
printf( "Links: %3d Blockcount: %d\n",
di->di_nlink, di->di_blocks);
- printf( "ctime: 0x%x", di->di_ctime.tv_sec);
+ printf( "ctime: 0x%x", di->di_ctime);
#if !defined(__FreeBSD__)
- print_time(" -- %s\n", di->di_ctime.tv_sec);
+ print_time(" -- %s\n", di->di_ctime);
#endif
- printf( "atime: 0x%x", di->di_atime.tv_sec);
+ printf( "atime: 0x%x", di->di_atime);
#if !defined(__FreeBSD__)
- print_time(" -- %s\n", di->di_atime.tv_sec);
+ print_time(" -- %s\n", di->di_atime);
#endif
- printf( "mtime: 0x%x", di->di_mtime.tv_sec);
+ printf( "mtime: 0x%x", di->di_mtime);
#if !defined(__FreeBSD__)
- print_time(" -- %s\n", di->di_mtime.tv_sec);
+ print_time(" -- %s\n", di->di_mtime);
#endif
printf( "BLOCKS: ");
for(i=0; i < (di->di_blocks <= 24 ? ((di->di_blocks+1)/2): 12); i++)
@@ -110,9 +110,9 @@ ext2_ei2di(ei, di)
*/
di->di_mode = ei->i_links_count ? ei->i_mode : 0;
di->di_size = ei->i_size;
- di->di_atime.tv_sec = ei->i_atime;
- di->di_mtime.tv_sec = ei->i_mtime;
- di->di_ctime.tv_sec = ei->i_ctime;
+ di->di_atime = ei->i_atime;
+ di->di_mtime = ei->i_mtime;
+ di->di_ctime = ei->i_ctime;
di->di_flags = 0;
di->di_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0;
di->di_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0;
@@ -143,11 +143,11 @@ ext2_di2ei(di, ei)
Godmar thinks: if dtime is nonzero, ext2 says this inode
has been deleted, this would correspond to a zero link count
*/
- ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime.tv_sec;
+ ei->i_dtime = ei->i_links_count ? 0 : di->di_mtime;
ei->i_size = di->di_size;
- ei->i_atime = di->di_atime.tv_sec;
- ei->i_mtime = di->di_mtime.tv_sec;
- ei->i_ctime = di->di_ctime.tv_sec;
+ ei->i_atime = di->di_atime;
+ ei->i_mtime = di->di_mtime;
+ ei->i_ctime = di->di_ctime;
ei->i_flags = di->di_flags;
ei->i_flags = 0;
ei->i_flags |= (di->di_flags & APPEND) ? EXT2_APPEND_FL: 0;
diff --git a/sys/gnu/fs/ext2fs/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c
index baeaa52..eabd40e 100644
--- a/sys/gnu/fs/ext2fs/ext2_lookup.c
+++ b/sys/gnu/fs/ext2fs/ext2_lookup.c
@@ -274,6 +274,7 @@ ext2_lookup(ap)
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
+ struct proc *p = cnp->cn_proc;
int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize;
@@ -318,14 +319,14 @@ ext2_lookup(ap)
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, p);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
/*
* Check that the capability number did not change
@@ -336,9 +337,9 @@ ext2_lookup(ap)
return (0);
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
- if (error = VOP_LOCK(pdp))
+ if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
return (error);
vdp = pdp;
dp = VTOI(pdp);
@@ -548,7 +549,7 @@ searchloop:
*/
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (EJUSTRETURN);
}
/*
@@ -625,7 +626,7 @@ found:
}
*vpp = tdp;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (0);
}
@@ -650,7 +651,7 @@ found:
*vpp = tdp;
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (0);
}
@@ -675,13 +676,13 @@ found:
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp); /* race to get the inode */
+ VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) {
- VOP_LOCK(pdp);
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
if (lockparent && (flags & ISLASTCN) &&
- (error = VOP_LOCK(pdp))) {
+ (error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
vput(tdp);
return (error);
}
@@ -693,7 +694,7 @@ found:
if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp))
return (error);
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
*vpp = tdp;
}
diff --git a/sys/gnu/fs/ext2fs/ext2_mount.h b/sys/gnu/fs/ext2fs/ext2_mount.h
index d7b7b28..87041a6 100644
--- a/sys/gnu/fs/ext2fs/ext2_mount.h
+++ b/sys/gnu/fs/ext2fs/ext2_mount.h
@@ -30,13 +30,34 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufsmount.h 8.2 (Berkeley) 1/12/94
+ * @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
* $FreeBSD$
*/
#ifndef _UFS_UFS_UFSMOUNT_H_
#define _UFS_UFS_UFSMOUNT_H_
+/*
+ * Arguments to mount UFS-based filesystems
+ */
+struct ufs_args {
+ char *fspec; /* block special device to mount */
+ struct export_args export; /* network export information */
+};
+
+#ifdef MFS
+/*
+ * Arguments to mount MFS
+ */
+struct mfs_args {
+ char *fspec; /* name to export for statfs */
+ struct export_args export; /* if exported MFSes are supported */
+ caddr_t base; /* base of file system in memory */
+ u_long size; /* size of file system */
+};
+#endif /* MFS */
+
+#ifdef KERNEL
struct buf;
struct inode;
struct nameidata;
@@ -51,6 +72,7 @@ struct ufsmount {
struct mount *um_mountp; /* filesystem vfs structure */
dev_t um_dev; /* device mounted */
struct vnode *um_devvp; /* block device mounted vnode */
+
union { /* pointer to superblock */
struct lfs *lfs; /* LFS */
struct fs *fs; /* FFS */
@@ -60,6 +82,7 @@ struct ufsmount {
#define um_lfs ufsmount_u.lfs
#define um_e2fs ufsmount_u.e2fs
#define um_e2fsb ufsmount_u.e2fs->s_es
+
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
u_long um_nindir; /* indirect ptrs per block */
@@ -69,7 +92,9 @@ struct ufsmount {
time_t um_itime[MAXQUOTAS]; /* inode quota time limit */
char um_qflags[MAXQUOTAS]; /* quota specific flags */
struct netexport um_export; /* export information */
+ int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */
};
+
/*
* Flags describing the state of quotas.
*/
@@ -83,8 +108,9 @@ struct ufsmount {
* Macros to access file system parameters in the ufsmount structure.
* Used by ufs_bmap.
*/
-#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
-#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
-#define MNINDIR(ump) ((ump)->um_nindir)
+#define MNINDIR(ump) ((ump)->um_nindir)
+#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
+#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
+#endif /* KERNEL */
#endif
diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c
index d7c3e03..f01c059 100644
--- a/sys/gnu/fs/ext2fs/ext2_vfsops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c
@@ -221,10 +221,10 @@ ext2_mount(mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp))
+ if (vfs_busy(mp, LK_NOWAIT, 0, p))
return (EBUSY);
error = ext2_flushfiles(mp, flags, p);
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
if (!error && (mp->mnt_flag & MNT_RELOAD))
error = ext2_reload(mp, ndp->ni_cnd.cn_cred, p);
@@ -515,7 +515,7 @@ loop:
/*
* Step 5: invalidate all cached file data.
*/
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
if (vinvalbuf(vp, 0, cred, p, 0, 0))
panic("ext2_reload: dirty2");
@@ -727,17 +727,12 @@ ext2_flushfiles(mp, flags, p)
int flags;
struct proc *p;
{
-#if !defined(__FreeBSD__)
- extern int doforce;
-#endif
register struct ufsmount *ump;
int error;
#if QUOTA
int i;
#endif
- if (!doforce)
- flags &= ~FORCECLOSE;
ump = VFSTOUFS(mp);
#if QUOTA
if (mp->mnt_flag & MNT_QUOTA) {
@@ -872,7 +867,7 @@ loop:
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL)
continue;
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
if (error = VOP_FSYNC(vp, cred, waitfor, p))
allerror = error;
diff --git a/sys/gnu/fs/ext2fs/fs.h b/sys/gnu/fs/ext2fs/fs.h
index 28071d4..03f137c 100644
--- a/sys/gnu/fs/ext2fs/fs.h
+++ b/sys/gnu/fs/ext2fs/fs.h
@@ -152,6 +152,6 @@ extern u_char *fragtbl[];
* I think I'll try a VOP_LOCK/VOP_UNLOCK on the device vnode
*/
#define DEVVP(inode) (VFSTOUFS(ITOV(inode)->v_mount)->um_devvp)
-#define lock_super(devvp) VOP_LOCK(devvp)
-#define unlock_super(devvp) VOP_UNLOCK(devvp)
+#define lock_super(devvp) vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, curproc)
+#define unlock_super(devvp) VOP_UNLOCK(devvp, 0, curproc)
diff --git a/sys/gnu/fs/ext2fs/inode.h b/sys/gnu/fs/ext2fs/inode.h
index dc19d34..438471f 100644
--- a/sys/gnu/fs/ext2fs/inode.h
+++ b/sys/gnu/fs/ext2fs/inode.h
@@ -35,42 +35,33 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)inode.h 8.4 (Berkeley) 1/21/94
+ * @(#)inode.h 8.9 (Berkeley) 5/14/95
* $FreeBSD$
*/
#ifndef _UFS_UFS_INODE_H_
#define _UFS_UFS_INODE_H_
+#include <ufs/ufs/dir.h>
#include <ufs/ufs/dinode.h>
/*
- * Theoretically, directories can be more than 2Gb in length, however, in
- * practice this seems unlikely. So, we define the type doff_t as a long
- * to keep down the cost of doing lookup on a 32-bit machine. If you are
- * porting to a 64-bit architecture, you should make doff_t the same as off_t.
- */
-#define doff_t long
-
-/*
- * The inode is used to describe each active (or recently active)
- * file in the UFS filesystem. It is composed of two types of
- * information. The first part is the information that is needed
- * only while the file is active (such as the identity of the file
- * and linkage to speed its lookup). The second part is the
- * permanent meta-data associated with the file which is read
- * in from the permanent dinode from long term storage when the
- * file becomes active, and is put back when the file is no longer
- * being used.
+ * The inode is used to describe each active (or recently active) file in the
+ * UFS filesystem. It is composed of two types of information. The first part
+ * is the information that is needed only while the file is active (such as
+ * the identity of the file and linkage to speed its lookup). The second part
+ * is the permanent meta-data associated with the file which is read in
+ * from the permanent dinode from long term storage when the file becomes
+ * active, and is put back when the file is no longer being used.
*/
struct inode {
- struct inode *i_next; /* Hash chain forward. */
- struct inode **i_prev; /* Hash chain back. */
- struct vnode *i_vnode; /* Vnode associated with this inode. */
- struct vnode *i_devvp; /* Vnode for block I/O. */
- u_long i_flag; /* I* flags. */
- dev_t i_dev; /* Device associated with the inode. */
- ino_t i_number; /* The identity of the inode. */
+ LIST_ENTRY(inode) i_hash;/* Hash chain. */
+ struct vnode *i_vnode;/* Vnode associated with this inode. */
+ struct vnode *i_devvp;/* Vnode for block I/O. */
+ u_int32_t i_flag; /* flags, see below */
+ dev_t i_dev; /* Device associated with the inode. */
+ ino_t i_number; /* The identity of the inode. */
+
union { /* Associated filesystem. */
struct fs *fs; /* FFS */
struct lfs *lfs; /* LFS */
@@ -79,22 +70,21 @@ struct inode {
#define i_fs inode_u.fs
#define i_lfs inode_u.lfs
#define i_e2fs inode_u.e2fs
- struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
- u_quad_t i_modrev; /* Revision level for lease. */
- struct lockf *i_lockf; /* Head of byte-level lock list. */
- pid_t i_lockholder; /* DEBUG: holder of inode lock. */
- pid_t i_lockwaiter; /* DEBUG: latest blocked for inode lock. */
+ struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
+ u_quad_t i_modrev; /* Revision level for NFS lease. */
+ struct lockf *i_lockf;/* Head of byte-level lock list. */
+ struct lock i_lock; /* Inode lock. */
/*
* Side effects; used during directory lookup.
*/
- long i_count; /* Size of free slot in directory. */
- doff_t i_endoff; /* End of useful stuff in directory. */
- 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. */
- u_long i_reclen; /* Size of found directory entry. */
- int i_lockcount; /* Process lock count (recursion) */
- long i_spare[10]; /* Spares to round up to 128 bytes. */
+ int32_t i_count; /* Size of free slot in directory. */
+ doff_t i_endoff; /* End of useful stuff in directory. */
+ 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. */
+ u_int32_t i_reclen; /* Size of found directory entry. */
+ int i_lockcount; /* Process lock count (recursion) */
+ int i_spare[10]; /* XXX spare storage (for ext2fs) */
/*
* The on-disk dinode itself.
*/
@@ -102,8 +92,10 @@ struct inode {
};
#define i_atime i_din.di_atime
+#define i_atimensec i_din.di_atimensec
#define i_blocks i_din.di_blocks
#define i_ctime i_din.di_ctime
+#define i_ctimensec i_din.di_ctimensec
#define i_db i_din.di_db
#define i_flags i_din.di_flags
#define i_gen i_din.di_gen
@@ -111,6 +103,7 @@ struct inode {
#define i_ib i_din.di_ib
#define i_mode i_din.di_mode
#define i_mtime i_din.di_mtime
+#define i_mtimensec i_din.di_mtimensec
#define i_nlink i_din.di_nlink
#define i_rdev i_din.di_rdev
#define i_shortlink i_din.di_shortlink
@@ -120,15 +113,12 @@ struct inode {
/* These flags are kept in i_flag. */
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
-#define IN_EXLOCK 0x0004 /* File has exclusive lock. */
-#define IN_LOCKED 0x0008 /* Inode lock. */
-#define IN_LWAIT 0x0010 /* Process waiting on file lock. */
-#define IN_MODIFIED 0x0020 /* Inode has been modified. */
-#define IN_RENAME 0x0040 /* Inode is being renamed. */
-#define IN_SHLOCK 0x0080 /* File has shared lock. */
-#define IN_UPDATE 0x0100 /* Modification time update request. */
-#define IN_WANTED 0x0200 /* Inode is wanted by a process. */
-#define IN_RECURSE 0x0400 /* Recursion expected */
+#define IN_UPDATE 0x0004 /* Modification time update request. */
+#define IN_MODIFIED 0x0008 /* Inode has been modified. */
+#define IN_RENAME 0x0010 /* Inode is being renamed. */
+#define IN_SHLOCK 0x0020 /* File has shared lock. */
+#define IN_EXLOCK 0x0040 /* File has exclusive lock. */
+#define IN_RECURSE 0x0080 /* Recursion expected */
#ifdef KERNEL
/*
@@ -136,7 +126,7 @@ struct inode {
* ufs_getlbns and used by truncate and bmap code.
*/
struct indir {
- daddr_t in_lbn; /* Logical block number. */
+ ufs_daddr_t in_lbn; /* Logical block number. */
int in_off; /* Offset in buffer. */
int in_exists; /* Flag if the block exists. */
};
@@ -155,25 +145,25 @@ struct indir {
if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \
(ip)->i_flag |= IN_MODIFIED; \
if ((ip)->i_flag & IN_ACCESS) \
- (ip)->i_atime.tv_sec \
+ (ip)->i_atime \
= ((t1) == &time ? tv_sec : (t1)->tv_sec); \
if ((ip)->i_flag & IN_UPDATE) { \
- (ip)->i_mtime.tv_sec \
+ (ip)->i_mtime \
= ((t2) == &time ? tv_sec : (t2)->tv_sec); \
(ip)->i_modrev++; \
} \
if ((ip)->i_flag & IN_CHANGE) \
- (ip)->i_ctime.tv_sec = tv_sec; \
+ (ip)->i_ctime = tv_sec; \
(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \
} \
}
/* This overlays the fid structure (see mount.h). */
struct ufid {
- u_short ufid_len; /* Length of structure. */
- u_short ufid_pad; /* Force long alignment. */
- ino_t ufid_ino; /* File number (ino). */
- long ufid_gen; /* Generation number. */
+ u_int16_t ufid_len; /* Length of structure. */
+ u_int16_t ufid_pad; /* Force 32-bit alignment. */
+ ino_t ufid_ino; /* File number (ino). */
+ int32_t ufid_gen; /* Generation number. */
};
#endif /* KERNEL */
diff --git a/sys/i386/i386/autoconf.c b/sys/i386/i386/autoconf.c
index 866b420..6e305d0 100644
--- a/sys/i386/i386/autoconf.c
+++ b/sys/i386/i386/autoconf.c
@@ -53,6 +53,7 @@
#include <sys/reboot.h>
#include <sys/kernel.h>
#include <sys/mount.h>
+#include <sys/vnode.h>
#include <sys/sysctl.h>
#include <machine/bootinfo.h>
@@ -88,31 +89,15 @@
static void configure __P((void *));
SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
-#ifdef MFS_ROOT
-extern struct vfsops mfs_vfsops;
-#endif
-#ifdef FFS
-extern struct vfsops ufs_vfsops;
-#endif
-#ifdef LFS
-extern struct vfsops lfs_vfsops;
-#endif
-#ifdef NFS
-extern int nfs_mountroot __P((void *));
-#endif
-#ifdef CD9660
-extern int cd9660_mountroot __P((void *));
-#endif
-#ifdef MSDOSFS
-extern int msdosfs_mountroot __P((void *));
-#endif
-
static void configure_finish __P((void));
static void configure_start __P((void));
static int setdumpdev __P((dev_t dev));
static void setroot __P((void));
#ifdef CD9660
+
+#include <isofs/cd9660/iso.h>
+
/* We need to try out all our potential CDROM drives, so we need a table. */
static struct {
char *name;
@@ -138,7 +123,7 @@ find_cdrom_root(dummy)
rootdev = makedev(try_cdrom[k].major,j*8);
printf("trying rootdev=0x%lx (%s%d)\n",
rootdev, try_cdrom[k].name,j);
- i = (*cd9660_mountroot)((void *)NULL);
+ i = (*cd9660_mountroot)();
if (!i) return i;
}
return EINVAL;
@@ -176,6 +161,11 @@ configure(dummy)
enable_intr();
INTREN(IRQ_SLAVE);
+#if NCRD > 0
+ /* Before isa_configure to avoid ISA drivers finding our cards */
+ pccard_configure();
+#endif
+
#if NEISA > 0
eisa_configure();
#endif
@@ -188,11 +178,6 @@ configure(dummy)
isa_configure();
#endif
-#if NCRD > 0
- /* After everyone else has a chance at grabbing resources */
- pccard_configure();
-#endif
-
if (setdumpdev(dumpdev) != 0)
dumpdev = NODEV;
@@ -235,19 +220,26 @@ configure(dummy)
}
#ifdef CD9660
- if ((boothowto & RB_CDROM) && !mountroot) {
+ if ((boothowto & RB_CDROM)) {
if (bootverbose)
printf("Considering CD-ROM root f/s.\n");
- mountroot = find_cdrom_root;
+ mountrootfsname = "cd9660";
}
#endif
+#ifdef NFS
+ if (!mountrootfsname && nfs_diskless_valid) {
+ if (bootverbose)
+ printf("Considering NFS root f/s.\n");
+ mountrootfsname = "nfs";
+ }
+#endif /* NFS */
+
#ifdef MFS_ROOT
- if (!mountroot) {
+ if (!mountrootfsname) {
if (bootverbose)
printf("Considering MFS root f/s.\n");
- mountroot = vfs_mountroot; /* XXX goes away*/
- mountrootvfsops = &mfs_vfsops;
+ mountrootfsname = "mfs";
/*
* Ignore the -a flag if this kernel isn't compiled
* with a generic root/swap configuration: if we skip
@@ -260,21 +252,11 @@ configure(dummy)
setroot();
}
#endif
-
-#ifdef NFS
- if (!mountroot && nfs_diskless_valid) {
- if (bootverbose)
- printf("Considering NFS root f/s.\n");
- mountroot = nfs_mountroot;
- }
-#endif /* NFS */
-
#ifdef FFS
- if (!mountroot) {
+ if (!mountrootfsname) {
+ mountrootfsname = "ufs";
if (bootverbose)
printf("Considering FFS root f/s.\n");
- mountroot = vfs_mountroot; /* XXX goes away*/
- mountrootvfsops = &ufs_vfsops;
/*
* Ignore the -a flag if this kernel isn't compiled
* with a generic root/swap configuration: if we skip
@@ -288,11 +270,10 @@ configure(dummy)
}
#endif
#ifdef LFS
- if (!mountroot) {
+ if (!mountrootfsname) {
if (bootverbose)
printf("Considering LFS root f/s.\n");
- mountroot = vfs_mountroot; /* XXX goes away*/
- mountrootvfsops = &lfs_vfsops;
+ mountrootfsname = "lfs";
/*
* Ignore the -a flag if this kernel isn't compiled
* with a generic root/swap configuration: if we skip
@@ -305,8 +286,7 @@ configure(dummy)
setroot();
}
#endif
-
- if (!mountroot) {
+ if (!mountrootfsname) {
panic("Nobody wants to mount my root for me");
}
@@ -417,4 +397,4 @@ sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
}
SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
- 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
+ 0, sizeof dumpdev, sysctl_kern_dumpdev, "I", "");
diff --git a/sys/i386/i386/db_trace.c b/sys/i386/i386/db_trace.c
index 386e093..93078a8 100644
--- a/sys/i386/i386/db_trace.c
+++ b/sys/i386/i386/db_trace.c
@@ -34,7 +34,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_prot.h>
#include <vm/pmap.h>
#include <ddb/ddb.h>
diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c
index 9a2f646e..c993129 100644
--- a/sys/i386/i386/genassym.c
+++ b/sys/i386/i386/genassym.c
@@ -61,13 +61,15 @@
#include <sys/vmmeter.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/user.h>
#include <net/if.h>
#include <netinet/in.h>
#include <nfs/nfsv2.h>
+#include <nfs/rpcv2.h>
+#include <nfs/nfs.h>
#include <nfs/nfsdiskless.h>
extern int main __P((void));
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 6ebccff..b95b0ff 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -82,7 +82,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
diff --git a/sys/i386/i386/math_emulate.c b/sys/i386/i386/math_emulate.c
index 8bfa140..7a773a8 100644
--- a/sys/i386/i386/math_emulate.c
+++ b/sys/i386/i386/math_emulate.c
@@ -56,7 +56,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/user.h>
diff --git a/sys/i386/i386/mem.c b/sys/i386/i386/mem.c
index 28d8058..5275e7d 100644
--- a/sys/i386/i386/mem.c
+++ b/sys/i386/i386/mem.c
@@ -68,7 +68,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_prot.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 3c47ee4..0159c32 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -85,7 +85,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
diff --git a/sys/i386/i386/procfs_machdep.c b/sys/i386/i386/procfs_machdep.c
index 9e1dbff..78eb796 100644
--- a/sys/i386/i386/procfs_machdep.c
+++ b/sys/i386/i386/procfs_machdep.c
@@ -80,7 +80,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c
index d1b9807..8506cfc 100644
--- a/sys/i386/i386/sys_machdep.c
+++ b/sys/i386/i386/sys_machdep.c
@@ -44,7 +44,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index b38e35d..c866f32 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -61,7 +61,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index d320dac..f6c1606 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -58,7 +58,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c
index 693182f..7b7c172 100644
--- a/sys/i386/ibcs2/ibcs2_misc.c
+++ b/sys/i386/ibcs2/ibcs2_misc.c
@@ -354,7 +354,7 @@ ibcs2_getdents(p, uap, retval)
buflen = max(DIRBLKSIZ, SCARG(uap, nbytes) + blockoff);
buflen = min(buflen, MAXBSIZE);
buf = malloc(buflen, M_TEMP, M_WAITOK);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
again:
aiov.iov_base = buf;
aiov.iov_len = buflen;
@@ -420,7 +420,7 @@ again:
eof:
*retval = SCARG(uap, nbytes) - resid;
out:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
free(buf, M_TEMP);
return (error);
}
@@ -465,7 +465,7 @@ ibcs2_read(p, uap, retval)
buflen = max(DIRBLKSIZ, SCARG(uap, nbytes) + blockoff);
buflen = min(buflen, MAXBSIZE);
buf = malloc(buflen, M_TEMP, M_WAITOK);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
again:
aiov.iov_base = buf;
aiov.iov_len = buflen;
@@ -535,7 +535,7 @@ again:
eof:
*retval = SCARG(uap, nbytes) - resid;
out:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
free(buf, M_TEMP);
return (error);
}
diff --git a/sys/i386/ibcs2/imgact_coff.c b/sys/i386/ibcs2/imgact_coff.c
index d140406..bd1adc3 100644
--- a/sys/i386/ibcs2/imgact_coff.c
+++ b/sys/i386/ibcs2/imgact_coff.c
@@ -214,7 +214,7 @@ coff_load_file(struct proc *p, char *name)
* Lose the lock on the vnode. It's no longer needed, and must not
* exist for the pagefault paging to work below.
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
if (error = vm_mmap(kernel_map,
(vm_offset_t *) &ptr,
diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h
index b560351..01d8615 100644
--- a/sys/i386/include/param.h
+++ b/sys/i386/include/param.h
@@ -45,6 +45,7 @@
*/
#define MACHINE "i386"
+#define NCPUS 1
#define MID_MACHINE MID_I386
/*
@@ -125,4 +126,63 @@
#define i386_btop(x) ((unsigned)(x) >> PAGE_SHIFT)
#define i386_ptob(x) ((unsigned)(x) << PAGE_SHIFT)
+#ifndef _SIMPLELOCK_H_
+#define _SIMPLELOCK_H_
+/*
+ * A simple spin lock.
+ *
+ * This structure only sets one bit of data, but is sized based on the
+ * minimum word size that can be operated on by the hardware test-and-set
+ * instruction. It is only needed for multiprocessors, as uniprocessors
+ * will always run to completion or a sleep. It is an error to hold one
+ * of these locks while a process is sleeping.
+ */
+struct simplelock {
+ int lock_data;
+};
+
+#if !defined(SIMPLELOCK_DEBUG) && NCPUS > 1
+/*
+ * The simple-lock routines are the primitives out of which the lock
+ * package is built. The machine-dependent code must implement an
+ * atomic test_and_set operation that indivisibly sets the simple lock
+ * to non-zero and returns its old value. It also assumes that the
+ * setting of the lock to zero below is indivisible. Simple locks may
+ * only be used for exclusive locks.
+ */
+static __inline void
+simple_lock_init(lkp)
+ struct simplelock *lkp;
+{
+
+ lkp->lock_data = 0;
+}
+
+static __inline void
+simple_lock(lkp)
+ __volatile struct simplelock *lkp;
+{
+
+ while (test_and_set(&lkp->lock_data))
+ continue;
+}
+
+static __inline int
+simple_lock_try(lkp)
+ __volatile struct simplelock *lkp;
+{
+
+ return (!test_and_set(&lkp->lock_data))
+}
+
+static __inline void
+simple_unlock(lkp)
+ __volatile struct simplelock *lkp;
+{
+
+ lkp->lock_data = 0;
+}
+#endif /* NCPUS > 1 */
+#endif /* !_SIMPLELOCK_H_ */
+
#endif /* !_MACHINE_PARAM_H_ */
diff --git a/sys/i386/include/types.h b/sys/i386/include/types.h
index 040501f..3eee8a7 100644
--- a/sys/i386/include/types.h
+++ b/sys/i386/include/types.h
@@ -67,4 +67,6 @@ typedef unsigned long long u_int64_t;
typedef int32_t register_t;
+typedef int32_t ufs_daddr_t;
+
#endif /* !_MACHINE_TYPES_H_ */
diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c
index 9c095c9..c2d495d 100644
--- a/sys/i386/isa/fd.c
+++ b/sys/i386/isa/fd.c
@@ -277,7 +277,7 @@ static d_strategy_t fdstrategy;
static struct cdevsw fd_cdevsw;
static struct bdevsw fd_bdevsw =
{ Fdopen, fdclose, fdstrategy, fdioctl, /*2*/
- nodump, nopsize, 0, "fd", &fd_cdevsw, -1 };
+ nodump, nopsize, D_DISK, "fd", &fd_cdevsw, -1 };
static struct isa_device *fdcdevs[NFDC];
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 7ec5989..6e5823a 100644
--- a/sys/i386/isa/wd.c
+++ b/sys/i386/isa/wd.c
@@ -236,7 +236,7 @@ static d_psize_t wdsize;
static struct cdevsw wd_cdevsw;
static struct bdevsw wd_bdevsw =
{ wdopen, wdclose, wdstrategy, wdioctl, /*0*/
- wddump, wdsize, 0, "wd", &wd_cdevsw, -1 };
+ wddump, wdsize, D_DISK, "wd", &wd_cdevsw, -1 };
/*
* Probe for controller.
diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c
index 55c8a35..9fe4d40 100644
--- a/sys/i386/linux/linux_file.c
+++ b/sys/i386/linux/linux_file.c
@@ -450,7 +450,7 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
buflen = max(DIRBLKSIZ, nbytes + blockoff);
buflen = min(buflen, MAXBSIZE);
buf = malloc(buflen, M_TEMP, M_WAITOK);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
again:
aiov.iov_base = buf;
aiov.iov_len = buflen;
@@ -530,7 +530,7 @@ again:
eof:
*retval = nbytes - resid;
out:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
free(buf, M_TEMP);
return error;
}
diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c
index 536d797..d0332cf 100644
--- a/sys/i386/linux/linux_misc.c
+++ b/sys/i386/linux/linux_misc.c
@@ -237,7 +237,7 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
/*
* Lock no longer needed
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
locked = 0;
/*
@@ -392,7 +392,7 @@ cleanup:
* Unlock vnode if needed
*/
if (locked)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, p);
/*
* Release the kernel mapping.
diff --git a/sys/isa/fd.c b/sys/isa/fd.c
index 9c095c9..c2d495d 100644
--- a/sys/isa/fd.c
+++ b/sys/isa/fd.c
@@ -277,7 +277,7 @@ static d_strategy_t fdstrategy;
static struct cdevsw fd_cdevsw;
static struct bdevsw fd_bdevsw =
{ Fdopen, fdclose, fdstrategy, fdioctl, /*2*/
- nodump, nopsize, 0, "fd", &fd_cdevsw, -1 };
+ nodump, nopsize, D_DISK, "fd", &fd_cdevsw, -1 };
static struct isa_device *fdcdevs[NFDC];
diff --git a/sys/isofs/cd9660/TODO b/sys/isofs/cd9660/TODO
index eb24a23..71859c7 100644
--- a/sys/isofs/cd9660/TODO
+++ b/sys/isofs/cd9660/TODO
@@ -25,16 +25,6 @@
There is some preliminary stuff in there that (ab-)uses the mknod
system call, but this needs a writable filesystem
- 3) should be called cdfs, as there are other ISO file system soon possible
-
- Not yet. Probably we should make another file system when the ECMA draft
- is valid and do it. For doing Rock Ridge Support, I can use almost same
- code. So I just use the same file system interface...
-
- 4) should have file handles implemented for use with NFS, etc
-
- Yes. we have already this one, and I based it for this release.
-
5) should have name translation enabled by mount flag
Yes. we can disable the Rock Ridge Extension by follows option;
@@ -57,23 +47,3 @@
clean. As far as I know, if you export the cdrom by NFS, the client
can access the 8 bit clean (ie. Solaris Japanese with EUC code )
- 9) Access checks in isofs_access
-
- Not yet.
-
- 10) Support for generation numbers
-
- Yes. Default is to list only the last file (the one with the highest
- generation number). If you mount with -gen, all files are shown with
- their generation numbers. In both cases you can specify the generation
- number on opening files (if you happen to know it) or leave it off,
- when it will again find the last file.
-
- 11) Support for extended attributes
-
- Yes. Since this requires an extra block buffer for the attributes
- this must be enabled on mounting with the option -extattr.
-
-----------
-Last update July 19, '93 by Atsushi Murai. (amurai@spec.co.jp)
-Last update August 19, '93 by Wolfgang Solfrank. (ws@tools.de)
diff --git a/sys/isofs/cd9660/cd9660_bmap.c b/sys/isofs/cd9660/cd9660_bmap.c
index 6fffe7a..71dfb9e 100644
--- a/sys/isofs/cd9660/cd9660_bmap.c
+++ b/sys/isofs/cd9660/cd9660_bmap.c
@@ -67,7 +67,7 @@ cd9660_bmap(ap)
{
struct iso_node *ip = VTOI(ap->a_vp);
daddr_t lblkno = ap->a_bn;
- long bsize;
+ int bshift;
/*
* Check for underlying vnode requests and ensure that logical
@@ -81,8 +81,8 @@ cd9660_bmap(ap)
/*
* Compute the requested block number
*/
- bsize = ip->i_mnt->logical_block_size;
- *ap->a_bnp = (ip->iso_start + lblkno) * btodb(bsize);
+ bshift = ip->i_mnt->im_bshift;
+ *ap->a_bnp = (ip->iso_start + lblkno) << (bshift - DEV_BSHIFT);
/*
* Determine maximum number of readahead blocks following the
@@ -91,11 +91,11 @@ cd9660_bmap(ap)
if (ap->a_runp) {
int nblk;
- nblk = (ip->i_size - (lblkno + 1) * bsize) / bsize;
+ nblk = (ip->i_size >> bshift) - (lblkno + 1);
if (nblk <= 0)
*ap->a_runp = 0;
- else if (nblk >= MAXBSIZE/bsize)
- *ap->a_runp = MAXBSIZE/bsize - 1;
+ else if (nblk >= (MAXBSIZE >> bshift))
+ *ap->a_runp = (MAXBSIZE >> bshift) - 1;
else
*ap->a_runp = nblk;
}
diff --git a/sys/isofs/cd9660/cd9660_lookup.c b/sys/isofs/cd9660/cd9660_lookup.c
index 6e85a81..a7e38bb 100644
--- a/sys/isofs/cd9660/cd9660_lookup.c
+++ b/sys/isofs/cd9660/cd9660_lookup.c
@@ -108,8 +108,9 @@ cd9660_lookup(ap)
int saveoffset = 0; /* offset of last directory entry in dir */
int numdirpasses; /* strategy for directory search */
doff_t endsearch; /* offset to end directory search */
- struct iso_node *pdp; /* saved dp during symlink work */
- struct iso_node *tdp; /* returned by iget */
+ struct vnode *pdp; /* saved dp during symlink work */
+ struct vnode *tdp; /* returned by cd9660_vget_internal */
+ u_long bmask; /* block offset mask */
int lockparent; /* 1 => lockparent flag is set */
int wantparent; /* 1 => wantparent or lockparent flag */
int error;
@@ -126,6 +127,7 @@ cd9660_lookup(ap)
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
+ struct proc *p = cnp->cn_proc;
bp = NULL;
*vpp = NULL;
@@ -139,13 +141,13 @@ cd9660_lookup(ap)
* Check accessiblity of directory.
*/
if (vdp->v_type != VDIR)
- return (ENOTDIR);
- if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)))
+ return (ENOTDIR);
+ if (error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc))
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.
*
@@ -160,29 +162,29 @@ cd9660_lookup(ap)
return (error);
#ifdef PARANOID
if ((vdp->v_flag & VROOT) && (flags & ISDOTDOT))
- panic("ufs_lookup: .. through root");
+ panic("cd9660_lookup: .. through root");
#endif
/*
* Get the next vnode in the path.
* See comment below starting `Step through' for
* an explaination of the locking protocol.
*/
- pdp = dp;
+ pdp = vdp;
dp = VTOI(*vpp);
vdp = *vpp;
vpid = vdp->v_id;
- if (pdp == dp) {
+ if (pdp == vdp) {
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- ISO_IUNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, p);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- ISO_ILOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
/*
* Check that the capability number did not change
@@ -191,13 +193,14 @@ cd9660_lookup(ap)
if (!error) {
if (vpid == vdp->v_id)
return (0);
- iso_iput(dp);
- if (lockparent && pdp != dp && (flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
+ vput(vdp);
+ if (lockparent && pdp != vdp && (flags & ISLASTCN))
+ VOP_UNLOCK(pdp, 0, p);
}
- ISO_ILOCK(pdp);
- dp = pdp;
- vdp = ITOV(dp);
+ if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
+ return (error);
+ vdp = pdp;
+ dp = VTOI(pdp);
*vpp = NULL;
}
@@ -223,6 +226,7 @@ cd9660_lookup(ap)
* profiling time and hence has been removed in the interest
* of simplicity.
*/
+ bmask = imp->im_bmask;
if (nameiop != LOOKUP || dp->i_diroff == 0 ||
dp->i_diroff > dp->i_size) {
entryoffsetinblock = 0;
@@ -230,16 +234,14 @@ cd9660_lookup(ap)
numdirpasses = 1;
} else {
dp->i_offset = dp->i_diroff;
- entryoffsetinblock = iso_blkoff(imp, dp->i_offset);
- if (entryoffsetinblock != 0) {
- if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
+ if ((entryoffsetinblock = dp->i_offset & bmask) &&
+ (error = VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp)))
return (error);
- }
numdirpasses = 2;
iso_nchstats.ncs_2passes++;
}
- endsearch = roundup(dp->i_size, imp->logical_block_size);
-
+ endsearch = dp->i_size;
+
searchloop:
while (dp->i_offset < endsearch) {
/*
@@ -247,10 +249,11 @@ searchloop:
* read the next directory block.
* Release previous if it exists.
*/
- if (iso_blkoff(imp, dp->i_offset) == 0) {
+ if ((dp->i_offset & bmask) == 0) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(dp, dp->i_offset, &bp)))
+ if (error =
+ VOP_BLKATOFF(vdp, (off_t)dp->i_offset, NULL, &bp))
return (error);
entryoffsetinblock = 0;
}
@@ -258,13 +261,13 @@ searchloop:
* Get pointer to next entry.
*/
ep = (struct iso_directory_record *)
- (bp->b_un.b_addr + entryoffsetinblock);
-
- reclen = isonum_711 (ep->length);
+ ((char *)bp->b_data + entryoffsetinblock);
+
+ reclen = isonum_711(ep->length);
if (reclen == 0) {
/* skip to next block, if any */
dp->i_offset =
- roundup(dp->i_offset, imp->logical_block_size);
+ (dp->i_offset & ~bmask) + imp->logical_block_size;
continue;
}
@@ -275,10 +278,7 @@ searchloop:
if (entryoffsetinblock + reclen > imp->logical_block_size)
/* entries are not allowed to cross boundaries */
break;
-
- /*
- * Check for a name match.
- */
+
namelen = isonum_711(ep->name_len);
isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
&ep->date[6]: ep->flags);
@@ -286,7 +286,10 @@ searchloop:
if (reclen < ISO_DIRECTORY_RECORD_SIZE + namelen)
/* illegal entry, stop */
break;
-
+
+ /*
+ * Check for a name match.
+ */
switch (imp->iso_ftype) {
default:
if (!(isoflags & 4) == !assoc) {
@@ -297,10 +300,9 @@ searchloop:
&& ep->name[0] == ((flags & ISDOTDOT) ? 1 : 0)) {
/*
* Save directory entry's inode number and
- * reclen in ndp->ni_ufs area, and release
- * directory buffer.
+ * release directory buffer.
*/
- isodirino(&dp->i_ino,ep,imp);
+ dp->i_ino = isodirino(ep, imp);
goto found;
}
if (namelen != 1
@@ -308,8 +310,8 @@ searchloop:
goto notfound;
} else if (!(res = isofncmp(name,len,
ep->name,namelen))) {
- if (isoflags & 2)
- isodirino(&ino,ep,imp);
+ if (isonum_711(ep->flags)&2)
+ ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno)
+ entryoffsetinblock;
@@ -326,7 +328,7 @@ searchloop:
break;
case ISO_FTYPE_RRIP:
if (isonum_711(ep->flags)&2)
- isodirino(&ino,ep,imp);
+ ino = isodirino(ep, imp);
else
ino = dbtob(bp->b_blkno) + entryoffsetinblock;
dp->i_ino = ino;
@@ -344,15 +346,17 @@ searchloop:
foundino:
dp->i_ino = ino;
if (saveoffset != dp->i_offset) {
- if (iso_lblkno(imp,dp->i_offset)
- != iso_lblkno(imp,saveoffset)) {
+ if (lblkno(imp, dp->i_offset) !=
+ lblkno(imp, saveoffset)) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(dp, saveoffset, &bp)))
+ if (error = VOP_BLKATOFF(vdp,
+ (off_t)saveoffset, NULL, &bp))
return (error);
}
- ep = (struct iso_directory_record *)(bp->b_un.b_addr
- + iso_blkoff(imp,saveoffset));
+ entryoffsetinblock = saveoffset & bmask;
+ ep = (struct iso_directory_record *)
+ ((char *)bp->b_data + entryoffsetinblock);
dp->i_offset = saveoffset;
}
goto found;
@@ -370,6 +374,7 @@ notfound:
}
if (bp != NULL)
brelse(bp);
+
/*
* Insert name into cache (as non-existent) if appropriate.
*/
@@ -382,9 +387,7 @@ notfound:
found:
if (numdirpasses == 2)
iso_nchstats.ncs_pass2++;
- if (bp != NULL)
- brelse(bp);
-
+
/*
* Found component in pathname.
* If the final component of path name, save information
@@ -412,31 +415,39 @@ found:
* work if the file system has any hard links other than ".."
* that point backwards in the directory structure.
*/
- pdp = dp;
+ pdp = vdp;
/*
* If ino is different from dp->i_ino,
* it's a relocated directory.
*/
if (flags & ISDOTDOT) {
- ISO_IUNLOCK(pdp); /* race to get the inode */
- if ((error = iso_iget(dp,dp->i_ino,
- dp->i_ino != ino,
- &tdp,ep))) {
- ISO_ILOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p); /* 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) {
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
- if (lockparent && (flags & ISLASTCN))
- ISO_ILOCK(pdp);
- *vpp = ITOV(tdp);
+ if (lockparent && (flags & ISLASTCN) &&
+ (error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
+ vput(tdp);
+ return (error);
+ }
+ *vpp = tdp;
} else if (dp->i_number == dp->i_ino) {
+ brelse(bp);
VREF(vdp); /* we want ourself, ie "." */
*vpp = vdp;
} else {
- if ((error = iso_iget(dp,dp->i_ino,dp->i_ino!=ino,&tdp,ep)))
+ error = cd9660_vget_internal(vdp->v_mount, dp->i_ino, &tdp,
+ dp->i_ino != ino, ep);
+ brelse(bp);
+ if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
- ISO_IUNLOCK(pdp);
- *vpp = ITOV(tdp);
+ VOP_UNLOCK(pdp, 0, p);
+ *vpp = tdp;
}
/*
@@ -448,29 +459,37 @@ found:
}
/*
- * Return buffer with contents of block "offset"
- * from the beginning of directory "ip". If "res"
- * is non-zero, fill it in with a pointer to the
+ * Return buffer with the contents of block "offset" from the beginning of
+ * directory "ip". If "res" is non-zero, fill it in with a pointer to the
* remaining space in the directory.
*/
int
-iso_blkatoff(ip, offset, bpp)
- struct iso_node *ip;
- doff_t offset;
- struct buf **bpp;
+cd9660_blkatoff(ap)
+ struct vop_blkatoff_args /* {
+ struct vnode *a_vp;
+ off_t a_offset;
+ char **a_res;
+ struct buf **a_bpp;
+ } */ *ap;
{
- register struct iso_mnt *imp = ip->i_mnt;
- daddr_t lbn = iso_lblkno(imp,offset);
- int bsize = iso_blksize(imp,ip,lbn);
+ struct iso_node *ip;
+ register struct iso_mnt *imp;
struct buf *bp;
- int error;
+ daddr_t lbn;
+ int bsize, error;
- if ((error = bread(ITOV(ip),lbn,bsize,NOCRED,&bp))) {
+ ip = VTOI(ap->a_vp);
+ imp = ip->i_mnt;
+ lbn = lblkno(imp, ap->a_offset);
+ bsize = blksize(imp, ip, lbn);
+
+ if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
brelse(bp);
- *bpp = 0;
+ *ap->a_bpp = NULL;
return (error);
}
- *bpp = bp;
-
+ if (ap->a_res)
+ *ap->a_res = (char *)bp->b_data + blkoff(imp, ap->a_offset);
+ *ap->a_bpp = bp;
return (0);
}
diff --git a/sys/isofs/cd9660/cd9660_node.c b/sys/isofs/cd9660/cd9660_node.c
index c3f0911..c726696 100644
--- a/sys/isofs/cd9660/cd9660_node.c
+++ b/sys/isofs/cd9660/cd9660_node.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1982, 1986, 1989, 1994
+ * Copyright (c) 1982, 1986, 1989, 1994, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
@@ -52,32 +52,21 @@
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
#include <isofs/cd9660/iso_rrip.h>
-#define INOHSZ 512
-#if ((INOHSZ&(INOHSZ-1)) == 0)
-#define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1))
-#else
-#define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ)
-#endif
-
-union iso_ihead {
- union iso_ihead *ih_head[2];
- struct iso_node *ih_chain[2];
-} iso_ihead[INOHSZ];
-
-#ifdef ISODEVMAP
-#define DNOHSZ 64
-#if ((DNOHSZ&(DNOHSZ-1)) == 0)
-#define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1))
-#else
-#define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ)
-#endif
-
-union iso_dhead {
- union iso_dhead *dh_head[2];
- struct iso_dnode *dh_chain[2];
-} iso_dhead[DNOHSZ];
+/*
+ * Structures associated with iso_node caching.
+ */
+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;
+u_long idvhash;
+#define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
#endif
static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
@@ -86,73 +75,68 @@ static unsigned cd9660_chars2ui __P((unsigned char *begin, int len));
* Initialize hash links for inodes and dnodes.
*/
int
-cd9660_init()
+cd9660_init(vfsp)
+ struct vfsconf *vfsp;
{
- register int i;
- register union iso_ihead *ih = iso_ihead;
-#ifdef ISODEVMAP
- register union iso_dhead *dh = iso_dhead;
-#endif
- for (i = INOHSZ; --i >= 0; ih++) {
- ih->ih_head[0] = ih;
- ih->ih_head[1] = ih;
- }
-#ifdef ISODEVMAP
- for (i = DNOHSZ; --i >= 0; dh++) {
- dh->dh_head[0] = dh;
- dh->dh_head[1] = dh;
- }
+ isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash);
+ simple_lock_init(&cd9660_ihash_slock);
+#ifdef ISODEVMAP
+ idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash);
#endif
return (0);
}
-#ifdef ISODEVMAP
+#ifdef ISODEVMAP
/*
* Enter a new node into the device hash list
*/
struct iso_dnode *
-iso_dmap(dev,ino,create)
- dev_t dev;
- ino_t ino;
+iso_dmap(device, inum, create)
+ dev_t device;
+ ino_t inum;
int create;
{
- struct iso_dnode *dp;
- union iso_dhead *dh;
+ register struct iso_dnode **dpp, *dp, *dq;
- dh = &iso_dhead[DNOHASH(dev, ino)];
- for (dp = dh->dh_chain[0];
- dp != (struct iso_dnode *)dh;
- dp = dp->d_forw)
- if (ino == dp->i_number && dev == dp->i_dev)
- return dp;
+ dpp = &idvhashtbl[DNOHASH(device, inum)];
+ for (dp = *dpp;; dp = dp->d_next) {
+ if (dp == NULL)
+ return (NULL);
+ if (inum == dp->i_number && device == dp->i_dev)
+ return (dp);
if (!create)
- return (struct iso_dnode *)0;
+ return (NULL);
- MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK);
+ MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE,
+ M_WAITOK);
dp->i_dev = dev;
dp->i_number = ino;
- insque(dp,dh);
- return dp;
+ if (dq = *dpp)
+ dq->d_prev = dp->d_next;
+ dp->d_next = dq;
+ dp->d_prev = dpp;
+ *dpp = dp;
+
+ return (dp);
}
void
-iso_dunmap(dev)
- dev_t dev;
+iso_dunmap(device)
+ dev_t device;
{
- struct iso_dnode *dp, *dq;
- union iso_dhead *dh;
-
- for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) {
- for (dp = dh->dh_chain[0];
- dp != (struct iso_dnode *)dh;
- dp = dq) {
- dq = dp->d_forw;
- if (dev == dp->i_dev) {
- remque(dp);
- FREE(dp,M_CACHE);
+ struct iso_dnode **dpp, *dp, *dq;
+
+ for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) {
+ for (dp = *dpp; dp != NULL; dp = dq)
+ dq = dp->d_next;
+ if (device == dp->i_dev) {
+ if (dq)
+ dq->d_prev = dp->d_prev;
+ *dp->d_prev = dq;
+ FREE(dp, M_CACHE);
}
}
}
@@ -160,197 +144,74 @@ iso_dunmap(dev)
#endif
/*
- * Look up a ISOFS dinode number to find its incore vnode.
- * If it is not in core, read it in from the specified device.
- * If it is in core, wait for the lock bit to clear, then
- * return the inode locked. Detection and handling of mount
- * points must be done by the calling routine.
+ * Use the device/inum pair to find the incore inode, and return a pointer
+ * to it. If it is in core, but locked, wait for it.
*/
-int
-iso_iget(xp, ino, relocated, ipp, isodir)
- struct iso_node *xp;
- ino_t ino;
- int relocated;
- struct iso_node **ipp;
- struct iso_directory_record *isodir;
+struct vnode *
+cd9660_ihashget(dev, inum)
+ dev_t dev;
+ ino_t inum;
{
- dev_t dev = xp->i_dev;
- struct mount *mntp = ITOV(xp)->v_mount;
- register struct iso_node *ip, *iq;
- register struct vnode *vp;
-#ifdef ISODEVMAP
- register struct iso_dnode *dp;
-#endif
- struct vnode *nvp;
- struct buf *bp = NULL, *bp2 = NULL;
- union iso_ihead *ih;
- int error, result;
- struct iso_mnt *imp;
+ struct proc *p = curproc; /* XXX */
+ struct iso_node *ip;
+ struct vnode *vp;
- ih = &iso_ihead[INOHASH(dev, ino)];
loop:
- for (ip = ih->ih_chain[0];
- ip != (struct iso_node *)ih;
- ip = ip->i_forw) {
- if (ino != ip->i_number || dev != ip->i_dev)
- continue;
- if ((ip->i_flag&ILOCKED) != 0) {
- ip->i_flag |= IWANT;
- (void) tsleep((caddr_t)ip, PINOD, "isoigt", 0);
- goto loop;
- }
- if (vget(ITOV(ip), 1))
- goto loop;
- *ipp = ip;
- return 0;
- }
-
- /*
- * Do the MALLOC before the getnewvnode since doing so afterward
- * might cause a bogus v_data pointer to get dereferenced
- * elsewhere if MALLOC should block.
- */
- MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE, M_WAITOK);
-
- /*
- * Allocate a new vnode/iso_node.
- */
- if ((error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp))) {
- *ipp = NULL;
- FREE(ip, M_ISOFSNODE);
- return error;
- }
- bzero((caddr_t)ip, sizeof(struct iso_node));
- nvp->v_data = ip;
- ip->i_vnode = nvp;
- ip->i_flag = 0;
- ip->i_devvp = 0;
- ip->i_diroff = 0;
- ip->i_lockf = 0;
-
- /*
- * Put it onto its hash chain and lock it so that other requests for
- * this inode will block if they arrive while we are sleeping waiting
- * for old data structures to be purged or for the contents of the
- * disk portion of this inode to be read.
- */
- ip->i_dev = dev;
- ip->i_number = ino;
- insque(ip, ih);
- ISO_ILOCK(ip);
-
- imp = VFSTOISOFS (mntp);
- ip->i_mnt = imp;
- ip->i_devvp = imp->im_devvp;
- VREF(ip->i_devvp);
-
- if (relocated) {
- /*
- * On relocated directories we must
- * read the `.' entry out of a dir.
- */
- ip->iso_start = ino >> imp->im_bshift;
- if ((error = iso_blkatoff(ip,0,&bp))) {
- vrele(ip->i_devvp);
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
- iso_iput(ip);
- *ipp = 0;
- return error;
- }
- isodir = (struct iso_directory_record *)bp->b_un.b_addr;
- }
-
- ip->iso_extent = isonum_733(isodir->extent);
- ip->i_size = isonum_733(isodir->size);
- ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
-
- vp = ITOV(ip);
-
- /*
- * Setup time stamp, attribute
- */
- vp->v_type = VNON;
- switch (imp->iso_ftype) {
- default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */
- if ((imp->im_flags&ISOFSMNT_EXTATT)
- && isonum_711(isodir->ext_attr_length))
- iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length),
- &bp2);
- cd9660_defattr(isodir,ip,bp2,imp->iso_ftype );
- cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype );
- break;
- case ISO_FTYPE_RRIP:
- result = cd9660_rrip_analyze(isodir,ip,imp);
- break;
- }
- if (bp2)
- brelse(bp2);
- if (bp)
- brelse(bp);
-
- /*
- * Initialize the associated vnode
- */
- vp->v_type = IFTOVT(ip->inode.iso_mode);
-
- if ( vp->v_type == VFIFO ) {
- vp->v_op = cd9660_fifoop_p;
- } else if ( vp->v_type == VCHR || vp->v_type == VBLK ) {
- /*
- * if device, look at device number table for translation
- */
-#ifdef ISODEVMAP
- if (dp = iso_dmap(dev,ino,0))
- ip->inode.iso_rdev = dp->d_dev;
-#endif
- vp->v_op = cd9660_specop_p;
- if ((nvp = checkalias(vp, ip->inode.iso_rdev, mntp))) {
- /*
- * Reinitialize aliased inode.
- */
- vp = nvp;
- iq = VTOI(vp);
- iq->i_vnode = vp;
- iq->i_flag = 0;
- ISO_ILOCK(iq);
- iq->i_dev = dev;
- iq->i_number = ino;
- iq->i_mnt = ip->i_mnt;
- bcopy(&ip->iso_extent,&iq->iso_extent,
- (char *)(ip + 1) - (char *)&ip->iso_extent);
- insque(iq, ih);
- /*
- * Discard unneeded vnode
- * (This introduces the need of INACTIVE modification)
- */
- ip->inode.iso_mode = 0;
- iso_iput(ip);
- ip = iq;
+ 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, p))
+ goto loop;
+ return (vp);
}
}
+ simple_unlock(&cd9660_ihash_slock);
+ return (NULL);
+}
- if (ip->iso_extent == imp->root_extent)
- vp->v_flag |= VROOT;
-
+/*
+ * Insert the inode into the hash table, and return it locked.
+ */
+void
+cd9660_ihashins(ip)
+ struct iso_node *ip;
+{
+ struct proc *p = curproc; /* XXX */
+ struct iso_node **ipp, *iq;
+
+ simple_lock(&cd9660_ihash_slock);
+ ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
+ if (iq = *ipp)
+ iq->i_prev = &ip->i_next;
+ ip->i_next = iq;
+ ip->i_prev = ipp;
*ipp = ip;
- return 0;
+ simple_unlock(&cd9660_ihash_slock);
+
+ lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
}
/*
- * Unlock and decrement the reference count of an inode structure.
+ * Remove the inode from the hash table.
*/
-int
-iso_iput(ip)
+void
+cd9660_ihashrem(ip)
register struct iso_node *ip;
{
-
- if ((ip->i_flag & ILOCKED) == 0)
- panic("iso_iput");
- ISO_IUNLOCK(ip);
- vrele(ITOV(ip));
- return (0);
+ register struct iso_node *iq;
+
+ simple_lock(&cd9660_ihash_slock);
+ if (iq = ip->i_next)
+ iq->i_prev = ip->i_prev;
+ *ip->i_prev = iq;
+#ifdef DIAGNOSTIC
+ ip->i_next = NULL;
+ ip->i_prev = NULL;
+#endif
+ simple_unlock(&cd9660_ihash_slock);
}
/*
@@ -361,9 +222,11 @@ int
cd9660_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
register struct iso_node *ip = VTOI(vp);
int error = 0;
@@ -371,12 +234,13 @@ cd9660_inactive(ap)
vprint("cd9660_inactive: pushing active", vp);
ip->i_flag = 0;
+ VOP_UNLOCK(vp, 0, p);
/*
* 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;
}
@@ -387,6 +251,7 @@ int
cd9660_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
@@ -397,9 +262,7 @@ cd9660_reclaim(ap)
/*
* Remove the inode from its hash chain.
*/
- remque(ip);
- ip->i_forw = ip;
- ip->i_back = ip;
+ cd9660_ihashrem(ip);
/*
* Purge old data structures associated with the inode.
*/
@@ -410,46 +273,6 @@ cd9660_reclaim(ap)
}
FREE(vp->v_data, M_ISOFSNODE);
vp->v_data = NULL;
- return 0;
-}
-
-/*
- * Lock an inode. If its already locked, set the WANT bit and sleep.
- */
-int
-iso_ilock(ip)
- register struct iso_node *ip;
-{
-
- while (ip->i_flag & ILOCKED) {
- ip->i_flag |= IWANT;
- if (ip->i_spare0 == curproc->p_pid)
- panic("locking against myself");
- ip->i_spare1 = curproc->p_pid;
- (void) tsleep((caddr_t)ip, PINOD, "isoilk", 0);
- }
- ip->i_spare1 = 0;
- ip->i_spare0 = curproc->p_pid;
- ip->i_flag |= ILOCKED;
- return (0);
-}
-
-/*
- * Unlock an inode. If WANT bit is on, wakeup.
- */
-int
-iso_iunlock(ip)
- register struct iso_node *ip;
-{
-
- if ((ip->i_flag & ILOCKED) == 0)
- vprint("iso_iunlock: unlocked inode", ITOV(ip));
- ip->i_spare0 = 0;
- ip->i_flag &= ~ILOCKED;
- if (ip->i_flag&IWANT) {
- ip->i_flag &= ~IWANT;
- wakeup((caddr_t)ip);
- }
return (0);
}
@@ -457,7 +280,7 @@ iso_iunlock(ip)
* File attributes
*/
void
-cd9660_defattr(isodir,inop,bp,ftype)
+cd9660_defattr(isodir, inop, bp, ftype)
struct iso_directory_record *isodir;
struct iso_node *inop;
struct buf *bp;
@@ -482,14 +305,15 @@ cd9660_defattr(isodir,inop,bp,ftype)
inop->inode.iso_links = 1;
}
if (!bp
- && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
- iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
bp = bp2;
}
if (bp) {
- ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
-
+ ap = (struct iso_extended_attributes *)bp->b_data;
+
if (isonum_711(ap->version) == 1) {
if (!(ap->perm[0]&0x40))
inop->inode.iso_mode |= VEXEC >> 6;
@@ -533,16 +357,16 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
int off;
if (!bp
- && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT)
+ && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
&& (off = isonum_711(isodir->ext_attr_length))) {
- iso_blkatoff(inop,-off * imp->logical_block_size,&bp2);
+ VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
bp = bp2;
}
if (bp) {
- ap = (struct iso_extended_attributes *)bp->b_un.b_addr;
-
- if (ftype != ISO_FTYPE_HIGH_SIERRA
- && isonum_711(ap->version) == 1) {
+ ap = (struct iso_extended_attributes *)bp->b_data;
+
+ if (isonum_711(ap->version) == 1) {
if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
@@ -563,9 +387,9 @@ cd9660_deftstamp(isodir,inop,bp,ftype)
int
cd9660_tstamp_conv7(pi,pu,ftype)
-char *pi;
-struct timespec *pu;
-enum ISO_FTYPE ftype;
+ u_char *pi;
+ struct timespec *pu;
+ enum ISO_FTYPE ftype;
{
int crtime, days;
int y, m, d, hour, minute, second, tz;
@@ -609,13 +433,13 @@ enum ISO_FTYPE ftype;
return 1;
}
-static unsigned
+static u_int
cd9660_chars2ui(begin,len)
- unsigned char *begin;
+ u_char *begin;
int len;
{
- unsigned rc;
-
+ u_int rc;
+
for (rc = 0; --len >= 0;) {
rc *= 10;
rc += *begin++ - '0';
@@ -625,12 +449,12 @@ cd9660_chars2ui(begin,len)
int
cd9660_tstamp_conv17(pi,pu)
- unsigned char *pi;
+ u_char *pi;
struct timespec *pu;
{
- unsigned char buf[7];
-
- /* year:"0001"-"9999" -> -1900 */
+ u_char buf[7];
+
+ /* year:"0001"-"9999" -> -1900 */
buf[0] = cd9660_chars2ui(pi,4) - 1900;
/* month: " 1"-"12" -> 1 - 12 */
@@ -654,12 +478,14 @@ cd9660_tstamp_conv17(pi,pu)
return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT);
}
-void
-isodirino(inump,isodir,imp)
- ino_t *inump;
+ino_t
+isodirino(isodir, imp)
struct iso_directory_record *isodir;
struct iso_mnt *imp;
{
- *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
- * imp->logical_block_size;
+ ino_t ino;
+
+ ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
+ << imp->im_bshift;
+ return (ino);
}
diff --git a/sys/isofs/cd9660/cd9660_node.h b/sys/isofs/cd9660/cd9660_node.h
index 992f9cb..de538fb 100644
--- a/sys/isofs/cd9660/cd9660_node.h
+++ b/sys/isofs/cd9660/cd9660_node.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_node.h 8.2 (Berkeley) 1/23/94
+ * @(#)cd9660_node.h 8.6 (Berkeley) 5/14/95
* $FreeBSD$
*/
@@ -59,22 +59,20 @@ typedef struct {
dev_t iso_rdev; /* Major/Minor number for special */
} ISO_RRIP_INODE;
-#ifdef ISODEVMAP
+#ifdef ISODEVMAP
/*
* FOr device# (major,minor) translation table
*/
struct iso_dnode {
- struct iso_dnode *d_chain[2]; /* hash chain, MUST be first */
+ struct iso_dnode *d_next, **d_prev; /* hash chain */
dev_t i_dev; /* device where dnode resides */
ino_t i_number; /* the identity of the inode */
dev_t d_dev; /* device # for translation */
};
-#define d_forw d_chain[0]
-#define d_back d_chain[1]
#endif
struct iso_node {
- struct iso_node *i_chain[2]; /* hash chain, MUST be first */
+ struct iso_node *i_next, **i_prev; /* hash chain */
struct vnode *i_vnode; /* vnode associated with this inode */
struct vnode *i_devvp; /* vnode for block I/O */
u_long i_flag; /* see below */
@@ -87,8 +85,7 @@ struct iso_node {
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 */
- long i_spare0;
- long i_spare1;
+ struct lock i_lock; /* node lock */
long iso_extent; /* extent of file */
long i_size;
@@ -101,19 +98,11 @@ struct iso_node {
#define i_back i_chain[1]
/* flags */
-#define ILOCKED 0x0001 /* inode is locked */
-#define IWANT 0x0002 /* some process waiting on lock */
-#define IACC 0x0020 /* inode access time to be updated */
+#define IN_ACCESS 0x0020 /* inode access time to be updated */
#define VTOI(vp) ((struct iso_node *)(vp)->v_data)
#define ITOV(ip) ((ip)->i_vnode)
-#define ISO_ILOCK(ip) iso_ilock(ip)
-#define ISO_IUNLOCK(ip) iso_iunlock(ip)
-
-extern vop_t **cd9660_fifoop_p;
-extern vop_t **cd9660_specop_p;
-
/*
* Prototypes for ISOFS vnode operations
*/
@@ -121,14 +110,19 @@ int cd9660_lookup __P((struct vop_lookup_args *));
int cd9660_inactive __P((struct vop_inactive_args *));
int cd9660_reclaim __P((struct vop_reclaim_args *));
int cd9660_bmap __P((struct vop_bmap_args *));
+int cd9660_pathconf __P((struct vop_pathconf_args *));
+int cd9660_blkatoff __P((struct vop_blkatoff_args *));
+#define cd9660_revoke vop_revoke
+
void cd9660_defattr __P((struct iso_directory_record *,
struct iso_node *, struct buf *, enum ISO_FTYPE));
void cd9660_deftstamp __P((struct iso_directory_record *,
struct iso_node *, struct buf *, enum ISO_FTYPE));
-int cd9660_tstamp_conv7 __P((char *pi, struct timespec *pu, enum ISO_FTYPE));
-int cd9660_tstamp_conv17 __P((unsigned char *pi, struct timespec *pu));
-void isodirino __P((ino_t *inump, struct iso_directory_record *isodir,
- struct iso_mnt *imp));
+struct vnode *cd9660_ihashget __P((dev_t, ino_t));
+void cd9660_ihashins __P((struct iso_node *));
+void cd9660_ihashrem __P((struct iso_node *));
+int cd9660_tstamp_conv7 __P((u_char *, struct timespec *, enum ISO_FTYPE));
+int cd9660_tstamp_conv17 __P((u_char *, struct timespec *));
#ifdef ISODEVMAP
struct iso_dnode *iso_dmap __P((dev_t, ino_t, int));
void iso_dunmap __P((dev_t));
diff --git a/sys/isofs/cd9660/cd9660_rrip.c b/sys/isofs/cd9660/cd9660_rrip.c
index 44d52eb..521094f 100644
--- a/sys/isofs/cd9660/cd9660_rrip.c
+++ b/sys/isofs/cd9660/cd9660_rrip.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_rrip.c 8.2 (Berkeley) 1/23/94
+ * @(#)cd9660_rrip.c 8.6 (Berkeley) 12/5/94
* $FreeBSD$
*/
@@ -104,10 +104,10 @@ cd9660_rrip_attr(p,ana)
ISO_RRIP_ATTR *p;
ISO_RRIP_ANALYZE *ana;
{
- ana->inop->inode.iso_mode = isonum_731(p->mode_l);
- ana->inop->inode.iso_uid = (uid_t)isonum_731(p->uid_l);
- ana->inop->inode.iso_gid = (gid_t)isonum_731(p->gid_l);
- ana->inop->inode.iso_links = isonum_731(p->links_l);
+ ana->inop->inode.iso_mode = isonum_733(p->mode);
+ ana->inop->inode.iso_uid = isonum_733(p->uid);
+ ana->inop->inode.iso_gid = isonum_733(p->gid);
+ ana->inop->inode.iso_links = isonum_733(p->links);
ana->fields &= ~ISO_SUSP_ATTR;
return ISO_SUSP_ATTR;
}
@@ -352,8 +352,8 @@ cd9660_rrip_tstamp(p,ana)
ISO_RRIP_TSTAMP *p;
ISO_RRIP_ANALYZE *ana;
{
- unsigned char *ptime;
-
+ u_char *ptime;
+
ptime = p->time;
/* Check a format of time stamp (7bytes/17bytes) */
@@ -367,7 +367,7 @@ cd9660_rrip_tstamp(p,ana)
ptime += 7;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
-
+
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv7(ptime,&ana->inop->inode.iso_atime,
ISO_FTYPE_RRIP);
@@ -390,7 +390,7 @@ cd9660_rrip_tstamp(p,ana)
ptime += 17;
} else
bzero(&ana->inop->inode.iso_mtime,sizeof(struct timespec));
-
+
if (*p->flags&ISO_SUSP_TSTAMP_ACCESS) {
cd9660_tstamp_conv17(ptime,&ana->inop->inode.iso_atime);
ptime += 17;
@@ -423,16 +423,15 @@ cd9660_rrip_device(p,ana)
ISO_RRIP_DEVICE *p;
ISO_RRIP_ANALYZE *ana;
{
- unsigned high, low;
-
- high = isonum_733(p->dev_t_high_l);
- low = isonum_733(p->dev_t_low_l);
-
- if ( high == 0 ) {
- ana->inop->inode.iso_rdev = makedev( major(low), minor(low) );
- } else {
- ana->inop->inode.iso_rdev = makedev( high, minor(low) );
- }
+ u_int high, low;
+
+ high = isonum_733(p->dev_t_high);
+ low = isonum_733(p->dev_t_low);
+
+ if (high == 0)
+ ana->inop->inode.iso_rdev = makedev(major(low), minor(low));
+ else
+ ana->inop->inode.iso_rdev = makedev(high, minor(low));
ana->fields &= ~ISO_SUSP_DEVICE;
return ISO_SUSP_DEVICE;
}
@@ -475,8 +474,6 @@ cd9660_rrip_stop(p,ana)
ISO_SUSP_HEADER *p;
ISO_RRIP_ANALYZE *ana;
{
- /* stop analyzing */
- ana->fields = 0;
return ISO_SUSP_STOP;
}
@@ -545,22 +542,30 @@ cd9660_rrip_loop(isodir,ana,table)
if (!ana->fields)
break;
}
+ if (result&ISO_SUSP_STOP) {
+ result &= ~ISO_SUSP_STOP;
+ break;
+ }
+ /* plausibility check */
+ if (isonum_711(phead->length) < sizeof(*phead))
+ break;
/*
* move to next SUSP
* Hopefully this works with newer versions, too
*/
phead = (ISO_SUSP_HEADER *)((char *)phead + isonum_711(phead->length));
}
-
- if ( ana->fields && ana->iso_ce_len ) {
+
+ if (ana->fields && ana->iso_ce_len) {
if (ana->iso_ce_blk >= ana->imp->volume_space_size
|| ana->iso_ce_off + ana->iso_ce_len > ana->imp->logical_block_size
|| bread(ana->imp->im_devvp,
- iso_lblktodaddr(ana->imp, ana->iso_ce_blk),
- ana->imp->logical_block_size,NOCRED,&bp))
+ ana->iso_ce_blk <<
+ (ana->imp->im_bshift - DEV_BSHIFT),
+ ana->imp->logical_block_size, NOCRED, &bp))
/* what to do now? */
break;
- phead = (ISO_SUSP_HEADER *)(bp->b_un.b_addr + ana->iso_ce_off);
+ phead = (ISO_SUSP_HEADER *)(bp->b_data + ana->iso_ce_off);
pend = (ISO_SUSP_HEADER *) ((char *)phead + ana->iso_ce_len);
} else
break;
@@ -569,7 +574,7 @@ cd9660_rrip_loop(isodir,ana,table)
brelse(bp);
/*
* If we don't find the Basic SUSP stuffs, just set default value
- * ( attribute/time stamp )
+ * (attribute/time stamp)
*/
for (ptable = table; ptable->func2; ptable++)
if (!(ptable->result&result))
@@ -579,6 +584,9 @@ cd9660_rrip_loop(isodir,ana,table)
}
/*
+ * Get Attributes.
+ */
+/*
* XXX the casts are bogus but will do for now.
*/
#define BC (rrt_func_t *)
@@ -607,10 +615,8 @@ cd9660_rrip_analyze(isodir,inop,imp)
return cd9660_rrip_loop(isodir,&analyze,rrip_table_analyze);
}
-/*
- * Get Alternate Name from 'AL' record
- * If either no AL record or 0 length,
- * it will be return the translated ISO9660 name,
+/*
+ * Get Alternate Name.
*/
static RRIP_TABLE rrip_table_getname[] = {
{ "NM", BC cd9660_rrip_altname, cd9660_rrip_defname, ISO_SUSP_ALTNAME },
@@ -654,10 +660,8 @@ cd9660_rrip_getname(isodir,outbuf,outlen,inump,imp)
return cd9660_rrip_loop(isodir,&analyze,tab);
}
-/*
- * Get Symbolic Name from 'SL' record
- *
- * Note: isodir should contains SL record!
+/*
+ * Get Symbolic Link.
*/
static RRIP_TABLE rrip_table_getsymname[] = {
{ "SL", BC cd9660_rrip_slink, 0, ISO_SUSP_SLINK },
@@ -696,7 +700,7 @@ static RRIP_TABLE rrip_table_extref[] = {
/*
* Check for Rock Ridge Extension and return offset of its fields.
- * Note: We require the ER field.
+ * Note: We insist on the ER field.
*/
int
cd9660_rrip_offset(isodir,imp)
diff --git a/sys/isofs/cd9660/cd9660_rrip.h b/sys/isofs/cd9660/cd9660_rrip.h
index e65fb3b..cacee39 100644
--- a/sys/isofs/cd9660/cd9660_rrip.h
+++ b/sys/isofs/cd9660/cd9660_rrip.h
@@ -35,36 +35,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_rrip.h 8.1 (Berkeley) 1/21/94
- * $FreeBSD$
+ * @(#)cd9660_rrip.h 8.2 (Berkeley) 12/5/94
+ * $Id: cd9660_rrip.h,v 1.3.2000.1 1996/09/30 12:46:48 dfr Exp $
*/
-
+
typedef struct {
- char type [ISODCL ( 0, 1)];
- unsigned char length [ISODCL ( 2, 2)]; /* 711 */
- unsigned char version [ISODCL ( 3, 3)];
+ char type [ISODCL ( 0, 1)];
+ u_char length [ISODCL ( 2, 2)]; /* 711 */
+ u_char version [ISODCL ( 3, 3)];
} ISO_SUSP_HEADER;
-
+
typedef struct {
ISO_SUSP_HEADER h;
- char mode_l [ISODCL ( 4, 7)]; /* 731 */
- char mode_m [ISODCL ( 8, 11)]; /* 732 */
- char links_l [ISODCL ( 12, 15)]; /* 731 */
- char links_m [ISODCL ( 16, 19)]; /* 732 */
- char uid_l [ISODCL ( 20, 23)]; /* 731 */
- char uid_m [ISODCL ( 24, 27)]; /* 732 */
- char gid_l [ISODCL ( 28, 31)]; /* 731 */
- char gid_m [ISODCL ( 32, 35)]; /* 732 */
+ char mode [ISODCL ( 4, 11)]; /* 733 */
+ char links [ISODCL ( 12, 19)]; /* 733 */
+ char uid [ISODCL ( 20, 27)]; /* 733 */
+ char gid [ISODCL ( 28, 35)]; /* 733 */
} ISO_RRIP_ATTR;
-
+
typedef struct {
ISO_SUSP_HEADER h;
- char dev_t_high_l [ISODCL ( 4, 7)]; /* 731 */
- char dev_t_high_m [ISODCL ( 8, 11)]; /* 732 */
- char dev_t_low_l [ISODCL ( 12, 15)]; /* 731 */
- char dev_t_low_m [ISODCL ( 16, 19)]; /* 732 */
+ char dev_t_high [ISODCL ( 4, 11)]; /* 733 */
+ char dev_t_low [ISODCL ( 12, 19)]; /* 733 */
} ISO_RRIP_DEVICE;
-
+
#define ISO_SUSP_CFLAG_CONTINUE 0x01
#define ISO_SUSP_CFLAG_CURRENT 0x02
#define ISO_SUSP_CFLAG_PARENT 0x04
@@ -73,9 +67,9 @@ typedef struct {
#define ISO_SUSP_CFLAG_HOST 0x20
typedef struct {
- u_char cflag [ISODCL ( 1, 1)];
- u_char clen [ISODCL ( 2, 2)];
- u_char name [0];
+ u_char cflag [ISODCL ( 1, 1)];
+ u_char clen [ISODCL ( 2, 2)];
+ u_char name [1]; /* XXX */
} ISO_RRIP_SLINK_COMPONENT;
#define ISO_RRIP_SLSIZ 2
@@ -116,13 +110,13 @@ typedef struct {
typedef struct {
ISO_SUSP_HEADER h;
- unsigned char flags [ISODCL ( 4, 4)];
- unsigned char time [ISODCL ( 5, 5)];
+ u_char flags [ISODCL ( 4, 4)];
+ u_char time [ISODCL ( 5, 5)];
} ISO_RRIP_TSTAMP;
typedef struct {
ISO_SUSP_HEADER h;
- unsigned char flags [ISODCL ( 4, 4)];
+ u_char flags [ISODCL ( 4, 4)];
} ISO_RRIP_IDFLAG;
typedef struct {
diff --git a/sys/isofs/cd9660/cd9660_util.c b/sys/isofs/cd9660/cd9660_util.c
index 786d4fd..151d1c3 100644
--- a/sys/isofs/cd9660/cd9660_util.c
+++ b/sys/isofs/cd9660/cd9660_util.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_util.c 8.1 (Berkeley) 1/21/94
+ * @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94
* $FreeBSD$
*/
@@ -58,104 +58,14 @@
#include <isofs/cd9660/iso.h>
-#ifdef __notanymore__
-int
-isonum_711 (p)
-unsigned char *p;
-{
- return (*p);
-}
-
-int
-isonum_712 (p)
-signed char *p;
-{
- return (*p);
-}
-
-int
-isonum_721 (p)
-unsigned char *p;
-{
- /* little endian short */
-#if BYTE_ORDER != LITTLE_ENDIAN
- printf ("isonum_721 called on non little-endian machine!\n");
-#endif
-
- return *(short *)p;
-}
-
-int
-isonum_722 (p)
-unsigned char *p;
-{
- /* big endian short */
-#if BYTE_ORDER != BIG_ENDIAN
- printf ("isonum_722 called on non big-endian machine!\n");
-#endif
-
- return *(short *)p;
-}
-
-int
-isonum_723 (p)
-unsigned char *p;
-{
-#if BYTE_ORDER == BIG_ENDIAN
- return isonum_722 (p + 2);
-#elif BYTE_ORDER == LITTLE_ENDIAN
- return isonum_721 (p);
-#else
- printf ("isonum_723 unsupported byte order!\n");
- return 0;
-#endif
-}
-
-int
-isonum_731 (p)
-unsigned char *p;
-{
- /* little endian long */
-#if BYTE_ORDER != LITTLE_ENDIAN
- printf ("isonum_731 called on non little-endian machine!\n");
-#endif
-
- return *(long *)p;
-}
-
-int
-isonum_732 (p)
-unsigned char *p;
-{
- /* big endian long */
-#if BYTE_ORDER != BIG_ENDIAN
- printf ("isonum_732 called on non big-endian machine!\n");
-#endif
-
- return *(long *)p;
-}
-
-int
-isonum_733 (p)
-unsigned char *p;
-{
-#if BYTE_ORDER == BIG_ENDIAN
- return isonum_732 (p + 4);
-#elif BYTE_ORDER == LITTLE_ENDIAN
- return isonum_731 (p);
-#else
- printf ("isonum_733 unsupported byte order!\n");
- return 0;
-#endif
-}
-#endif /* __notanymore__ */
-
/*
* translate and compare a filename
* Note: Version number plus ';' may be omitted.
*/
int
-isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
+isofncmp(fn, fnlen, isofn, isolen)
+ u_char *fn, *isofn;
+ int fnlen, isolen;
{
int i, j;
unsigned char c;
@@ -211,9 +121,12 @@ isofncmp(unsigned char *fn,int fnlen,unsigned char *isofn,int isolen)
* translate a filename
*/
void
-isofntrans(unsigned char *infn,int infnlen,
- unsigned char *outfn,unsigned short *outfnlen,
- int original,int assoc)
+isofntrans(infn, infnlen, outfn, outfnlen, original, assoc)
+ u_char *infn, *outfn;
+ int infnlen;
+ u_short *outfnlen;
+ int original;
+ int assoc;
{
int fnidx = 0;
diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c
index 752a7b4..15eade4 100644
--- a/sys/isofs/cd9660/cd9660_vfsops.c
+++ b/sys/isofs/cd9660/cd9660_vfsops.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_vfsops.c 8.3 (Berkeley) 1/31/94
+ * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $FreeBSD$
*/
@@ -52,10 +52,12 @@
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/malloc.h>
+#include <sys/stat.h>
#include <isofs/cd9660/iso.h>
-#include <isofs/cd9660/cd9660_node.h>
#include <isofs/cd9660/iso_rrip.h>
+#include <isofs/cd9660/cd9660_node.h>
+#include <isofs/cd9660/cd9660_mount.h>
static int cd9660_mount __P((struct mount *,
@@ -84,17 +86,14 @@ static struct vfsops cd9660_vfsops = {
cd9660_vget,
cd9660_fhtovp,
cd9660_vptofh,
- cd9660_init,
+ cd9660_init
};
VFS_SET(cd9660_vfsops, cd9660, MOUNT_CD9660, VFCF_READONLY);
/*
* Called by vfs_mountroot when iso is going to be mounted as root.
- *
- * Name is updated by mount(8) after booting.
*/
-#define ROOTNAME "root_device"
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
struct proc *p, struct iso_args *argp));
@@ -102,55 +101,38 @@ static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
int
cd9660_mountroot()
{
- register struct mount *mp;
+ struct mount *mp;
struct proc *p = curproc; /* XXX */
- struct iso_mnt *imp;
- u_int size;
- int error;
struct iso_args args;
-
+ int error;
+
/*
* Get vnode for rootdev.
*/
- if (bdevvp(rootdev, &rootvp))
- panic("cd9660_mountroot: can't setup bdevvp for rootdev");
-
- 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;
- args.flags = ISOFSMNT_ROOT;
- if ((error = iso_mountfs(rootvp, mp, p, &args))) {
- free(mp, M_MOUNT);
+ if ((error = bdevvp(swapdev, &swapdev_vp)) ||
+ (error = bdevvp(rootdev, &rootvp))) {
+ printf("cd9660_mountroot: can't setup bdevvp's");
return (error);
}
- if ((error = vfs_lock(mp))) {
- (void)cd9660_unmount(mp, 0, p);
+
+ if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
+ return (error);
+ args.flags = ISOFSMNT_ROOT;
+ if (error = iso_mountfs(rootvp, mp, p, &args)) {
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
free(mp, M_MOUNT);
return (error);
}
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
- mp->mnt_flag |= MNT_ROOTFS;
- mp->mnt_vnodecovered = NULLVP;
- imp = VFSTOISOFS(mp);
- bzero(imp->im_fsmnt, sizeof(imp->im_fsmnt));
- imp->im_fsmnt[0] = '/';
- bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
- MNAMELEN);
- (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
- &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
- (void) cd9660_statfs(mp, &mp->mnt_stat, p);
- vfs_unlock(mp);
+ simple_unlock(&mountlist_slock);
+ (void)cd9660_statfs(mp, &mp->mnt_stat, p);
+ vfs_unbusy(mp, p);
return (0);
}
/*
- * Flag to allow forcible unmounting.
- */
-static int iso_doforce = 1;
-
-/*
* VFS Operations.
*
* mount system call
@@ -214,10 +196,8 @@ cd9660_mount(mp, path, data, ndp, p)
return error;
}
imp = VFSTOISOFS(mp);
- (void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size);
- bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size);
- bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
- MNAMELEN);
+ (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
+ bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
&size);
bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
@@ -277,11 +257,11 @@ iso_mountfs(devvp, mp, p, argp)
iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
- if ((error = bread (devvp, btodb(iso_blknum * iso_bsize),
- iso_bsize, NOCRED, &bp)))
+ if (error = bread(devvp, iso_blknum * btodb(iso_bsize),
+ iso_bsize, NOCRED, &bp))
goto out;
-
- vdp = (struct iso_volume_descriptor *)bp->b_un.b_addr;
+
+ vdp = (struct iso_volume_descriptor *)bp->b_data;
if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
if (bcmp (vdp->id_sierra, ISO_SIERRA_ID,
sizeof vdp->id) != 0) {
@@ -347,7 +327,7 @@ iso_mountfs(devvp, mp, p, argp)
mp->mnt_data = (qaddr_t)isomp;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
- mp->mnt_stat.f_fsid.val[1] = MOUNT_CD9660;
+ mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
mp->mnt_flag |= MNT_LOCAL;
isomp->im_mountp = mp;
@@ -358,14 +338,14 @@ iso_mountfs(devvp, mp, p, argp)
/* Check the Rock Ridge Extention support */
if (!(argp->flags & ISOFSMNT_NORRIP)) {
- if ((error = bread (isomp->im_devvp,
- (isomp->root_extent + isonum_711(rootp->ext_attr_length))
- * isomp->logical_block_size / DEV_BSIZE,
- isomp->logical_block_size,NOCRED,&bp)))
+ if (error = bread(isomp->im_devvp,
+ (isomp->root_extent + isonum_711(rootp->ext_attr_length)) <<
+ (isomp->im_bshift - DEV_BSHIFT),
+ isomp->logical_block_size, NOCRED, &bp))
goto out;
-
- rootp = (struct iso_directory_record *)bp->b_un.b_addr;
-
+
+ rootp = (struct iso_directory_record *)bp->b_data;
+
if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
argp->flags |= ISOFSMNT_NORRIP;
} else {
@@ -436,12 +416,9 @@ cd9660_unmount(mp, mntflags, p)
{
register struct iso_mnt *isomp;
int error, flags = 0;
-
- if (mntflags & MNT_FORCE) {
- if (!iso_doforce)
- return (EINVAL);
+
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
#if 0
mntflushbuf(mp, 0);
if (mntinvalbuf(mp))
@@ -474,33 +451,17 @@ cd9660_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- register struct iso_node *ip;
- struct iso_node tip, *nip;
- struct vnode tvp;
- int error;
- struct iso_mnt *imp = VFSTOISOFS (mp);
- struct iso_directory_record *dp;
-
- tvp.v_mount = mp;
- tvp.v_data = &tip;
- ip = VTOI(&tvp);
- ip->i_vnode = &tvp;
- ip->i_dev = imp->im_dev;
- ip->i_diroff = 0;
- dp = (struct iso_directory_record *)imp->root;
- isodirino(&ip->i_number,dp,imp);
-
+ struct iso_mnt *imp = VFSTOISOFS(mp);
+ struct iso_directory_record *dp =
+ (struct iso_directory_record *)imp->root;
+ ino_t ino = isodirino(dp, imp);
+
/*
* With RRIP we must use the `.' entry of the root directory.
- * Simply tell iget, that it's a relocated directory.
+ * Simply tell vget, that it's a relocated directory.
*/
- error = iso_iget(ip,ip->i_number,
- imp->iso_ftype == ISO_FTYPE_RRIP,
- &nip,dp);
- if (error)
- return error;
- *vpp = ITOV(nip);
- return 0;
+ return (cd9660_vget_internal(mp, ino, vpp,
+ imp->iso_ftype == ISO_FTYPE_RRIP, dp));
}
/*
@@ -541,10 +502,8 @@ cd9660_statfs(mp, sbp, p)
sbp->f_files = 0; /* total files */
sbp->f_ffree = 0; /* free file nodes */
if (sbp != &mp->mnt_stat) {
- bcopy((caddr_t)mp->mnt_stat.f_mntonname,
- (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
- bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
- (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
+ bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
+ bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
/* Use the first spare for flags: */
sbp->f_spare[0] = isomp->im_flags;
@@ -563,21 +522,6 @@ cd9660_sync(mp, waitfor, cred, p)
}
/*
- * Flat namespace lookup.
- * Currently unsupported.
- */
-/* ARGSUSED */
-static int
-cd9660_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-/*
* File handle to vnode
*
* Have to be really careful about stale file handles:
@@ -604,92 +548,262 @@ cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
int *exflagsp;
struct ucred **credanonp;
{
- struct vnode tvp;
- int error;
- int lbn, off;
- struct ifid *ifhp;
- struct iso_mnt *imp;
- struct buf *bp;
- struct iso_directory_record *dirp;
- struct iso_node tip, *ip, *nip;
- struct netcred *np;
-
- imp = VFSTOISOFS (mp);
- ifhp = (struct ifid *)fhp;
-
+ struct ifid *ifhp = (struct ifid *)fhp;
+ register struct iso_node *ip;
+ register struct netcred *np;
+ register struct iso_mnt *imp = VFSTOISOFS(mp);
+ struct vnode *nvp;
+ int error;
+
#ifdef ISOFS_DBG
printf("fhtovp: ino %d, start %ld\n",
ifhp->ifid_ino, ifhp->ifid_start);
#endif
-
+
+ /*
+ * Get the export permission structure for this <mp, client> tuple.
+ */
np = vfs_export_lookup(mp, &imp->im_export, nam);
if (np == NULL)
return (EACCES);
- lbn = iso_lblkno(imp, ifhp->ifid_ino);
- if (lbn >= imp->volume_space_size) {
- printf("fhtovp: lbn exceed volume space %d\n", lbn);
- return (ESTALE);
+ if (error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) {
+ *vpp = NULLVP;
+ return (error);
}
-
- off = iso_blkoff(imp, ifhp->ifid_ino);
- if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
- printf("fhtovp: crosses block boundary %d\n",
- off + ISO_DIRECTORY_RECORD_SIZE);
+ ip = VTOI(nvp);
+ if (ip->inode.iso_mode == 0) {
+ vput(nvp);
+ *vpp = NULLVP;
return (ESTALE);
}
+ *vpp = nvp;
+ *exflagsp = np->netc_exflags;
+ *credanonp = &np->netc_anon;
+ return (0);
+}
- error = bread(imp->im_devvp, btodb(lbn * imp->logical_block_size),
- imp->logical_block_size, NOCRED, &bp);
- if (error) {
- printf("fhtovp: bread error %d\n",error);
- brelse(bp);
+int
+cd9660_vget(mp, ino, vpp)
+ struct mount *mp;
+ ino_t ino;
+ struct vnode **vpp;
+{
+
+ /*
+ * XXXX
+ * It would be nice if we didn't always set the `relocated' flag
+ * and force the extra read, but I don't want to think about fixing
+ * that right now.
+ */
+ return (cd9660_vget_internal(mp, ino, vpp,
+#if 0
+ VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
+#else
+ 0,
+#endif
+ (struct iso_directory_record *)0));
+}
+
+int
+cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
+ struct mount *mp;
+ ino_t ino;
+ struct vnode **vpp;
+ int relocated;
+ struct iso_directory_record *isodir;
+{
+ struct iso_mnt *imp;
+ struct iso_node *ip;
+ struct buf *bp;
+ struct vnode *vp, *nvp;
+ dev_t dev;
+ int error;
+
+ imp = VFSTOISOFS(mp);
+ dev = imp->im_dev;
+ if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
+ return (0);
+
+ /* Allocate a new vnode/iso_node. */
+ if (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) {
+ *vpp = NULLVP;
return (error);
}
+ 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;
+ ip->i_number = ino;
- dirp = (struct iso_directory_record *)(bp->b_un.b_addr + off);
- if (off + isonum_711(dirp->length) > imp->logical_block_size) {
- brelse(bp);
- printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
- off+isonum_711(dirp->length), off,
- isonum_711(dirp->length));
- return (ESTALE);
+ /*
+ * Put it onto its hash chain and lock it so that other requests for
+ * this inode will block if they arrive while we are sleeping waiting
+ * for old data structures to be purged or for the contents of the
+ * disk portion of this inode to be read.
+ */
+ cd9660_ihashins(ip);
+
+ if (isodir == 0) {
+ int lbn, off;
+
+ lbn = lblkno(imp, ino);
+ if (lbn >= imp->volume_space_size) {
+ vput(vp);
+ printf("fhtovp: lbn exceed volume space %d\n", lbn);
+ return (ESTALE);
+ }
+
+ off = blkoff(imp, ino);
+ if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
+ vput(vp);
+ printf("fhtovp: crosses block boundary %d\n",
+ off + ISO_DIRECTORY_RECORD_SIZE);
+ return (ESTALE);
+ }
+
+ error = bread(imp->im_devvp,
+ lbn << (imp->im_bshift - DEV_BSHIFT),
+ imp->logical_block_size, NOCRED, &bp);
+ if (error) {
+ vput(vp);
+ brelse(bp);
+ printf("fhtovp: bread error %d\n",error);
+ return (error);
+ }
+ isodir = (struct iso_directory_record *)(bp->b_data + off);
+
+ if (off + isonum_711(isodir->length) >
+ imp->logical_block_size) {
+ vput(vp);
+ if (bp != 0)
+ brelse(bp);
+ printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
+ off +isonum_711(isodir->length), off,
+ isonum_711(isodir->length));
+ return (ESTALE);
+ }
+
+#if 0
+ if (isonum_733(isodir->extent) +
+ isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
+ if (bp != 0)
+ brelse(bp);
+ printf("fhtovp: file start miss %d vs %d\n",
+ isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
+ ifhp->ifid_start);
+ return (ESTALE);
+ }
+#endif
+ } else
+ bp = 0;
+
+ ip->i_mnt = imp;
+ ip->i_devvp = imp->im_devvp;
+ VREF(ip->i_devvp);
+
+ if (relocated) {
+ /*
+ * On relocated directories we must
+ * read the `.' entry out of a dir.
+ */
+ ip->iso_start = ino >> imp->im_bshift;
+ if (bp != 0)
+ brelse(bp);
+ if (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) {
+ vput(vp);
+ return (error);
+ }
+ isodir = (struct iso_directory_record *)bp->b_data;
}
- if (isonum_733(dirp->extent) + isonum_711(dirp->ext_attr_length) !=
- ifhp->ifid_start) {
- brelse(bp);
- printf("fhtovp: file start miss %d vs %ld\n",
- isonum_733(dirp->extent)+isonum_711(dirp->ext_attr_length),
- ifhp->ifid_start);
- return (ESTALE);
+ ip->iso_extent = isonum_733(isodir->extent);
+ ip->i_size = isonum_733(isodir->size);
+ ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
+
+ /*
+ * Setup time stamp, attribute
+ */
+ vp->v_type = VNON;
+ switch (imp->iso_ftype) {
+ default: /* ISO_FTYPE_9660 */
+ {
+ struct buf *bp2;
+ int off;
+ if ((imp->im_flags & ISOFSMNT_EXTATT)
+ && (off = isonum_711(isodir->ext_attr_length)))
+ VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
+ &bp2);
+ else
+ bp2 = NULL;
+ cd9660_defattr(isodir, ip, bp2, ISO_FTYPE_9660);
+ cd9660_deftstamp(isodir, ip, bp2, ISO_FTYPE_9660);
+ if (bp2)
+ brelse(bp2);
+ break;
+ }
+ case ISO_FTYPE_RRIP:
+ cd9660_rrip_analyze(isodir, ip, imp);
+ break;
}
- brelse(bp);
- ip = &tip;
- tvp.v_mount = mp;
- tvp.v_data = ip;
- ip->i_vnode = &tvp;
- ip->i_dev = imp->im_dev;
- if ((error = iso_iget(ip, ifhp->ifid_ino, 0, &nip, dirp))) {
- *vpp = NULLVP;
- printf("fhtovp: failed to get inode\n");
- return (error);
+ if (bp != 0)
+ brelse(bp);
+
+ /*
+ * Initialize the associated vnode
+ */
+ switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
+ case VFIFO:
+#ifdef FIFO
+ vp->v_op = cd9660_fifoop_p;
+ break;
+#else
+ vput(vp);
+ return (EOPNOTSUPP);
+#endif /* FIFO */
+ case VCHR:
+ case VBLK:
+ /*
+ * if device, look at device number table for translation
+ */
+#ifdef ISODEVMAP
+ if (dp = iso_dmap(dev, ino, 0))
+ ip->inode.iso_rdev = dp->d_dev;
+#endif
+ vp->v_op = cd9660_specop_p;
+ if (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) {
+ /*
+ * Discard unneeded vnode, but save its iso_node.
+ * Note that the lock is carried over in the iso_node
+ * to the replacement vnode.
+ */
+ nvp->v_data = vp->v_data;
+ vp->v_data = NULL;
+ vp->v_op = spec_vnodeop_p;
+ vrele(vp);
+ vgone(vp);
+ /*
+ * Reinitialize aliased inode.
+ */
+ vp = nvp;
+ ip->i_vnode = vp;
+ }
+ break;
}
- ip = nip;
+
+ if (ip->iso_extent == imp->root_extent)
+ vp->v_flag |= VROOT;
+
/*
* XXX need generation number?
*/
- if (ip->inode.iso_mode == 0) {
- iso_iput(ip);
- *vpp = NULLVP;
- printf("fhtovp: inode mode == 0\n");
- return (ESTALE);
- }
- *vpp = ITOV(ip);
- *exflagsp = np->netc_exflags;
- *credanonp = &np->netc_anon;
- return 0;
+
+ *vpp = vp;
+ return (0);
}
/*
diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c
index 88440eb..854d6b5 100644
--- a/sys/isofs/cd9660/cd9660_vnops.c
+++ b/sys/isofs/cd9660/cd9660_vnops.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cd9660_vnops.c 8.3 (Berkeley) 1/23/94
+ * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
* $FreeBSD$
*/
@@ -55,6 +55,7 @@
#include <miscfs/fifofs/fifo.h>
#include <sys/malloc.h>
#include <sys/dir.h>
+#include <sys/unistd.h>
#include <isofs/cd9660/iso.h>
#include <isofs/cd9660/cd9660_node.h>
@@ -81,7 +82,6 @@ static int cd9660_lock __P((struct vop_lock_args *));
static int cd9660_unlock __P((struct vop_unlock_args *));
static int cd9660_strategy __P((struct vop_strategy_args *));
static int cd9660_print __P((struct vop_print_args *));
-static int cd9660_enotsupp __P((void));
static int cd9660_islocked __P((struct vop_islocked_args *));
#if 0
@@ -100,7 +100,7 @@ cd9660_mknod(ndp, vap, cred, p)
free(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
vput(ndp->ni_vp);
- return EINVAL;
+ return (EINVAL);
#else
register struct vnode *vp;
struct iso_node *ip;
@@ -116,7 +116,7 @@ cd9660_mknod(ndp, vap, cred, p)
free(ndp->ni_pnbuf, M_NAMEI);
vput(ndp->ni_dvp);
vput(ndp->ni_vp);
- return EINVAL;
+ return (EINVAL);
}
dp = iso_dmap(ip->i_dev,ip->i_number,1);
@@ -144,7 +144,7 @@ cd9660_mknod(ndp, vap, cred, p)
/*
* Setattr call. Only allowed for block and character special devices.
*/
-static int
+int
cd9660_setattr(ap)
struct vop_setattr_args /* {
struct vnodeop_desc *a_desc;
@@ -175,7 +175,7 @@ cd9660_setattr(ap)
return (0);
}
}
- return (EOPNOTSUPP);
+ return (0);
}
/*
@@ -229,23 +229,65 @@ cd9660_access(ap)
struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
+ struct iso_node *ip = VTOI(vp);
+ struct ucred *cred = ap->a_cred;
+ mode_t mask, mode = ap->a_mode;
+ gid_t *gp;
+ int i;
+
/*
- * Disallow write attempts on read-only file systems;
- * unless the file is a socket, fifo, or a block or
- * character device resident on the file system.
+ * 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 (ap->a_vp->v_type) {
+ if (mode & VWRITE) {
+ switch (vp->v_type) {
case VDIR:
case VLNK:
case VREG:
- if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
- return (EROFS);
- break;
+ return (EROFS);
}
}
- return (0);
+ /* User id 0 always gets access. */
+ if (cred->cr_uid == 0)
+ return (0);
+
+ mask = 0;
+
+ /* Otherwise, check the owner. */
+ if (cred->cr_uid == ip->inode.iso_uid) {
+ if (mode & VEXEC)
+ mask |= S_IXUSR;
+ if (mode & VREAD)
+ mask |= S_IRUSR;
+ if (mode & VWRITE)
+ mask |= S_IWUSR;
+ return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
+ }
+
+ /* Otherwise, check the groups. */
+ for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
+ if (ip->inode.iso_gid == *gp) {
+ if (mode & VEXEC)
+ mask |= S_IXGRP;
+ if (mode & VREAD)
+ mask |= S_IRGRP;
+ if (mode & VWRITE)
+ mask |= S_IWGRP;
+ return ((ip->inode.iso_mode & mask) == mask ?
+ 0 : EACCES);
+ }
+
+ /* Otherwise, check everyone else. */
+ if (mode & VEXEC)
+ mask |= S_IXOTH;
+ if (mode & VREAD)
+ mask |= S_IROTH;
+ if (mode & VWRITE)
+ mask |= S_IWOTH;
+ return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
}
static int
@@ -275,6 +317,29 @@ cd9660_getattr(ap)
vap->va_rdev = ip->inode.iso_rdev;
vap->va_size = (u_quad_t) ip->i_size;
+ if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
+ struct vop_readlink_args rdlnk;
+ struct iovec aiov;
+ struct uio auio;
+ char *cp;
+
+ MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
+ aiov.iov_base = cp;
+ aiov.iov_len = MAXPATHLEN;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_procp = ap->a_p;
+ auio.uio_resid = MAXPATHLEN;
+ rdlnk.a_uio = &auio;
+ rdlnk.a_vp = ap->a_vp;
+ rdlnk.a_cred = ap->a_cred;
+ if (cd9660_readlink(&rdlnk) == 0)
+ vap->va_size = MAXPATHLEN - auio.uio_resid;
+ FREE(cp, M_TEMP);
+ }
vap->va_flags = 0;
vap->va_gen = 1;
vap->va_blocksize = ip->i_mnt->logical_block_size;
@@ -325,31 +390,31 @@ cd9660_read(ap)
return (0);
if (uio->uio_offset < 0)
return (EINVAL);
- ip->i_flag |= IACC;
+ ip->i_flag |= IN_ACCESS;
imp = ip->i_mnt;
do {
- lbn = iso_lblkno(imp, uio->uio_offset);
- on = iso_blkoff(imp, uio->uio_offset);
- n = min((unsigned)(imp->logical_block_size - on),
+ lbn = lblkno(imp, uio->uio_offset);
+ on = blkoff(imp, uio->uio_offset);
+ n = min((u_int)(imp->logical_block_size - on),
uio->uio_resid);
diff = (off_t)ip->i_size - uio->uio_offset;
if (diff <= 0)
return (0);
if (diff < n)
n = diff;
- size = iso_blksize(imp, ip, lbn);
+ size = blksize(imp, ip, lbn);
rablock = lbn + 1;
if (doclusterread) {
- if (iso_lblktosize(imp, rablock) <= ip->i_size)
- error = cluster_read(vp, ip->i_size,
+ if (lblktosize(imp, rablock) <= ip->i_size)
+ error = cluster_read(vp, (off_t)ip->i_size,
lbn, size, NOCRED, uio->uio_resid,
(ap->a_ioflag >> 16), &bp);
else
error = bread(vp, lbn, size, NOCRED, &bp);
} else {
if (vp->v_lastr + 1 == lbn &&
- iso_lblktosize(imp, rablock) < ip->i_size) {
- rasize = iso_blksize(imp, ip, rablock);
+ lblktosize(imp, rablock) < ip->i_size) {
+ rasize = blksize(imp, ip, rablock);
error = breadn(vp, lbn, size, &rablock,
&rasize, 1, NOCRED, &bp);
} else
@@ -362,7 +427,10 @@ cd9660_read(ap)
return (error);
}
- error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
+ error = uiomove(bp->b_data + on, (int)n, uio);
+ if (n + on == imp->logical_block_size ||
+ uio->uio_offset == (off_t)ip->i_size)
+ bp->b_flags |= B_AGE;
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n != 0);
return (error);
@@ -373,8 +441,8 @@ static int
cd9660_ioctl(ap)
struct vop_ioctl_args /* {
struct vnode *a_vp;
- int a_command;
- caddr_t a_data;
+ u_long a_command;
+ caddr_t a_data;
int a_fflag;
struct ucred *a_cred;
struct proc *a_p;
@@ -452,12 +520,12 @@ struct isoreaddir {
off_t curroff;
struct uio *uio;
off_t uio_off;
- u_int *cookiep;
+ int eofflag;
+ u_long *cookies;
int ncookies;
- int eof;
};
-static int
+int
iso_uiodir(idp,dp,off)
struct isoreaddir *idp;
struct dirent *dp;
@@ -469,27 +537,27 @@ iso_uiodir(idp,dp,off)
dp->d_reclen = DIRSIZ(dp);
if (idp->uio->uio_resid < dp->d_reclen) {
- idp->eof = 0;
- return -1;
+ idp->eofflag = 0;
+ return (-1);
}
- if (idp->cookiep) {
+ if (idp->cookies) {
if (idp->ncookies <= 0) {
- idp->eof = 0;
- return -1;
+ idp->eofflag = 0;
+ return (-1);
}
- *idp->cookiep++ = off;
+ *idp->cookies++ = off;
--idp->ncookies;
}
- if ((error = uiomove((caddr_t)dp,dp->d_reclen,idp->uio)))
- return error;
+ if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio))
+ return (error);
idp->uio_off = off;
- return 0;
+ return (0);
}
-static int
+int
iso_shipdir(idp)
struct isoreaddir *idp;
{
@@ -517,13 +585,13 @@ assoc = (cl > 1) && (*cname == ASSOCCHAR);
if (sl != cl
|| bcmp(sname,cname,sl)) {
if (idp->assocent.d_namlen) {
- if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)))
- return error;
+ if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
+ return (error);
idp->assocent.d_namlen = 0;
}
if (idp->saveent.d_namlen) {
- if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)))
- return error;
+ if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
+ return (error);
idp->saveent.d_namlen = 0;
}
}
@@ -536,13 +604,11 @@ assoc = (cl > 1) && (*cname == ASSOCCHAR);
idp->saveoff = idp->curroff;
bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
}
- return 0;
+ return (0);
}
/*
* Vnode op for readdir
- * XXX make sure everything still works now that eofflagp and cookiep
- * are no longer args.
*/
static int
cd9660_readdir(ap)
@@ -550,54 +616,61 @@ cd9660_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ int *a_ncookies;
+ u_long *a_cookies;
} */ *ap;
{
register struct uio *uio = ap->a_uio;
struct isoreaddir *idp;
+ struct vnode *vdp = ap->a_vp;
+ struct iso_node *dp;
+ struct iso_mnt *imp;
+ struct buf *bp = NULL;
+ struct iso_directory_record *ep;
int entryoffsetinblock;
+ doff_t endsearch;
+ u_long bmask;
int error = 0;
- int endsearch;
- struct iso_directory_record *ep;
- u_short elen;
- int namlen;
int reclen;
- int isoflags;
- struct iso_mnt *imp;
- struct iso_node *ip;
- struct buf *bp = NULL;
- u_short tmplen;
+ u_short namelen;
int ncookies = 0;
- u_int *cookies = NULL;
+ u_long *cookies = NULL;
- ip = VTOI(ap->a_vp);
- imp = ip->i_mnt;
+ dp = VTOI(vdp);
+ imp = dp->i_mnt;
+ bmask = imp->im_bmask;
- MALLOC(idp,struct isoreaddir *,sizeof(*idp),M_TEMP,M_WAITOK);
- idp->saveent.d_namlen = 0;
- idp->assocent.d_namlen = 0;
+ MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
+ idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
+ /*
+ * XXX
+ * Is it worth trying to figure out the type?
+ */
+ idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
+ DT_UNKNOWN;
idp->uio = uio;
- if (ap->a_ncookies != NULL) {
+ if (ap->a_ncookies == NULL) {
+ idp->cookies = NULL;
+ } else {
/*
* Guess the number of cookies needed.
*/
ncookies = uio->uio_resid / 16;
- MALLOC(cookies, u_int *, ncookies * sizeof(u_int), M_TEMP, M_WAITOK);
- idp->cookiep = cookies;
+ MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP,
+ M_WAITOK);
+ idp->cookies = cookies;
idp->ncookies = ncookies;
- } else
- idp->cookiep = 0;
- idp->eof = 0;
+ }
+ idp->eofflag = 1;
idp->curroff = uio->uio_offset;
- entryoffsetinblock = iso_blkoff(imp, idp->curroff);
- if (entryoffsetinblock != 0) {
- if ((error = iso_blkatoff(ip, idp->curroff, &bp))) {
- FREE(idp,M_TEMP);
- return (error);
- }
+ if ((entryoffsetinblock = idp->curroff & bmask) &&
+ (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
+ FREE(idp, M_TEMP);
+ return (error);
}
-
- endsearch = ip->i_size;
+ endsearch = dp->i_size;
while (idp->curroff < endsearch) {
/*
@@ -605,26 +678,25 @@ cd9660_readdir(ap)
* read the next directory block.
* Release previous if it exists.
*/
-
- if (iso_blkoff(imp, idp->curroff) == 0) {
+ if ((idp->curroff & bmask) == 0) {
if (bp != NULL)
brelse(bp);
- if ((error = iso_blkatoff(ip, idp->curroff, &bp)))
+ if (error =
+ VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))
break;
entryoffsetinblock = 0;
}
/*
* Get pointer to next entry.
*/
-
ep = (struct iso_directory_record *)
- (bp->b_un.b_addr + entryoffsetinblock);
+ ((char *)bp->b_data + entryoffsetinblock);
- reclen = isonum_711 (ep->length);
+ reclen = isonum_711(ep->length);
if (reclen == 0) {
/* skip to next block, if any */
- idp->curroff = roundup (idp->curroff,
- imp->logical_block_size);
+ idp->curroff =
+ (idp->curroff & ~bmask) + imp->logical_block_size;
continue;
}
@@ -640,35 +712,27 @@ cd9660_readdir(ap)
break;
}
- namlen = isonum_711 (ep->name_len);
- if (reclen < ISO_DIRECTORY_RECORD_SIZE + namlen) {
+ idp->current.d_namlen = isonum_711(ep->name_len);
+
+ if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
error = EINVAL;
/* illegal entry, stop */
break;
}
- /* XXX: be more intelligent if we can */
- idp->current.d_type = DT_UNKNOWN;
-
- idp->current.d_namlen = namlen;
- isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
- &ep->date[6]: ep->flags);
- if (isoflags & 2)
- isodirino(&idp->current.d_fileno,ep,imp);
+ if (isonum_711(ep->flags)&2)
+ idp->current.d_fileno = isodirino(ep, imp);
else
idp->current.d_fileno = dbtob(bp->b_blkno) +
- idp->curroff;
+ entryoffsetinblock;
idp->curroff += reclen;
- /*
- *
- */
+
switch (imp->iso_ftype) {
case ISO_FTYPE_RRIP:
- cd9660_rrip_getname(ep,idp->current.d_name,
- &tmplen,
+ cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
&idp->current.d_fileno,imp);
- idp->current.d_namlen = tmplen;
+ idp->current.d_namlen = (u_char)namelen;
if (idp->current.d_namlen)
error = iso_uiodir(idp,&idp->current,idp->curroff);
break;
@@ -685,10 +749,10 @@ cd9660_readdir(ap)
break;
default:
isofntrans(ep->name,idp->current.d_namlen,
- idp->current.d_name, &elen,
+ idp->current.d_name, &namelen,
imp->iso_ftype == ISO_FTYPE_9660,
- isoflags & 4);
- idp->current.d_namlen = (u_char)elen;
+ isonum_711(ep->flags)&4);
+ idp->current.d_namlen = (u_char)namelen;
if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
error = iso_shipdir(idp);
else
@@ -711,7 +775,7 @@ cd9660_readdir(ap)
if (ap->a_ncookies != NULL) {
if (error)
- FREE(cookies, M_TEMP);
+ free(cookies, M_TEMP);
else {
/*
* Work out the number of cookies actually used.
@@ -725,10 +789,9 @@ cd9660_readdir(ap)
brelse (bp);
uio->uio_offset = idp->uio_off;
- if (ap->a_eofflag)
- *ap->a_eofflag = idp->eof;
+ *ap->a_eofflag = idp->eofflag;
- FREE(idp,M_TEMP);
+ FREE(idp, M_TEMP);
return (error);
}
@@ -754,44 +817,34 @@ cd9660_readlink(ap)
ISODIR *dirp;
ISOMNT *imp;
struct buf *bp;
+ struct uio *uio;
u_short symlen;
int error;
char *symname;
ip = VTOI(ap->a_vp);
imp = ip->i_mnt;
+ uio = ap->a_uio;
if (imp->iso_ftype != ISO_FTYPE_RRIP)
- return EINVAL;
+ return (EINVAL);
/*
* Get parents directory record block that this inode included.
*/
error = bread(imp->im_devvp,
- iso_dblkno(imp, ip->i_number),
- imp->logical_block_size,
- NOCRED,
- &bp);
+ (ip->i_number >> imp->im_bshift) <<
+ (imp->im_bshift - DEV_BSHIFT),
+ imp->logical_block_size, NOCRED, &bp);
if (error) {
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Setup the directory pointer for this inode
*/
- dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask));
-#ifdef DEBUG
- printf("lbn=%d,off=%d,bsize=%d,DEV_BSIZE=%d, dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n",
- (daddr_t)(ip->i_number >> imp->im_bshift),
- ip->i_number & imp->im_bmask,
- imp->logical_block_size,
- DEV_BSIZE,
- dirp,
- bp->b_un.b_addr,
- ip->i_number,
- ip->i_number & imp->im_bmask );
-#endif
+ dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
/*
* Just make sure, we have a right one....
@@ -800,22 +853,26 @@ cd9660_readlink(ap)
if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
> (unsigned)imp->logical_block_size) {
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Now get a buffer
* Abuse a namei buffer for now.
*/
- MALLOC(symname,char *,MAXPATHLEN,M_NAMEI,M_WAITOK);
-
+ if (uio->uio_segflg == UIO_SYSSPACE)
+ symname = uio->uio_iov->iov_base;
+ else
+ MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
+
/*
* Ok, we just gathering a symbolic name in SL record.
*/
- if (cd9660_rrip_getsymname(dirp,symname,&symlen,imp) == 0) {
- FREE(symname,M_NAMEI);
+ if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
+ if (uio->uio_segflg != UIO_SYSSPACE)
+ FREE(symname, M_NAMEI);
brelse(bp);
- return EINVAL;
+ return (EINVAL);
}
/*
* Don't forget before you leave from home ;-)
@@ -825,11 +882,15 @@ cd9660_readlink(ap)
/*
* return with the symbolic name to caller's.
*/
- error = uiomove(symname,symlen,ap->a_uio);
-
- FREE(symname,M_NAMEI);
-
- return error;
+ if (uio->uio_segflg != UIO_SYSSPACE) {
+ error = uiomove(symname, symlen, uio);
+ FREE(symname, M_NAMEI);
+ return (error);
+ }
+ uio->uio_resid -= symlen;
+ uio->uio_iov->iov_base += symlen;
+ uio->uio_iov->iov_len -= symlen;
+ return (0);
}
/*
@@ -845,7 +906,7 @@ cd9660_abortop(ap)
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
- return 0;
+ return (0);
}
/*
@@ -855,12 +916,14 @@ static int
cd9660_lock(ap)
struct vop_lock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- register struct iso_node *ip = VTOI(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
- ISO_ILOCK(ip);
- return 0;
+ return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
+ ap->a_p));
}
/*
@@ -870,29 +933,14 @@ static int
cd9660_unlock(ap)
struct vop_unlock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- register struct iso_node *ip = VTOI(ap->a_vp);
-
- if (!(ip->i_flag & ILOCKED))
- panic("cd9660_unlock NOT LOCKED");
- ISO_IUNLOCK(ip);
- return 0;
-}
-
-/*
- * Check for a locked inode.
- */
-static int
-cd9660_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
+ struct vnode *vp = ap->a_vp;
- if (VTOI(ap->a_vp)->i_flag & ILOCKED)
- return 1;
- return 0;
+ return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
+ &vp->v_interlock, ap->a_p));
}
/*
@@ -943,102 +991,150 @@ cd9660_print(ap)
struct vnode *a_vp;
} */ *ap;
{
+
printf("tag VT_ISOFS, isofs vnode\n");
- return 0;
+ return (0);
+}
+
+/*
+ * Check for a locked inode.
+ */
+int
+cd9660_islocked(ap)
+ struct vop_islocked_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
+{
+
+ return (lockstatus(&VTOI(ap->a_vp)->i_lock));
}
/*
- * Unsupported operation
+ * Return POSIX pathconf information applicable to cd9660 filesystems.
*/
-static int
-cd9660_enotsupp()
+int
+cd9660_pathconf(ap)
+ struct vop_pathconf_args /* {
+ struct vnode *a_vp;
+ int a_name;
+ register_t *a_retval;
+ } */ *ap;
{
- return (EOPNOTSUPP);
+ switch (ap->a_name) {
+ case _PC_LINK_MAX:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NAME_MAX:
+ if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
+ *ap->a_retval = NAME_MAX;
+ else
+ *ap->a_retval = 37;
+ return (0);
+ case _PC_PATH_MAX:
+ *ap->a_retval = PATH_MAX;
+ return (0);
+ case _PC_PIPE_BUF:
+ *ap->a_retval = PIPE_BUF;
+ return (0);
+ case _PC_CHOWN_RESTRICTED:
+ *ap->a_retval = 1;
+ return (0);
+ case _PC_NO_TRUNC:
+ *ap->a_retval = 1;
+ return (0);
+ default:
+ return (EINVAL);
+ }
+ /* NOTREACHED */
}
/*
* Global vfs data structures for isofs
*/
#define cd9660_create \
- ((int (*) __P((struct vop_create_args *)))cd9660_enotsupp)
-#define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))cd9660_enotsupp)
-#define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_create_args *)))eopnotsupp)
+#define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
+#define cd9660_write ((int (*) __P((struct vop_write_args *)))eopnotsupp)
+#ifdef NFS
+#define cd9660_lease_check lease_check
+#else
+#define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
+#endif
#define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define cd9660_remove \
- ((int (*) __P((struct vop_remove_args *)))cd9660_enotsupp)
-#define cd9660_link ((int (*) __P((struct vop_link_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
+#define cd9660_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
#define cd9660_rename \
- ((int (*) __P((struct vop_rename_args *)))cd9660_enotsupp)
-#define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))cd9660_enotsupp)
-#define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
+#define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
+#define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
#define cd9660_symlink \
- ((int (*) __P((struct vop_symlink_args *)))cd9660_enotsupp)
-#define cd9660_pathconf \
- ((int (*) __P((struct vop_pathconf_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
#define cd9660_advlock \
- ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp)
-#define cd9660_blkatoff \
- ((int (*) __P((struct vop_blkatoff_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
#define cd9660_valloc ((int(*) __P(( \
struct vnode *pvp, \
int mode, \
struct ucred *cred, \
- struct vnode **vpp))) cd9660_enotsupp)
-#define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp)
+ struct vnode **vpp))) eopnotsupp)
+#define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))eopnotsupp)
#define cd9660_truncate \
- ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
#define cd9660_update \
- ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_update_args *)))eopnotsupp)
#define cd9660_bwrite \
- ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp)
+ ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
/*
- * Global vfs data structures for nfs
+ * Global vfs data structures for cd9660
*/
vop_t **cd9660_vnodeop_p;
-static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
+struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
+
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)cd9660_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)cd9660_open }, /* open */
- { &vop_close_desc, (vop_t *)cd9660_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)cd9660_read }, /* read */
- { &vop_write_desc, (vop_t *)cd9660_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)cd9660_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)cd9660_select }, /* select */
- { &vop_mmap_desc, (vop_t *)cd9660_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)cd9660_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)cd9660_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)cd9660_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)cd9660_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)cd9660_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)cd9660_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)cd9660_strategy }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)cd9660_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)cd9660_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)cd9660_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)cd9660_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)cd9660_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)cd9660_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)cd9660_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)cd9660_open }, /* open */
+ { &vop_close_desc, (vop_t *)cd9660_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)cd9660_read }, /* read */
+ { &vop_write_desc, (vop_t *)cd9660_write }, /* write */
+ { &vop_lease_desc, (vop_t *)cd9660_lease_check },/* lease */
+ { &vop_ioctl_desc, (vop_t *)cd9660_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)cd9660_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)cd9660_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)cd9660_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)cd9660_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)cd9660_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
+ { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)cd9660_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)cd9660_readlink },/* readlink */
+ { &vop_abortop_desc, (vop_t *)cd9660_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)cd9660_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)cd9660_strategy },/* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)cd9660_pathconf },/* pathconf */
+ { &vop_advlock_desc, (vop_t *)cd9660_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)cd9660_blkatoff },/* blkatoff */
+ { &vop_valloc_desc, (vop_t *)cd9660_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)cd9660_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)cd9660_truncate },/* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_vnodeop_opv_desc =
@@ -1049,101 +1145,106 @@ VNODEOP_SET(cd9660_vnodeop_opv_desc);
* Special device vnode ops
*/
vop_t **cd9660_specop_p;
-static struct vnodeopv_entry_desc cd9660_specop_entries[] = {
+struct vnodeopv_entry_desc cd9660_specop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)spec_open }, /* open */
- { &vop_close_desc, (vop_t *)spec_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)spec_read }, /* read */
- { &vop_write_desc, (vop_t *)spec_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)spec_select }, /* select */
- { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_getpages_desc, (vop_t *)spec_getpages}, /* getpages */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)spec_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)spec_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)spec_open }, /* open */
+ { &vop_close_desc, (vop_t *)spec_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)spec_read }, /* read */
+ { &vop_write_desc, (vop_t *)spec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
+ { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)spec_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)spec_link }, /* link */
+ { &vop_rename_desc, (vop_t *)spec_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)spec_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)spec_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)spec_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
+ { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */
+ { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_specop_opv_desc =
{ &cd9660_specop_p, cd9660_specop_entries };
VNODEOP_SET(cd9660_specop_opv_desc);
+#ifdef FIFO
vop_t **cd9660_fifoop_p;
-static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
+struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
- { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
- { &vop_create_desc, (vop_t *)cd9660_create }, /* create */
- { &vop_mknod_desc, (vop_t *)cd9660_mknod }, /* mknod */
- { &vop_open_desc, (vop_t *)fifo_open }, /* open */
- { &vop_close_desc, (vop_t *)fifo_close }, /* close */
- { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
- { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
- { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
- { &vop_read_desc, (vop_t *)fifo_read }, /* read */
- { &vop_write_desc, (vop_t *)fifo_write }, /* write */
- { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
- { &vop_select_desc, (vop_t *)fifo_select }, /* select */
- { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
- { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
- { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
- { &vop_remove_desc, (vop_t *)cd9660_remove }, /* remove */
- { &vop_link_desc, (vop_t *)cd9660_link }, /* link */
- { &vop_rename_desc, (vop_t *)cd9660_rename }, /* rename */
- { &vop_mkdir_desc, (vop_t *)cd9660_mkdir }, /* mkdir */
- { &vop_rmdir_desc, (vop_t *)cd9660_rmdir }, /* rmdir */
- { &vop_symlink_desc, (vop_t *)cd9660_symlink }, /* symlink */
- { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
- { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
- { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
- { &vop_inactive_desc, (vop_t *)cd9660_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
- { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
- { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
- { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
- { &vop_strategy_desc, (vop_t *)fifo_badop }, /* strategy */
- { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
- { &vop_islocked_desc, (vop_t *)cd9660_islocked }, /* islocked */
- { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
- { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
- { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
- { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
- { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
- { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
- { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
- { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
+ { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
+ { &vop_create_desc, (vop_t *)fifo_create }, /* create */
+ { &vop_mknod_desc, (vop_t *)fifo_mknod }, /* mknod */
+ { &vop_open_desc, (vop_t *)fifo_open }, /* open */
+ { &vop_close_desc, (vop_t *)fifo_close }, /* close */
+ { &vop_access_desc, (vop_t *)cd9660_access }, /* access */
+ { &vop_getattr_desc, (vop_t *)cd9660_getattr }, /* getattr */
+ { &vop_setattr_desc, (vop_t *)cd9660_setattr }, /* setattr */
+ { &vop_read_desc, (vop_t *)fifo_read }, /* read */
+ { &vop_write_desc, (vop_t *)fifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
+ { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
+ { &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
+ { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
+ { &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
+ { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
+ { &vop_remove_desc, (vop_t *)fifo_remove }, /* remove */
+ { &vop_link_desc, (vop_t *)fifo_link } , /* link */
+ { &vop_rename_desc, (vop_t *)fifo_rename }, /* rename */
+ { &vop_mkdir_desc, (vop_t *)fifo_mkdir }, /* mkdir */
+ { &vop_rmdir_desc, (vop_t *)fifo_rmdir }, /* rmdir */
+ { &vop_symlink_desc, (vop_t *)fifo_symlink }, /* symlink */
+ { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
+ { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
+ { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
+ { &vop_inactive_desc, (vop_t *)cd9660_inactive },/* inactive */
+ { &vop_reclaim_desc, (vop_t *)cd9660_reclaim }, /* reclaim */
+ { &vop_lock_desc, (vop_t *)cd9660_lock }, /* lock */
+ { &vop_unlock_desc, (vop_t *)cd9660_unlock }, /* unlock */
+ { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
+ { &vop_strategy_desc, (vop_t *)fifo_strategy }, /* strategy */
+ { &vop_print_desc, (vop_t *)cd9660_print }, /* print */
+ { &vop_islocked_desc, (vop_t *)cd9660_islocked },/* islocked */
+ { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
+ { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
+ { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
+ { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
+ { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
+ { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
+ { &vop_update_desc, (vop_t *)cd9660_update }, /* update */
+ { &vop_bwrite_desc, (vop_t *)vn_bwrite },
{ NULL, NULL }
};
static struct vnodeopv_desc cd9660_fifoop_opv_desc =
{ &cd9660_fifoop_p, cd9660_fifoop_entries };
VNODEOP_SET(cd9660_fifoop_opv_desc);
+#endif /* FIFO */
diff --git a/sys/isofs/cd9660/iso.h b/sys/isofs/cd9660/iso.h
index 1656c23..e2a7779 100644
--- a/sys/isofs/cd9660/iso.h
+++ b/sys/isofs/cd9660/iso.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)iso.h 8.2 (Berkeley) 1/23/94
+ * @(#)iso.h 8.6 (Berkeley) 5/10/95
* $FreeBSD$
*/
@@ -138,37 +138,37 @@ struct iso_sierra_primary_descriptor {
struct iso_directory_record {
char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
- unsigned char extent [ISODCL (3, 10)]; /* 733 */
- unsigned char size [ISODCL (11, 18)]; /* 733 */
+ u_char extent [ISODCL (3, 10)]; /* 733 */
+ u_char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
char name_len [ISODCL (33, 33)]; /* 711 */
- char name [0];
+ char name [1]; /* XXX */
};
/* can't take sizeof(iso_directory_record), because of possible alignment
of the last entry (34 instead of 33) */
#define ISO_DIRECTORY_RECORD_SIZE 33
struct iso_extended_attributes {
- unsigned char owner [ISODCL (1, 4)]; /* 723 */
- unsigned char group [ISODCL (5, 8)]; /* 723 */
- unsigned char perm [ISODCL (9, 10)]; /* 9.5.3 */
+ u_char owner [ISODCL (1, 4)]; /* 723 */
+ u_char group [ISODCL (5, 8)]; /* 723 */
+ u_char perm [ISODCL (9, 10)]; /* 9.5.3 */
char ctime [ISODCL (11, 27)]; /* 8.4.26.1 */
char mtime [ISODCL (28, 44)]; /* 8.4.26.1 */
char xtime [ISODCL (45, 61)]; /* 8.4.26.1 */
char ftime [ISODCL (62, 78)]; /* 8.4.26.1 */
char recfmt [ISODCL (79, 79)]; /* 711 */
char recattr [ISODCL (80, 80)]; /* 711 */
- unsigned char reclen [ISODCL (81, 84)]; /* 723 */
+ u_char reclen [ISODCL (81, 84)]; /* 723 */
char system_id [ISODCL (85, 116)]; /* achars */
char system_use [ISODCL (117, 180)];
char version [ISODCL (181, 181)]; /* 711 */
char len_esc [ISODCL (182, 182)]; /* 711 */
char reserved [ISODCL (183, 246)];
- unsigned char len_au [ISODCL (247, 250)]; /* 723 */
+ u_char len_au [ISODCL (247, 250)]; /* 723 */
};
/* CD-ROM Format type */
@@ -191,7 +191,6 @@ struct iso_mnt {
int im_bmask;
int volume_space_size;
- char im_fsmnt[50];
struct netexport im_export;
char root[ISODCL (157, 190)];
@@ -205,94 +204,102 @@ struct iso_mnt {
#define VFSTOISOFS(mp) ((struct iso_mnt *)((mp)->mnt_data))
-#define iso_blkoff(imp, loc) ((loc) & (imp)->im_bmask)
-#define iso_lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
-#define iso_blksize(imp, ip, lbn) ((imp)->logical_block_size)
-#define iso_lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
-#define iso_lblktodaddr(imp, lbn) btodb(iso_lblktosize(imp, lbn))
-#define iso_dblkinc(imp, lbn) ((lbn) + iso_lblktodaddr(imp, 1))
-#define iso_dblkno(imp, loc) iso_lblktodaddr(imp, iso_lblkno(imp, loc))
-int cd9660_init __P((void));
-
-struct iso_node;
-int iso_blkatoff __P((struct iso_node *ip, long offset, struct buf **bpp));
-int iso_iget __P((struct iso_node *xp, ino_t ino, int relocated,
- struct iso_node **ipp, struct iso_directory_record *isodir));
-int iso_iput __P((struct iso_node *ip));
-int iso_ilock __P((struct iso_node *ip));
-int iso_iunlock __P((struct iso_node *ip));
-int cd9660_mountroot __P((void));
+#define blkoff(imp, loc) ((loc) & (imp)->im_bmask)
+#define lblktosize(imp, blk) ((blk) << (imp)->im_bshift)
+#define lblkno(imp, loc) ((loc) >> (imp)->im_bshift)
+#define blksize(imp, ip, lbn) ((imp)->logical_block_size)
+
+int cd9660_vget_internal __P((struct mount *, ino_t, struct vnode **, int,
+ struct iso_directory_record *));
+int cd9660_init __P((struct vfsconf *));
+#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+
+int cd9660_mountroot __P((void));
extern vop_t **cd9660_vnodeop_p;
+extern vop_t **cd9660_specop_p;
+#ifdef FIFO
+extern vop_t **cd9660_fifoop_p;
+#endif
-static int isonum_711 __P((unsigned char *p));
-static int isonum_712 __P((char *p));
-static int isonum_721 __P((unsigned char *p));
-static int isonum_722 __P((unsigned char *p));
-static int isonum_723 __P((unsigned char *p));
-static int isonum_731 __P((unsigned char *p));
-static int isonum_732 __P((unsigned char *p));
-static int isonum_733 __P((unsigned char *p));
-
-static inline int
+static __inline int isonum_711 __P((u_char *));
+static __inline int
isonum_711(p)
- unsigned char *p;
+ u_char *p;
{
return *p;
}
-static inline int
+static __inline int isonum_712 __P((char *));
+static __inline int
isonum_712(p)
char *p;
{
return *p;
}
-static inline int
-isonum_721(p)
- unsigned char *p;
+#ifndef UNALIGNED_ACCESS
+
+static __inline int isonum_723 __P((u_char *));
+static __inline int
+isonum_723(p)
+ u_char *p;
{
- return *p|((char)p[1] << 8);
+ return *p|(p[1] << 8);
}
-static inline int
-isonum_722(p)
- unsigned char *p;
+static __inline int isonum_733 __P((u_char *));
+static __inline int
+isonum_733(p)
+ u_char *p;
{
- return ((char)*p << 8)|p[1];
+ return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
}
-static inline int
+#else /* UNALIGNED_ACCESS */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+static __inline int
isonum_723(p)
- unsigned char *p;
+ u_char *p
{
- return isonum_721(p);
+ return *(u_int16t *)p;
}
-static inline int
-isonum_731(p)
- unsigned char *p;
+static __inline int
+isonum_733(p)
+ u_char *p;
{
- return *p|(p[1] << 8)|(p[2] << 16)|(p[3] << 24);
+ return *(u_int32t *)p;
}
-static inline int
-isonum_732(p)
- unsigned char *p;
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+static __inline int
+isonum_723(p)
+ u_char *p
{
- return (*p << 24)|(p[1] << 16)|(p[2] << 8)|p[3];
+ return *(u_int16t *)(p + 2);
}
-static inline int
+static __inline int
isonum_733(p)
- unsigned char *p;
+ u_char *p;
{
- return isonum_731(p);
+ return *(u_int32t *)(p + 4);
}
-int isofncmp __P((unsigned char *, int, unsigned char *, int));
-void isofntrans __P((unsigned char *, int, unsigned char *, unsigned short *,
- int, int));
+#endif
+
+#endif /* UNALIGNED_ACCESS */
+
+int isofncmp __P((u_char *, int, u_char *, int));
+void isofntrans __P((u_char *, int, u_char *, u_short *, int, int));
+ino_t isodirino __P((struct iso_directory_record *, struct iso_mnt *));
/*
* Associated files have a leading '='.
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 71311eb..0730253 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -43,7 +43,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index edc4c45..47caf98 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -55,7 +55,7 @@
#include <vm/vm_kern.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_map.h>
#include <vm/vm_prot.h>
#include <vm/vm_extern.h>
@@ -358,7 +358,7 @@ elf_load_file(struct proc *p, char *file, u_long *addr, u_long *entry)
/*
* No longer need this, and it prevents demand paging.
*/
- VOP_UNLOCK(nd.ni_vp);
+ VOP_UNLOCK(nd.ni_vp, 0, p);
if (error)
goto fail;
diff --git a/sys/kern/imgact_gzip.c b/sys/kern/imgact_gzip.c
index 3156a86..9186749 100644
--- a/sys/kern/imgact_gzip.c
+++ b/sys/kern/imgact_gzip.c
@@ -39,7 +39,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_kern.h>
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 24c8ffb..589a4c5 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -66,7 +66,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/user.h>
@@ -468,16 +468,16 @@ sched_setup(dummy)
SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL)
/* ARGSUSED*/
-static void xxx_vfs_mountroot __P((void *dummy));
+static void xxx_vfs_mountroot __P((void *fsnamep));
static void
-xxx_vfs_mountroot(dummy)
- void *dummy;
+xxx_vfs_mountroot(fsnamep)
+ void *fsnamep;
{
/* Mount the root file system. */
- if ((*mountroot)(mountrootvfsops))
+ if (vfs_mountrootfs(*((char **) fsnamep)))
panic("cannot mount root");
}
-SYSINIT(mountroot, SI_SUB_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot, NULL)
+SYSINIT(mountroot, SI_SUB_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot, &mountrootfsname)
/* ARGSUSED*/
static void xxx_vfs_root_fdtab __P((void *dummy));
@@ -492,7 +492,7 @@ xxx_vfs_root_fdtab(dummy)
panic("cannot find root vnode");
fdp->fd_fd.fd_cdir = rootvnode;
VREF(fdp->fd_fd.fd_cdir);
- VOP_UNLOCK(rootvnode);
+ VOP_UNLOCK(rootvnode, 0, &proc0);
fdp->fd_fd.fd_rdir = NULL;
}
SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL)
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 9f41c00..dc5978d 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -238,7 +238,7 @@ struct sysent sysent[] = {
{ 2, (sy_call_t *)mlock }, /* 203 = mlock */
{ 2, (sy_call_t *)munlock }, /* 204 = munlock */
{ 2, (sy_call_t *)utrace }, /* 205 = utrace */
- { 0, (sy_call_t *)nosys }, /* 206 = nosys */
+ { 1, (sy_call_t *)undelete }, /* 206 = undelete */
{ 0, (sy_call_t *)nosys }, /* 207 = nosys */
{ 0, (sy_call_t *)nosys }, /* 208 = nosys */
{ 0, (sy_call_t *)nosys }, /* 209 = nosys */
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
index 2704347..59d0d35 100644
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -49,6 +49,7 @@
#include <sys/file.h>
#include <sys/syslog.h>
#include <sys/kernel.h>
+#include <sys/sysent.h>
#include <sys/sysctl.h>
#include <sys/namei.h>
#include <sys/errno.h>
@@ -101,18 +102,15 @@ SYSCTL_INT(_kern, OID_AUTO, acct_chkfreq, CTLFLAG_RW,
* Accounting system call. Written based on the specification and
* previous implementation done by Mark Tinguely.
*/
-#ifndef _SYS_SYSPROTO_H_
-struct acct_args {
- char *path;
-};
-
-#endif
int
-acct(p, uap, retval)
- struct proc *p;
- struct acct_args *uap;
- int *retval;
+acct(a1, uap, a3)
+ struct proc *a1;
+ struct acct_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ int *a3;
{
+ struct proc *p = curproc; /* XXX */
struct nameidata nd;
int error;
@@ -125,12 +123,13 @@ acct(p, uap, retval)
* If accounting is to be started to a file, open that file for
* writing and make sure it's a 'normal'.
*/
- if (uap->path != NULL) {
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, p);
+ if (SCARG(uap, path) != NULL) {
+ NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path),
+ p);
error = vn_open(&nd, FWRITE, 0);
if (error)
return (error);
- VOP_UNLOCK(nd.ni_vp);
+ VOP_UNLOCK(nd.ni_vp, 0, p);
if (nd.ni_vp->v_type != VREG) {
vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
return (EACCES);
@@ -147,7 +146,7 @@ acct(p, uap, retval)
p->p_ucred, p);
acctp = savacctp = NULLVP;
}
- if (uap->path == NULL)
+ if (SCARG(uap, path) == NULL)
return (error);
/*
@@ -228,7 +227,7 @@ acct_process(p)
/*
* Now, just write the accounting information to the file.
*/
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
return (vn_rdwr(UIO_WRITE, vp, (caddr_t)&acct, sizeof (acct),
(off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, p->p_ucred,
(int *)0, p));
@@ -298,7 +297,9 @@ acctwatch(a)
savacctp = NULLVP;
log(LOG_NOTICE, "Accounting resumed\n");
}
- } else if (acctp != NULLVP) {
+ } else {
+ if (acctp == NULLVP)
+ return;
if (acctp->v_type == VBAD) {
(void) vn_close(acctp, FWRITE, NOCRED, NULL);
acctp = NULLVP;
@@ -310,7 +311,6 @@ acctwatch(a)
acctp = NULLVP;
log(LOG_NOTICE, "Accounting suspended\n");
}
- } else
- return;
+ }
timeout(acctwatch, NULL, acctchkfreq * hz);
}
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 6b958df..938e3df 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -70,7 +70,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/sysctl.h>
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index 62deb52..c6a9e14 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -192,6 +192,14 @@ void
bdevsw_add_generic(int bdev, int cdev, struct bdevsw *bdevsw)
{
dev_t dev;
+ /*
+ * XXX hack alert.
+ */
+ if (isdisk(makedev(bdev, 0), VBLK) && bdevsw->d_flags != D_DISK) {
+ printf("bdevsw_add_generic: adding D_DISK flag for device %d\n",
+ bdev);
+ bdevsw->d_flags = D_DISK;
+ }
cdevsw_make(bdevsw);
dev = makedev(cdev, 0);
cdevsw_add(&dev, bdevsw->d_cdev, NULL);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 1a27a34..2d4247c 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -51,7 +51,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_kern.h>
@@ -162,7 +162,7 @@ interpret:
* Lose the lock on the vnode. It's no longer needed, and must not
* exist for the pagefault paging to work below.
*/
- VOP_UNLOCK(imgp->vp);
+ VOP_UNLOCK(imgp->vp, 0, p);
if (error)
goto exec_fail_dealloc;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 82c1f8b..f65419f 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/*-
+/*
* Copyright (c) 1982, 1986, 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
@@ -73,7 +73,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_kern.h>
@@ -208,7 +208,7 @@ exit1(p, rv)
* 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);
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 572cb60..0de5272 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -56,7 +56,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index e9f4792..3ed8013 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -271,7 +271,7 @@ ktrace(curp, uap, retval)
return (error);
}
vp = nd.ni_vp;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curp);
if (vp->v_type != VREG) {
(void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
curp->p_traceflag &= ~KTRFAC_ACTIVE;
@@ -478,9 +478,9 @@ ktrwrite(vp, kth)
aiov[1].iov_len = kth->ktr_len;
auio.uio_resid += kth->ktr_len;
}
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_WRITE(vp, &auio, IO_UNIT|IO_APPEND, p->p_ucred);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (!error)
return;
/*
diff --git a/sys/kern/kern_lkm.c b/sys/kern/kern_lkm.c
index c2dad16..33c5ef3 100644
--- a/sys/kern/kern_lkm.c
+++ b/sys/kern/kern_lkm.c
@@ -604,8 +604,11 @@ _lkm_vfs(lkmtp, cmd)
{
struct lkm_vfs *args = lkmtp->private.lkm_vfs;
struct vfsconf *vfc = args->lkm_vfsconf;
+ struct vfsconf *vfsp, *lastvfsp, *prev_vfsp, *new_vfc;
int i;
int err = 0;
+ char fstypename[MFSNAMELEN];
+ int neednamesearch = 1;
switch(cmd) {
case LKM_E_LOAD:
@@ -613,26 +616,51 @@ _lkm_vfs(lkmtp, cmd)
if (lkmexists(lkmtp))
return(EEXIST);
- for(i = 0; i < MOUNT_MAXTYPE; i++) {
- if(!strcmp(vfc->vfc_name, vfsconf[i]->vfc_name)) {
- return EEXIST;
- }
- }
-
- i = args->lkm_offset = vfc->vfc_index;
- if (i < 0) {
- for (i = MOUNT_MAXTYPE - 1; i >= 0; i--) {
- if(vfsconf[i] == &void_vfsconf)
+ /* check to see if filesystem already exists */
+ vfsp = NULL;
+#ifdef COMPAT_43 /* see vfs_syscalls.c:mount() */
+ if (vfc->vfc_typenum < maxvfsconf) {
+ neednamesearch = 0;
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (vfsp->vfc_typenum == vfc->vfc_typenum)
break;
+ if (vfsp != NULL) {
+ neednamesearch = 1;
+ strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
+ }
+ } else
+#endif /* COMPAT_43 */
+ if (neednamesearch) {
+ strncpy(fstypename, vfc->vfc_name, MFSNAMELEN);
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
+ if (!strcmp(vfsp->vfc_name, fstypename)) {
+ return EEXIST;
+ }
}
}
+
+ i = args->lkm_offset = vfc->vfc_typenum;
if (i < 0) {
- return EINVAL;
+ i = maxvfsconf;
}
- args->lkm_offset = vfc->vfc_index = i;
+ args->lkm_offset = vfc->vfc_typenum = i;
+
+ if (maxvfsconf <= vfsp->vfc_typenum)
+ maxvfsconf = vfsp->vfc_typenum + 1;
+
+ /* find vfsconf tail */
+ for (lastvfsp = vfsconf; lastvfsp->vfc_next;
+ lastvfsp = lastvfsp->vfc_next) ;
- vfsconf[i] = vfc;
- vfssw[i] = vfc->vfc_vfsops;
+ /* make copy */
+/* possible race condition if vfsconf changes while we wait XXX JH */
+ MALLOC(new_vfc, struct vfsconf *, sizeof(struct vfsconf),
+ M_VFSCONF, M_WAITOK);
+ *new_vfc = *vfc;
+ vfc = new_vfc;
+
+ lastvfsp->vfc_next = vfc;
+ vfc->vfc_next = NULL;
/* like in vfs_op_init */
for(i = 0; args->lkm_vnodeops->ls_items[i]; i++) {
@@ -645,7 +673,7 @@ _lkm_vfs(lkmtp, cmd)
/*
* Call init function for this VFS...
*/
- (*(vfssw[vfc->vfc_index]->vfs_init))();
+ (*(vfsp->vfc_vfsops->vfs_init))(vfsp);
/* done! */
break;
@@ -654,13 +682,23 @@ _lkm_vfs(lkmtp, cmd)
/* current slot... */
i = args->lkm_offset;
- if (vfsconf[i]->vfc_refcount) {
+ prev_vfsp = NULL;
+ for (vfsp = vfsconf; vfsp;
+ prev_vfsp = vfsp, vfsp = vfsp->vfc_next) {
+ if (vfsp->vfc_typenum == vfc->vfc_typenum)
+ break;
+ }
+ if (vfsp == NULL) {
+ return EINVAL;
+ }
+
+ if (vfsp->vfc_refcount) {
return EBUSY;
}
- /* replace current slot contents with old contents */
- vfssw[i] = (struct vfsops *)0;
- vfsconf[i] = &void_vfsconf;
+ FREE(vfsp, M_VFSCONF);
+
+ prev_vfsp->vfc_next = vfsp->vfc_next;
break;
diff --git a/sys/kern/kern_lockf.c b/sys/kern/kern_lockf.c
index aea3976..3491e63 100644
--- a/sys/kern/kern_lockf.c
+++ b/sys/kern/kern_lockf.c
@@ -52,16 +52,18 @@
* This variable controls the maximum number of processes that will
* be checked in doing deadlock detection.
*/
-int maxlockdepth = MAXDEPTH;
+static int maxlockdepth = MAXDEPTH;
#ifdef LOCKF_DEBUG
+#include <vm/vm.h>
+#include <sys/sysctl.h>
int lockf_debug = 0;
+SYSCTL_INT(_debug, 4, lockf_debug, CTLFLAG_RW, &lockf_debug, 0, "");
#endif
#define NOLOCKF (struct lockf *)0
#define SELF 0x1
#define OTHERS 0x2
-static void lf_addblock __P((struct lockf *, struct lockf *));
static int lf_clearlock __P((struct lockf *));
static int lf_findoverlap __P((struct lockf *,
struct lockf *, int, struct lockf ***, struct lockf **));
@@ -138,10 +140,11 @@ lf_advlock(ap, head, size)
lock->lf_start = start;
lock->lf_end = end;
lock->lf_id = ap->a_id;
- lock->lf_head = head;
+/* lock->lf_inode = ip; */ /* XXX JH */
lock->lf_type = fl->l_type;
+ lock->lf_head = head;
lock->lf_next = (struct lockf *)0;
- lock->lf_block = (struct lockf *)0;
+ TAILQ_INIT(&lock->lf_blkhd);
lock->lf_flags = ap->a_flags;
/*
* Do the requested operation.
@@ -252,7 +255,7 @@ lf_setlock(lock)
* 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);
@@ -260,19 +263,19 @@ lf_setlock(lock)
}
#endif /* LOCKF_DEBUG */
if ((error = tsleep((caddr_t)lock, priority, lockstr, 0))) {
- /*
- * Delete ourselves from the waiting to lock list.
- */
- 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;
- }
- free(lock, M_LOCKF);
- return (error);
+ /*
+ * 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).
+ */
+ if (lock->lf_next)
+ TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock,
+ lf_block);
+ free(lock, M_LOCKF);
+ return (error);
}
}
/*
@@ -347,9 +350,12 @@ lf_setlock(lock)
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.
@@ -645,34 +651,6 @@ lf_findoverlap(lf, lock, type, prev, overlap)
}
/*
- * Add a lock to the end of the blocked list.
- */
-static void
-lf_addblock(blocklist, lock)
- struct lockf *blocklist;
- struct lockf *lock;
-{
- register struct lockf *lf;
-
- if (lock == NOLOCKF)
- return;
-#ifdef LOCKF_DEBUG
- if (lockf_debug & 2) {
- lf_print("addblock: adding", lock);
- lf_print("to blocked list of", blocklist);
- }
-#endif /* LOCKF_DEBUG */
- if ((lf = blocklist->lf_block) == NOLOCKF) {
- blocklist->lf_block = lock;
- return;
- }
- while (lf->lf_block != NOLOCKF)
- lf = lf->lf_block;
- lf->lf_block = lock;
- return;
-}
-
-/*
* Split a lock and a contained region into
* two or three locks as necessary.
*/
@@ -710,7 +688,7 @@ lf_split(lock1, lock2)
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
@@ -727,28 +705,23 @@ static void
lf_wakelock(listhead)
struct lockf *listhead;
{
- register struct lockf *blocklist, *wakelock;
-
- blocklist = listhead->lf_block;
- listhead->lf_block = NOLOCKF;
- while (blocklist != NOLOCKF) {
- wakelock = blocklist;
- blocklist = blocklist->lf_block;
- wakelock->lf_block = NOLOCKF;
+ register struct lockf *wakelock;
+
+ 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 */
- wakeup((caddr_t)wakelock);
- }
+ wakeup((caddr_t)wakelock);
+ }
}
#ifdef LOCKF_DEBUG
/*
* Print out a lock.
*/
-void
lf_print(tag, lock)
char *tag;
register struct lockf *lock;
@@ -767,18 +740,17 @@ lf_print(tag, lock)
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 0x%x\n", lock->lf_block);
+ if (lock->lf_blkhd.tqh_first)
+ printf(" block 0x%x\n", lock->lf_blkhd.tqh_first);
else
printf("\n");
}
-void
lf_printlist(tag, lock)
char *tag;
struct lockf *lock;
{
- register struct lockf *lf;
+ register struct lockf *lf, *blk;
printf("%s: Lock list for ino %d on dev <%d, %d>:\n",
tag, lock->lf_inode->i_number,
@@ -795,10 +767,23 @@ lf_printlist(tag, lock)
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 0x%x\n", lf->lf_block);
- else
- printf("\n");
+ for (blk = lf->lf_blkhd.tqh_first; blk;
+ blk = blk->lf_block.tqe_next) {
+ printf("\n\t\tlock request 0x%lx for ", blk);
+ if (blk->lf_flags & F_POSIX)
+ printf("proc %d",
+ ((struct proc *)(blk->lf_id))->p_pid);
+ else
+ printf("id 0x%x", blk->lf_id);
+ printf(", %s, start %d, end %d",
+ 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 */
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 2b162be..37d99e4 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -53,7 +53,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/user.h>
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 70d1551..d9381a6 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -53,7 +53,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 0b82597..0f6c9e5 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -67,7 +67,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/user.h> /* for coredump */
@@ -660,7 +660,7 @@ gsignal(pgid, signum)
}
/*
- * 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
@@ -1255,7 +1255,7 @@ coredump(p)
}
VATTR_NULL(&vattr);
vattr.va_size = 0;
- LEASE_CHECK(vp, p, cred, LEASE_WRITE);
+ VOP_LEASE(vp, p, cred, LEASE_WRITE);
VOP_SETATTR(vp, &vattr, cred, p);
p->p_acflag |= ACORE;
bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc));
@@ -1272,7 +1272,7 @@ coredump(p)
(off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE,
IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
out:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error1 = vn_close(vp, FWRITE, cred, p);
if (error == 0)
error = error1;
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index d591c96..43f9e5d 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -529,9 +529,10 @@ mi_switch()
register long s, u;
struct timeval tv;
-#ifdef DEBUG
- if (p->p_simple_locks)
- panic("sleep: holding simple lock");
+#ifdef SIMPLELOCK_DEBUG
+ if (p->p_simple_locks) {
+ printf("sleep: holding simple lock");
+ }
#endif
/*
* Compute the amount of time during which the current
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 6b958df..938e3df 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -70,7 +70,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/sysctl.h>
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 82b03d5..baa8789 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -139,7 +139,9 @@ settimeofday(p, uap, retval)
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
if (timerisset(&p->p_realtimer.it_value))
timevaladd(&p->p_realtimer.it_value, &delta);
- LEASE_UPDATETIME(delta.tv_sec);
+# ifdef NFS
+ lease_updatetime(delta.tv_sec);
+# endif
splx(s);
resettodr();
}
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 6b958df..938e3df 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -70,7 +70,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <sys/sysctl.h>
diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c
index c88ffe7..303e33b 100644
--- a/sys/kern/subr_diskslice.c
+++ b/sys/kern/subr_diskslice.c
@@ -63,6 +63,7 @@
#include <sys/systm.h>
#include <sys/vnode.h>
+#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#define TRACE(str) do { if (ds_debug) printf str; } while (0)
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index b38e35d..c866f32 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -61,7 +61,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
diff --git a/sys/kern/subr_xxx.c b/sys/kern/subr_xxx.c
index 78e4013..fcb951f 100644
--- a/sys/kern/subr_xxx.c
+++ b/sys/kern/subr_xxx.c
@@ -52,6 +52,17 @@ eopnotsupp()
}
/*
+ * Return error for an inval operation
+ * on a specific object or file type.
+ */
+int
+einval()
+{
+
+ return (EINVAL);
+}
+
+/*
* Generic null operation, always returns success.
*/
int
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 9ad0a61..6d9a566 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -73,7 +73,7 @@
#include <vm/vm.h>
#include <vm/vm_prot.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_object.h>
#include <vm/vm_kern.h>
#include <vm/vm_extern.h>
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index b64f1e6..72e95e7 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -45,7 +45,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index e0c707d..2afd2b4 100644
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -227,7 +227,7 @@ char *syscallnames[] = {
"mlock", /* 203 = mlock */
"munlock", /* 204 = munlock */
"utrace", /* 205 = utrace */
- "#206", /* 206 = nosys */
+ "undelete", /* 206 = undelete */
"#207", /* 207 = nosys */
"#208", /* 208 = nosys */
"#209", /* 209 = nosys */
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 896f846..cacaf42 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -60,7 +60,7 @@
int flags); }
19 COMPAT POSIX { long lseek(int fd, long offset, int whence); }
20 STD POSIX { pid_t getpid(void); }
-21 STD BSD { int mount(int type, char *path, int flags, \
+21 STD BSD { int mount(char *type, char *path, int flags, \
caddr_t data); }
; XXX 4.4lite2 uses `char *type' but we're not ready for that.
; XXX `path' should have type `const char *' but we're not ready for that.
@@ -111,7 +111,7 @@
57 STD POSIX { int symlink(char *path, char *link); }
58 STD POSIX { int readlink(char *path, char *buf, int count); }
59 STD POSIX { int execve(char *fname, char **argv, char **envv); }
-60 STD POSIX { int umask(int newmask); } umask umask_args mode_t
+60 STD POSIX { int umask(int newmask); } umask umask_args int
61 STD BSD { int chroot(char *path); }
62 COMPAT POSIX { int fstat(int fd, struct ostat *sb); }
63 COMPAT BSD { int getkerninfo(int op, char *where, int *size, \
@@ -328,7 +328,7 @@
203 STD BSD { int mlock(caddr_t addr, size_t len); }
204 STD BSD { int munlock(caddr_t addr, size_t len); }
205 STD BSD { int utrace(caddr_t addr, size_t len); }
-206 UNIMPL NOHIDE nosys
+206 STD BSD { int undelete(char *path); }
207 UNIMPL NOHIDE nosys
208 UNIMPL NOHIDE nosys
209 UNIMPL NOHIDE nosys
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index f02a785..b777250 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -48,7 +48,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_object.h>
#include <vm/vm_map.h>
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 47707db..06ce568 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -94,7 +94,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c
index 770b66e..b6e3fda 100644
--- a/sys/kern/tty_tty.c
+++ b/sys/kern/tty_tty.c
@@ -78,7 +78,7 @@ cttyopen(dev, flag, mode, p)
if (ttyvp == NULL)
return (ENXIO);
- VOP_LOCK(ttyvp);
+ vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p);
#ifdef PARANOID
/*
* Since group is tty and mode is 620 on most terminal lines
@@ -93,7 +93,7 @@ cttyopen(dev, flag, mode, p)
if (!error)
#endif /* PARANOID */
error = VOP_OPEN(ttyvp, flag, NOCRED, p);
- VOP_UNLOCK(ttyvp);
+ VOP_UNLOCK(ttyvp, 0, p);
return (error);
}
@@ -104,14 +104,15 @@ cttyread(dev, uio, flag)
struct uio *uio;
int flag;
{
- register struct vnode *ttyvp = cttyvp(uio->uio_procp);
+ struct proc *p = uio->uio_procp;
+ register struct vnode *ttyvp = cttyvp(p);
int error;
if (ttyvp == NULL)
return (EIO);
- VOP_LOCK(ttyvp);
+ vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_READ(ttyvp, uio, flag, NOCRED);
- VOP_UNLOCK(ttyvp);
+ VOP_UNLOCK(ttyvp, 0, p);
return (error);
}
@@ -122,14 +123,15 @@ cttywrite(dev, uio, flag)
struct uio *uio;
int flag;
{
- register struct vnode *ttyvp = cttyvp(uio->uio_procp);
+ struct proc *p = uio->uio_procp;
+ struct vnode *ttyvp = cttyvp(uio->uio_procp);
int error;
if (ttyvp == NULL)
return (EIO);
- VOP_LOCK(ttyvp);
+ vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
- VOP_UNLOCK(ttyvp);
+ VOP_UNLOCK(ttyvp, 0, p);
return (error);
}
@@ -195,5 +197,3 @@ ctty_drvinit(void *unused)
}
SYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL)
-
-
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 2017de9..bfbb3c6 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -436,7 +436,7 @@ unp_bind(unp, nam, p)
struct nameidata nd;
NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
- soun->sun_path, p);
+ soun->sun_path, p);
if (unp->unp_vnode != NULL)
return (EINVAL);
if (nam->m_len == MLEN) {
@@ -461,15 +461,14 @@ unp_bind(unp, nam, p)
VATTR_NULL(&vattr);
vattr.va_type = VSOCK;
vattr.va_mode = ACCESSPERMS;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
- if (error)
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr))
return (error);
vp = nd.ni_vp;
vp->v_socket = unp->unp_socket;
unp->unp_vnode = vp;
unp->unp_addr = m_copy(nam, 0, (int)M_COPYALL);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (0);
}
@@ -888,7 +887,7 @@ unp_gc()
for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
sorflush((struct socket *)(*fpp)->f_data);
for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
- closef(*fpp,(struct proc*) NULL);
+ closef(*fpp, (struct proc *) NULL);
free((caddr_t)extra_ref, M_FILE);
unp_gcing = 0;
}
@@ -897,6 +896,7 @@ void
unp_dispose(m)
struct mbuf *m;
{
+
if (m)
unp_scan(m, unp_discard);
}
@@ -904,7 +904,7 @@ unp_dispose(m)
static void
unp_scan(m0, op)
register struct mbuf *m0;
- void (*op)(struct file *);
+ void (*op) __P((struct file *));
{
register struct mbuf *m;
register struct file **rp;
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index bee702d..718c4a3 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -1,8 +1,9 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
- * Copyright (c) 1995
- * Poul-Henning Kamp. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Poul-Henning Kamp of the FreeBSD Project.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -58,9 +59,8 @@
* obtained from (vp, name) where vp refers to the directory
* containing name.
*
- * If it is a "negative" entry, (that we know a name to >not< exist)
- * we point out entry at our own "nchENOENT", to avoid too much special
- * casing in the inner loops of lookup.
+ * If it is a "negative" entry, (i.e. for a name that is known NOT to
+ * exist) the vnode pointer will be NULL.
*
* For simplicity (and economy of storage), names longer than
* a maximum length of NCHNAMLEN are not cached; they occur
@@ -74,15 +74,15 @@
/*
* Structures associated with name cacheing.
*/
+#define NCHHASH(dvp, cnp) \
+ (&nchashtbl[((dvp)->v_id + (cnp)->cn_hash) & nchash])
static LIST_HEAD(nchashhead, namecache) *nchashtbl; /* Hash Table */
-static TAILQ_HEAD(, namecache) nclruhead; /* LRU chain */
-static u_long nchash; /* size of hash table */
-struct nchstats nchstats; /* cache effectiveness statistics */
-static struct vnode nchENOENT; /* our own "novnode" */
-static int doingcache = 1; /* 1 => enable the cache */
+static u_long nchash; /* size of hash table - 1 */
+static int doingcache = 1; /* 1 => enable the cache */
SYSCTL_INT(_debug, OID_AUTO, vfscache, CTLFLAG_RW, &doingcache, 0, "");
-static u_long numcache;
-u_long numvnodes;
+static u_long numcache; /* number of cache entries allocated */
+static TAILQ_HEAD(, namecache) nclruhead; /* LRU chain */
+struct nchstats nchstats; /* cache effectiveness statistics */
#ifdef NCH_STATISTICS
u_long nchnbr;
@@ -93,32 +93,42 @@ u_long nchnbr;
#define NCHHIT(ncp)
#endif
+/*
+ * Delete an entry from its hash list and move it to the front
+ * of the LRU list for immediate reuse.
+ */
#define PURGE(ncp) { \
LIST_REMOVE(ncp, nc_hash); \
ncp->nc_hash.le_prev = 0; \
TAILQ_REMOVE(&nclruhead, ncp, nc_lru); \
- TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru); }
+ TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru); \
+}
+/*
+ * Move an entry that has been used to the tail of the LRU list
+ * so that it will be preserved for future use.
+ */
#define TOUCH(ncp) { \
- if (ncp->nc_lru.tqe_next == 0) { } else { \
+ if (ncp->nc_lru.tqe_next != 0) { \
TAILQ_REMOVE(&nclruhead, ncp, nc_lru); \
TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru); \
- NCHNBR(ncp); } }
+ NCHNBR(ncp); \
+ } \
+}
/*
- * Lookup an entry in the cache
+ * Lookup an entry in the cache
*
- * We don't do this if the segment name is long, simply so the cache
+ * We don't do this if the segment name is long, simply so the cache
* can avoid holding long names (which would either waste space, or
* add greatly to the complexity).
*
* Lookup is called with dvp pointing to the directory to search,
- * cnp pointing to the name of the entry being sought.
- * If the lookup succeeds, the vnode is returned in *vpp, and a status
- * of -1 is returned.
- * If the lookup determines that the name does not exist (negative cacheing),
- * a status of ENOENT is returned.
- * If the lookup fails, a status of zero is returned.
+ * cnp pointing to the name of the entry being sought. If the lookup
+ * succeeds, the vnode is returned in *vpp, and a status of -1 is
+ * returned. If the lookup determines that the name does not exist
+ * (negative cacheing), a status of ENOENT is returned. If the lookup
+ * fails, a status of zero is returned.
*/
int
@@ -127,7 +137,7 @@ cache_lookup(dvp, vpp, cnp)
struct vnode **vpp;
struct componentname *cnp;
{
- register struct namecache *ncp,*nnp;
+ register struct namecache *ncp, *nnp;
register struct nchashhead *ncpp;
if (!doingcache) {
@@ -141,12 +151,12 @@ cache_lookup(dvp, vpp, cnp)
return (0);
}
- ncpp = &nchashtbl[(dvp->v_id + cnp->cn_hash) % nchash];
+ ncpp = NCHHASH(dvp, cnp);
for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) {
nnp = ncp->nc_hash.le_next;
/* If one of the vp's went stale, don't bother anymore. */
if ((ncp->nc_dvpid != ncp->nc_dvp->v_id) ||
- (ncp->nc_vpid != ncp->nc_vp->v_id)) {
+ (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id)) {
nchstats.ncs_falsehits++;
PURGE(ncp);
continue;
@@ -155,12 +165,15 @@ cache_lookup(dvp, vpp, cnp)
if (ncp->nc_dvp == dvp &&
ncp->nc_nlen == cnp->cn_namelen &&
!bcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen))
- goto found; /* Fanatism considered bad. */
+ break;
+ }
+
+ /* We failed to find an entry */
+ if (ncp == 0) {
+ nchstats.ncs_miss++;
+ return (0);
}
- nchstats.ncs_miss++;
- return (0);
- found:
NCHHIT(ncp);
/* We don't want to have an entry, so dump it */
@@ -168,10 +181,10 @@ cache_lookup(dvp, vpp, cnp)
nchstats.ncs_badhits++;
PURGE(ncp);
return (0);
- }
+ }
/* We found a "positive" match, return the vnode */
- if (ncp->nc_vp != &nchENOENT) {
+ if (ncp->nc_vp) {
nchstats.ncs_goodhits++;
TOUCH(ncp);
*vpp = ncp->nc_vp;
@@ -187,16 +200,19 @@ cache_lookup(dvp, vpp, cnp)
return (0);
}
- /* The name does not exists */
+ /*
+ * We found a "negative" match, ENOENT notifies client of this match.
+ * The nc_vpid field records whether this is a whiteout.
+ */
nchstats.ncs_neghits++;
TOUCH(ncp);
+ cnp->cn_flags |= ncp->nc_vpid;
return (ENOENT);
}
/*
* Add an entry to the cache.
*/
-
void
cache_enter(dvp, vp, cnp)
struct vnode *dvp;
@@ -209,12 +225,21 @@ cache_enter(dvp, vp, cnp)
if (!doingcache)
return;
+#ifdef DIAGNOSTIC
if (cnp->cn_namelen > NCHNAMLEN) {
printf("cache_enter: name too long");
return;
}
+#endif
- if (numcache < numvnodes) {
+ /*
+ * We allocate a new entry if we are less than the maximum
+ * allowed and the one at the front of the LRU list is in use.
+ * Otherwise we use the one at the front of the LRU list.
+ */
+ if (numcache < desiredvnodes &&
+ ((ncp = nclruhead.tqh_first) == NULL ||
+ ncp->nc_hash.le_prev != 0)) {
/* Add one more entry */
ncp = (struct namecache *)
malloc((u_long)sizeof *ncp, M_CACHE, M_WAITOK);
@@ -231,52 +256,51 @@ cache_enter(dvp, vp, cnp)
/* give up */
return;
}
-
- /* If vp is NULL this is a "negative" cache entry */
- if (!vp)
- vp = &nchENOENT;
-
- /* fill in cache info */
+ /*
+ * Fill in cache info, if vp is NULL this is a "negative" cache entry.
+ * For negative entries, we have to record whether it is a whiteout.
+ * the whiteout flag is stored in the nc_vpid field which is
+ * otherwise unused.
+ */
ncp->nc_vp = vp;
- if (vp->v_usage < MAXVNODEUSE)
- ++vp->v_usage;
- ncp->nc_vpid = vp->v_id;
+ if (vp) {
+ ncp->nc_vpid = vp->v_id;
+ if (vp->v_usage < MAXVNODEUSE)
+ ++vp->v_usage;
+ } else
+ ncp->nc_vpid = cnp->cn_flags & ISWHITEOUT;
ncp->nc_dvp = dvp;
ncp->nc_dvpid = dvp->v_id;
ncp->nc_nlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, ncp->nc_name, (unsigned)ncp->nc_nlen);
TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
- ncpp = &nchashtbl[(dvp->v_id + cnp->cn_hash) % nchash];
+ ncpp = NCHHASH(dvp, cnp);
LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
}
/*
* Name cache initialization, from vfs_init() when we are booting
*/
-
void
nchinit()
{
-
TAILQ_INIT(&nclruhead);
nchashtbl = phashinit(desiredvnodes, M_CACHE, &nchash);
- cache_purge(&nchENOENT); /* Initialize v_id */
}
/*
- * Invalidate all entries to a particular vnode.
- *
- * We actually just increment the v_id, that will do it. The stale entries
- * will be purged by lookup as they get found.
- * If the v_id wraps around, we need to ditch the entire cache, to avoid
- * confusion.
- * No valid vnode will ever have (v_id == 0).
+ * Invalidate all entries to particular vnode.
+ *
+ * We actually just increment the v_id, that will do it. The stale entries
+ * will be purged by lookup as they get found. If the v_id wraps around, we
+ * need to ditch the entire cache, to avoid confusion. No valid vnode will
+ * ever have (v_id == 0).
*/
-
void
cache_purge(vp)
struct vnode *vp;
{
+ struct namecache *ncp;
struct nchashhead *ncpp;
static u_long nextvnodeid;
@@ -284,10 +308,9 @@ cache_purge(vp)
if (nextvnodeid != 0)
return;
for (ncpp = &nchashtbl[nchash - 1]; ncpp >= nchashtbl; ncpp--) {
- while(ncpp->lh_first)
- PURGE(ncpp->lh_first);
+ while (ncp = ncpp->lh_first)
+ PURGE(ncp);
}
- nchENOENT.v_id = ++nextvnodeid;
vp->v_id = ++nextvnodeid;
}
@@ -296,29 +319,22 @@ cache_purge(vp)
*
* Since we need to check it anyway, we will flush all the invalid
* entries at the same time.
- *
- * If we purge anything, we scan the hash-bucket again. There is only
- * a handful of entries, so it cheap and simple.
*/
-
void
cache_purgevfs(mp)
struct mount *mp;
{
struct nchashhead *ncpp;
- struct namecache *ncp;
+ struct namecache *ncp, *nnp;
/* Scan hash tables for applicable entries */
for (ncpp = &nchashtbl[nchash - 1]; ncpp >= nchashtbl; ncpp--) {
- ncp = ncpp->lh_first;
- while(ncp) {
+ for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) {
+ nnp = ncp->nc_hash.le_next;
if (ncp->nc_dvpid != ncp->nc_dvp->v_id ||
- ncp->nc_vpid != ncp->nc_vp->v_id ||
+ (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id) ||
ncp->nc_dvp->v_mount == mp) {
PURGE(ncp);
- ncp = ncpp->lh_first;
- } else {
- ncp = ncp->nc_hash.le_next;
}
}
}
diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c
index fb8061b..5a84570 100644
--- a/sys/kern/vfs_conf.c
+++ b/sys/kern/vfs_conf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
* Copyright (c) 1995 Artisoft, Inc. All Rights Reserved.
*
@@ -61,26 +61,33 @@
/*
* GLOBALS
*/
-int (*mountroot) __P((void *));
+
+/*
+ * These define the root filesystem, device, and root filesystem type.
+ */
+struct mount *rootfs;
struct vnode *rootvnode;
-struct vfsops *mountrootvfsops;
+char *mountrootfsname;
+/*
+ * vfs_init() will set maxvfsconf
+ * to the highest defined type number.
+ */
+int maxvfsconf;
+struct vfsconf *vfsconf;
/*
* Common root mount code shared by all filesystems
*/
-#define ROOTDIR "/"
#define ROOTNAME "root_device"
-
-
/*
- * vfs_mountroot
+ * vfs_mountrootfs
*
* Common entry point for root mounts
*
* PARAMETERS:
- * data pointer to the vfs_ops for the FS type mounting
+ * fsname name of the filesystem
*
* RETURNS: 0 Success
* !0 error number (errno.h)
@@ -97,67 +104,44 @@ struct vfsops *mountrootvfsops;
* fixing the other file systems, not this code!
*/
int
-vfs_mountroot(data)
- void *data;
+vfs_mountrootfs(fsname)
+ char *fsname;
{
struct mount *mp;
- u_int size;
int err = 0;
struct proc *p = curproc; /* XXX */
- struct vfsops *mnt_op = (struct vfsops *)data;
/*
* New root mount structure
*/
- mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = mnt_op;
- mp->mnt_flag = MNT_ROOTFS;
- mp->mnt_vnodecovered = NULLVP;
-
- /*
- * Lock mount point
- */
- if( ( err = vfs_lock(mp)) != 0)
- goto error_1;
-
- /* Save "last mounted on" info for mount point (NULL pad)*/
- copystr( ROOTDIR, /* mount point*/
- mp->mnt_stat.f_mntonname, /* save area*/
- MNAMELEN - 1, /* max size*/
- &size); /* real size*/
- bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
-
- /* Save "mounted from" info for mount point (NULL pad)*/
- copystr( ROOTNAME, /* device name*/
- mp->mnt_stat.f_mntfromname, /* save area*/
- MNAMELEN - 1, /* max size*/
- &size); /* real size*/
- bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+ err = vfs_rootmountalloc(fsname, ROOTNAME, &mp);
+ if (err)
+ return (err);
+ mp->mnt_flag |= MNT_ROOTFS;
/*
* Attempt the mount
*/
- err = VFS_MOUNT( mp, NULL, NULL, NULL, p);
- if( err)
+ err = VFS_MOUNT(mp, NULL, NULL, NULL, p);
+ if (err)
goto error_2;
+ simple_lock(&mountlist_slock);
/* Add fs to list of mounted file systems*/
- CIRCLEQ_INSERT_TAIL( &mountlist, mp, mnt_list);
+ CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
- /* Unlock mount point*/
- vfs_unlock(mp);
+ vfs_unbusy(mp, p);
/* root mount, update system time from FS specific data*/
- inittodr( mp->mnt_time);
+ inittodr(mp->mnt_time);
goto success;
error_2: /* mount error*/
- /* unlock before failing*/
- vfs_unlock( mp);
+ vfs_unbusy(mp, p);
error_1: /* lock error*/
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 43f8669..0dea7bd 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94
+ * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
* $FreeBSD$
*/
@@ -75,7 +75,9 @@
#ifdef DDB
extern void printlockedvnodes __P((void));
#endif
-extern void vclean __P((struct vnode *vp, int flags));
+static void vclean __P((struct vnode *vp, int flags, struct proc *p));
+extern void vgonel __P((struct vnode *vp, struct proc *p));
+unsigned long numvnodes;
extern void vfs_unmountroot __P((struct mount *rootfs));
enum vtype iftovt_tab[16] = {
@@ -91,15 +93,19 @@ int vttoif_tab[9] = {
* Insq/Remq for the vnode usage lists.
*/
#define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs)
-#define bufremvn(bp) { \
- LIST_REMOVE(bp, b_vnbufs); \
- (bp)->b_vnbufs.le_next = NOLIST; \
+#define bufremvn(bp) { \
+ LIST_REMOVE(bp, b_vnbufs); \
+ (bp)->b_vnbufs.le_next = NOLIST; \
}
-
TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */
static u_long freevnodes = 0;
struct mntlist mountlist; /* mounted filesystem list */
+struct simplelock mountlist_slock;
+static struct simplelock mntid_slock;
+struct simplelock mntvnode_slock;
+struct simplelock vnode_free_list_slock;
+static struct simplelock spechash_slock;
int desiredvnodes;
SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RW, &desiredvnodes, 0, "");
@@ -117,164 +123,153 @@ vntblinit()
{
desiredvnodes = maxproc + vm_object_cache_max;
+ simple_lock_init(&mntvnode_slock);
+ simple_lock_init(&mntid_slock);
+ simple_lock_init(&spechash_slock);
TAILQ_INIT(&vnode_free_list);
+ simple_lock_init(&vnode_free_list_slock);
CIRCLEQ_INIT(&mountlist);
}
/*
- * Lock a filesystem.
- * Used to prevent access to it while mounting and unmounting.
+ * Mark a mount point as busy. Used to synchronize access and to delay
+ * unmounting. Interlock is not released on failure.
*/
int
-vfs_lock(mp)
- register struct mount *mp;
+vfs_busy(mp, flags, interlkp, p)
+ struct mount *mp;
+ int flags;
+ struct simplelock *interlkp;
+ struct proc *p;
{
+ int lkflags;
- while (mp->mnt_flag & MNT_MLOCK) {
+ if (mp->mnt_flag & MNT_UNMOUNT) {
+ if (flags & LK_NOWAIT)
+ return (ENOENT);
mp->mnt_flag |= MNT_MWAIT;
- (void) tsleep((caddr_t) mp, PVFS, "vfslck", 0);
+ 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.
+ */
+ tsleep((caddr_t)mp, PVFS, "vfs_busy", 0);
+ if (interlkp) {
+ simple_lock(interlkp);
+ }
+ return (ENOENT);
}
- mp->mnt_flag |= MNT_MLOCK;
+ lkflags = LK_SHARED;
+ if (interlkp)
+ lkflags |= LK_INTERLOCK;
+ if (lockmgr(&mp->mnt_lock, lkflags, interlkp, p))
+ panic("vfs_busy: unexpected lock failure");
return (0);
}
/*
- * Unlock a locked filesystem.
- * Panic if filesystem is not locked.
+ * Free a busy filesystem.
*/
void
-vfs_unlock(mp)
- register struct mount *mp;
+vfs_unbusy(mp, p)
+ struct mount *mp;
+ struct proc *p;
{
- if ((mp->mnt_flag & MNT_MLOCK) == 0)
- panic("vfs_unlock: not locked");
- mp->mnt_flag &= ~MNT_MLOCK;
- if (mp->mnt_flag & MNT_MWAIT) {
- mp->mnt_flag &= ~MNT_MWAIT;
- wakeup((caddr_t) mp);
- }
+ lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, p);
}
/*
- * Mark a mount point as busy.
- * Used to synchronize access and to delay unmounting.
+ * 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_busy(mp)
- register struct mount *mp;
+vfs_rootmountalloc(fstypename, devname, mpp)
+ char *fstypename;
+ char *devname;
+ struct mount **mpp;
{
+ struct proc *p = curproc; /* XXX */
+ struct vfsconf *vfsp;
+ struct mount *mp;
- while (mp->mnt_flag & MNT_MPBUSY) {
- mp->mnt_flag |= MNT_MPWANT;
- (void) tsleep((caddr_t) &mp->mnt_flag, PVFS, "vfsbsy", 0);
- }
- if (mp->mnt_flag & MNT_UNMOUNT)
- return (1);
- mp->mnt_flag |= MNT_MPBUSY;
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (!strcmp(vfsp->vfc_name, fstypename))
+ break;
+ if (vfsp == NULL)
+ return (ENODEV);
+ mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
+ bzero((char *)mp, (u_long)sizeof(struct mount));
+ lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
+ (void)vfs_busy(mp, LK_NOWAIT, 0, p);
+ LIST_INIT(&mp->mnt_vnodelist);
+ mp->mnt_vfc = vfsp;
+ mp->mnt_op = vfsp->vfc_vfsops;
+ mp->mnt_flag = MNT_RDONLY;
+ mp->mnt_vnodecovered = NULLVP;
+ vfsp->vfc_refcount++;
+ mp->mnt_stat.f_type = vfsp->vfc_typenum;
+ mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
+ strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
+ mp->mnt_stat.f_mntonname[0] = '/';
+ mp->mnt_stat.f_mntonname[1] = 0;
+ (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0);
+ *mpp = mp;
return (0);
}
/*
- * Free a busy filesystem.
- * Panic if filesystem is not busy.
- */
-void
-vfs_unbusy(mp)
- register 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);
- }
-}
-
-void
-vfs_unmountroot(struct mount *rootfs)
-{
- struct mount *mp = rootfs;
- int error;
-
- if (vfs_busy(mp)) {
- printf("failed to unmount root\n");
- return;
- }
- mp->mnt_flag |= MNT_UNMOUNT;
- if ((error = vfs_lock(mp))) {
- printf("lock of root filesystem failed (%d)\n", error);
- return;
- }
- vnode_pager_umount(mp); /* release cached vnodes */
- cache_purgevfs(mp); /* remove cache entries for this file sys */
-
- if ((error = VFS_SYNC(mp, MNT_WAIT, initproc->p_ucred, initproc)))
- printf("sync of root filesystem failed (%d)\n", error);
-
- if ((error = VFS_UNMOUNT(mp, MNT_FORCE, initproc))) {
- printf("unmount of root filesystem failed (");
- if (error == EBUSY)
- printf("BUSY)\n");
- else
- printf("%d)\n", error);
- }
- mp->mnt_flag &= ~MNT_UNMOUNT;
- vfs_unbusy(mp);
-}
-
-/*
- * Unmount all filesystems. Should only be called by halt().
+ * Find an appropriate filesystem to use for the root. If a filesystem
+ * has not been preselected, walk through the list of known filesystems
+ * trying those that have mountroot routines, and try them until one
+ * works or we have tried them all.
*/
-void
-vfs_unmountall()
+#ifdef notdef /* XXX JH */
+int
+lite2_vfs_mountroot(void)
{
- struct mount *mp, *nmp, *rootfs = NULL;
+ struct vfsconf *vfsp;
+ extern int (*lite2_mountroot)(void);
int error;
- /* unmount all but rootfs */
- for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
- nmp = mp->mnt_list.cqe_prev;
-
- if (mp->mnt_flag & MNT_ROOTFS) {
- rootfs = mp;
+ if (lite2_mountroot != NULL)
+ return ((*lite2_mountroot)());
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
+ if (vfsp->vfc_mountroot == NULL)
continue;
- }
- error = dounmount(mp, MNT_FORCE, initproc);
- if (error) {
- printf("unmount of %s failed (", mp->mnt_stat.f_mntonname);
- if (error == EBUSY)
- printf("BUSY)\n");
- else
- printf("%d)\n", error);
- }
- }
-
- /* and finally... */
- if (rootfs) {
- vfs_unmountroot(rootfs);
- } else {
- printf("no root filesystem\n");
+ if ((error = (*vfsp->vfc_mountroot)()) == 0)
+ return (0);
+ printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error);
}
+ return (ENODEV);
}
+#endif
/*
* 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) {
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);
}
@@ -282,14 +277,16 @@ getvfs(fsid)
* Get a new unique fsid
*/
void
-getnewfsid(mp, mtype)
+vfs_getnewfsid(mp)
struct mount *mp;
- int mtype;
{
static u_short xxxfs_mntid;
fsid_t tfsid;
+ int mtype;
+ simple_lock(&mntid_slock);
+ mtype = mp->mnt_vfc->vfc_typenum;
mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
mp->mnt_stat.f_fsid.val[1] = mtype;
if (xxxfs_mntid == 0)
@@ -297,12 +294,13 @@ getnewfsid(mp, mtype)
tfsid.val[0] = makedev(nblkdev + mtype, 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);
}
/*
@@ -326,6 +324,35 @@ vattr_null(vap)
vap->va_vaflags = 0;
}
+void
+vfs_unmountroot(struct mount *rootfs)
+{
+ struct proc *p = curproc; /* XXX */
+ struct mount *mp = rootfs;
+ int error;
+
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ printf("failed to unmount root\n");
+ return;
+ }
+ mp->mnt_flag |= MNT_UNMOUNT;
+ vnode_pager_umount(mp); /* release cached vnodes */
+ cache_purgevfs(mp); /* remove cache entries for this file sys */
+
+ if ((error = VFS_SYNC(mp, MNT_WAIT, initproc->p_ucred, initproc)))
+ printf("sync of root filesystem failed (%d)\n", error);
+
+ if ((error = VFS_UNMOUNT(mp, MNT_FORCE, initproc))) {
+ printf("unmount of root filesystem failed (");
+ if (error == EBUSY)
+ printf("BUSY)\n");
+ else
+ printf("%d)\n", error);
+ }
+ mp->mnt_flag &= ~MNT_UNMOUNT;
+ vfs_unbusy(mp, p);
+}
+
/*
* Routines having to do with the management of the vnode table.
*/
@@ -341,10 +368,11 @@ getnewvnode(tag, mp, vops, vpp)
vop_t **vops;
struct vnode **vpp;
{
- register struct vnode *vp;
+ struct proc *p = curproc; /* XXX */
+ struct vnode *vp;
+ simple_lock(&vnode_free_list_slock);
retry:
- vp = vnode_free_list.tqh_first;
/*
* we allocate a new vnode if
* 1. we don't have any free
@@ -357,12 +385,31 @@ retry:
*/
if (freevnodes < (numvnodes >> 2) ||
numvnodes < desiredvnodes ||
- vp == NULL) {
+ vnode_free_list.tqh_first == NULL) {
+ 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 {
+ 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)
+ panic("free vnode isn't");
TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
if (vp->v_usage > 0) {
--vp->v_usage;
@@ -370,14 +417,16 @@ retry:
goto retry;
}
freevnodes--;
- if (vp->v_usecount)
- panic("free vnode isn't");
/* 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
{
@@ -421,6 +470,7 @@ insmntque(vp, mp)
register struct mount *mp;
{
+ simple_lock(&mntvnode_slock);
/*
* Delete from old mount point vnode list, if on one.
*/
@@ -429,9 +479,12 @@ insmntque(vp, mp)
/*
* Insert into list of vnodes for the new mount point, if available.
*/
- if ((vp->v_mount = mp) == NULL)
+ if ((vp->v_mount = mp) == NULL) {
+ simple_unlock(&mntvnode_slock);
return;
+ }
LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
+ simple_unlock(&mntvnode_slock);
}
/*
@@ -723,7 +776,8 @@ checkalias(nvp, nvp_rdev, mp)
dev_t nvp_rdev;
struct mount *mp;
{
- register struct vnode *vp;
+ struct proc *p = curproc; /* XXX */
+ struct vnode *vp;
struct vnode **vpp;
if (nvp->v_type != VBLK && nvp->v_type != VCHR)
@@ -731,18 +785,24 @@ checkalias(nvp, nvp_rdev, mp)
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))
+ simple_unlock(&spechash_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
goto loop;
+ }
+ simple_lock(&spechash_slock);
break;
}
@@ -753,16 +813,19 @@ loop:
nvp->v_hashchain = vpp;
nvp->v_specnext = *vpp;
nvp->v_specflags = 0;
+ simple_unlock(&spechash_slock);
*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, p);
+ 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;
@@ -779,47 +842,162 @@ loop:
* been changed to a new file system type).
*/
int
-vget(vp, lockflag)
+vget(vp, flags, p)
register struct vnode *vp;
- int lockflag;
+ int flags;
+ struct proc *p;
{
+ 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.
+ * If the vnode is in the process of being cleaned out for
+ * another use, we wait for the cleaning to finish and then
+ * return failure. Cleaning is determined by checking that
+ * the VXLOCK flag is set.
*/
- 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;
- (void) tsleep((caddr_t) vp, PINOD, "vget", 0);
- return (1);
+ simple_unlock(&vp->v_interlock);
+ tsleep((caddr_t)vp, PINOD, "vget", 0);
+ return (ENOENT);
}
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);
freevnodes--;
}
vp->v_usecount++;
-
/*
* Create the VM object, if needed
*/
if ((vp->v_type == VREG) &&
((vp->v_object == NULL) ||
(vp->v_object->flags & OBJ_VFS_REF) == 0)) {
+ /*
+ * XXX vfs_object_create probably needs the interlock.
+ */
+ simple_unlock(&vp->v_interlock);
vfs_object_create(vp, curproc, curproc->p_ucred, 0);
+ simple_lock(&vp->v_interlock);
+ }
+ if (flags & LK_TYPE_MASK) {
+ if (error = vn_lock(vp, flags | LK_INTERLOCK, p))
+ vrele(vp);
+ return (error);
}
- if (lockflag)
- VOP_LOCK(vp);
+ simple_unlock(&vp->v_interlock);
+ return (0);
+}
+
+/*
+ * Stubs to use when there is no locking to be done on the underlying object.
+ * A minimal shared lock is necessary to ensure that the underlying object
+ * is not revoked while an operation is in progress. So, an active shared
+ * count is maintained in an auxillary vnode lock structure.
+ */
+int
+vop_nolock(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+#ifdef notyet
+ /*
+ * This code cannot be used until all the non-locking filesystems
+ * (notably NFS) are converted to properly lock and release nodes.
+ * Also, certain vnode operations change the locking state within
+ * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
+ * and symlink). Ideally these operations should not change the
+ * lock state, but should be changed to let the caller of the
+ * function unlock them. Otherwise all intermediate vnode layers
+ * (such as union, umapfs, etc) must catch these functions to do
+ * the necessary locking at their layer. Note that the inactive
+ * and lookup operations also change their lock state, but this
+ * cannot be avoided, so these two operations will always need
+ * to be handled in intermediate layers.
+ */
+ struct vnode *vp = ap->a_vp;
+ int vnflags, flags = ap->a_flags;
+ if (vp->v_vnlock == NULL) {
+ if ((flags & LK_TYPE_MASK) == LK_DRAIN)
+ return (0);
+ MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
+ M_VNODE, M_WAITOK);
+ lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
+ }
+ switch (flags & LK_TYPE_MASK) {
+ case LK_DRAIN:
+ vnflags = LK_DRAIN;
+ break;
+ case LK_EXCLUSIVE:
+ case LK_SHARED:
+ vnflags = LK_SHARED;
+ break;
+ case LK_UPGRADE:
+ case LK_EXCLUPGRADE:
+ case LK_DOWNGRADE:
+ return (0);
+ case LK_RELEASE:
+ default:
+ panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
+ }
+ if (flags & LK_INTERLOCK)
+ vnflags |= LK_INTERLOCK;
+ return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
+#else /* for now */
+ /*
+ * Since we are not using the lock manager, we must clear
+ * the interlock here.
+ */
+ if (ap->a_flags & LK_INTERLOCK) {
+ simple_unlock(&ap->a_vp->v_interlock);
+ }
return (0);
+#endif
+}
+
+/*
+ * Decrement the active use count.
+ */
+int
+vop_nounlock(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ if (vp->v_vnlock == NULL)
+ return (0);
+ return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p));
+}
+
+/*
+ * Return whether or not the node is in use.
+ */
+int
+vop_noislocked(ap)
+ struct vop_islocked_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ if (vp->v_vnlock == NULL)
+ return (0);
+ return (lockstatus(vp->v_vnlock));
}
+/* #ifdef DIAGNOSTIC */
/*
* Vnode reference, just increment the count
*/
@@ -827,6 +1005,7 @@ void
vref(vp)
struct vnode *vp;
{
+ simple_lock(&vp->v_interlock);
if (vp->v_usecount <= 0)
panic("vref used where vget required");
@@ -840,8 +1019,11 @@ vref(vp)
* the object is created. This is necessary to
* keep the system from re-entrantly doing it
* multiple times.
+ * XXX vfs_object_create probably needs the interlock?
*/
+ simple_unlock(&vp->v_interlock);
vfs_object_create(vp, curproc, curproc->p_ucred, 0);
+ simple_lock(&vp->v_interlock);
}
}
@@ -850,9 +1032,9 @@ vref(vp)
*/
void
vput(vp)
- register struct vnode *vp;
+ struct vnode *vp;
{
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curproc);
vrele(vp);
}
@@ -862,33 +1044,38 @@ vput(vp)
*/
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 == 1) &&
vp->v_object &&
(vp->v_object->flags & OBJ_VFS_REF)) {
vp->v_object->flags &= ~OBJ_VFS_REF;
+ simple_unlock(&vp->v_interlock);
vm_object_deallocate(vp->v_object);
return;
}
- if (vp->v_usecount > 0)
+ if (vp->v_usecount > 0) {
+ simple_unlock(&vp->v_interlock);
return;
+ }
if (vp->v_usecount < 0) {
#ifdef DIAGNOSTIC
vprint("vrele: negative ref count", vp);
#endif
- panic("vrele: negative reference cnt");
+ panic("vrele: negative ref cnt");
}
+ simple_lock(&vnode_free_list_slock);
if (vp->v_flag & VAGE) {
if(vp->v_tag != VT_TFS)
TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
@@ -898,9 +1085,12 @@ vrele(vp)
if(vp->v_tag != VT_TFS)
TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
}
+ simple_unlock(&vnode_free_list_slock);
+
freevnodes++;
- VOP_INACTIVE(vp);
+ if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0)
+ VOP_INACTIVE(vp, p);
}
#ifdef DIAGNOSTIC
@@ -912,7 +1102,9 @@ vhold(vp)
register struct vnode *vp;
{
+ simple_lock(&vp->v_interlock);
vp->v_holdcnt++;
+ simple_unlock(&vp->v_interlock);
}
/*
@@ -923,9 +1115,11 @@ holdrele(vp)
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 */
@@ -948,11 +1142,11 @@ vflush(mp, skipvp, flags)
struct vnode *skipvp;
int flags;
{
- register struct vnode *vp, *nvp;
+ struct proc *p = curproc; /* XXX */
+ 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) {
/*
@@ -967,24 +1161,34 @@ loop:
*/
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.
*/
if ((flags & WRITECLOSE) &&
- (vp->v_writecount == 0 || vp->v_type != VREG))
+ (vp->v_writecount == 0 || vp->v_type != VREG)) {
+ simple_unlock(&vp->v_interlock);
continue;
+ }
if (vp->v_object && (vp->v_object->flags & OBJ_VFS_REF)) {
+ simple_unlock(&vp->v_interlock);
+ simple_unlock(&mntvnode_slock);
vm_object_reference(vp->v_object);
pager_cache(vp->v_object, FALSE);
vp->v_object->flags &= ~OBJ_VFS_REF;
vm_object_deallocate(vp->v_object);
+ simple_lock(&mntvnode_slock);
+ simple_lock(&vp->v_interlock);
}
/*
@@ -992,7 +1196,9 @@ loop:
* 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;
}
@@ -1002,21 +1208,25 @@ loop:
* 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 DIAGNOSTIC
if (busyprt)
vprint("vflush: busy vnode", vp);
#endif
+ simple_unlock(&vp->v_interlock);
busy++;
}
+ simple_unlock(&mntvnode_slock);
if (busy)
return (EBUSY);
return (0);
@@ -1025,8 +1235,8 @@ loop:
/*
* Disassociate the underlying file system from a vnode.
*/
-void
-vclean(struct vnode *vp, int flags)
+static void
+vclean(struct vnode *vp, int flags, struct proc *p)
{
int active;
@@ -1036,15 +1246,7 @@ vclean(struct vnode *vp, int flags)
* generate a race against ourselves to recycle it.
*/
if ((active = vp->v_usecount))
- 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);
+ vp->v_usecount++;
/*
* Prevent the vnode from being recycled or brought into use while we
* clean it out.
@@ -1053,31 +1255,48 @@ vclean(struct vnode *vp, int flags)
panic("vclean: deadlock");
vp->v_flag |= VXLOCK;
/*
- * Clean out any buffers associated with the vnode.
+ * 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.
*/
- if (flags & DOCLOSE)
- vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
+ VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
/*
- * Any other processes trying to obtain this lock must first wait for
- * VXLOCK to clear, then call the new lock operation.
+ * Clean out any buffers associated with the vnode.
*/
- VOP_UNLOCK(vp);
+ if (flags & DOCLOSE)
+ vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
/*
- * If purging an active vnode, it must be closed and deactivated
- * before being reclaimed.
+ * If purging an active vnode, it must be closed and
+ * 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, p);
+ VOP_INACTIVE(vp, p);
+ } else {
+ /*
+ * Any other processes trying to obtain this lock must first
+ * wait for VXLOCK to clear, then call the new lock operation.
+ */
+ VOP_UNLOCK(vp, 0, p);
}
/*
* 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.
@@ -1092,46 +1311,91 @@ vclean(struct vnode *vp, int flags)
}
/*
- * Eliminate all activity associated with the requested vnode
+ * Eliminate all activity associated with the requested vnode
* and with all vnodes aliased to the requested vnode.
*/
-void
-vgoneall(vp)
- register struct vnode *vp;
+int
+vop_revoke(ap)
+ struct vop_revoke_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ } */ *ap;
{
- register struct vnode *vq;
+ struct vnode *vp, *vq;
+ struct proc *p = curproc; /* XXX */
+
+#ifdef DIAGNOSTIC
+ if ((ap->a_flags & REVOKEALL) == 0)
+ panic("vop_revoke");
+#endif
+
+ vp = ap->a_vp;
+ simple_lock(&vp->v_interlock);
if (vp->v_flag & VALIASED) {
/*
- * If a vgone (or vclean) is already in progress, wait until
- * it is done and return.
+ * If a vgone (or vclean) is already in progress,
+ * wait until it is done and return.
*/
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t) vp, PINOD, "vgall", 0);
- return;
+ 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.
+ * 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.
+ * 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;
}
- vgone(vp);
+ vgonel(vp, p);
+ return (0);
+}
+
+/*
+ * Recycle an unused vnode to the front of the free list.
+ * Release the passed interlock if the vnode will be recycled.
+ */
+int
+vrecycle(vp, inter_lkp, p)
+ struct vnode *vp;
+ struct simplelock *inter_lkp;
+ struct proc *p;
+{
+
+ simple_lock(&vp->v_interlock);
+ if (vp->v_usecount == 0) {
+ if (inter_lkp) {
+ simple_unlock(inter_lkp);
+ }
+ vgonel(vp, p);
+ return (1);
+ }
+ simple_unlock(&vp->v_interlock);
+ return (0);
}
/*
@@ -1142,16 +1406,31 @@ void
vgone(vp)
register 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)
+ struct vnode *vp;
+ struct proc *p;
+{
+ struct vnode *vq;
struct vnode *vx;
/*
- * If a vgone (or vclean) is already in progress, wait until it is
- * done and return.
+ * 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;
- (void) tsleep((caddr_t) vp, PINOD, "vgone", 0);
+ simple_unlock(&vp->v_interlock);
+ tsleep((caddr_t)vp, PINOD, "vgone", 0);
return;
}
@@ -1162,18 +1441,18 @@ vgone(vp)
/*
* Clean out the filesystem specific data.
*/
- vclean(vp, DOCLOSE);
+ vclean(vp, DOCLOSE, p);
/*
* Delete from old mount point vnode list, if on one.
*/
- if (vp->v_mount != NULL) {
- LIST_REMOVE(vp, v_mntvnodes);
- vp->v_mount = NULL;
- }
+ if (vp->v_mount != NULL)
+ insmntque(vp, (struct mount *)0);
/*
- * If special device, remove it from special device alias list.
+ * 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 {
@@ -1202,28 +1481,34 @@ vgone(vp)
vx->v_flag &= ~VALIASED;
vp->v_flag &= ~VALIASED;
}
+ simple_unlock(&spechash_slock);
FREE(vp->v_specinfo, M_VNODE);
vp->v_specinfo = NULL;
}
+
/*
- * If it is on the freelist and not already at the head, move it to
- * the head of the list. The test of the back pointer and the
- * reference count of zero is because it will be removed from the free
- * list by getnewvnode, but will not have its reference count
- * incremented until after calling vgone. If the reference count were
- * incremented first, vgone would (incorrectly) try to close the
- * previous instance of the underlying object. So, the back pointer is
- * explicitly set to `0xdeadb' in getnewvnode after removing it from
- * the freelist to ensure that we do not try to move it here.
+ * If it is on the freelist and not already at the head,
+ * move it to the head of the list. The test of the back
+ * pointer and the reference count of zero is because
+ * it will be removed from the free list by getnewvnode,
+ * but will not have its reference count incremented until
+ * after calling vgone. If the reference count were
+ * incremented first, vgone would (incorrectly) try to
+ * close the previous instance of the underlying object.
+ * So, the back pointer is explicitly set to `0xdeadb' in
+ * getnewvnode after removing it from the freelist to ensure
+ * that we do not try to move it here.
*/
- if (vp->v_usecount == 0 &&
- vp->v_freelist.tqe_prev != (struct vnode **) 0xdeadb &&
- vnode_free_list.tqh_first != vp) {
- if(vp->v_tag != VT_TFS) {
+ 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;
}
@@ -1254,7 +1539,7 @@ int
vcount(vp)
register struct vnode *vp;
{
- register struct vnode *vq, *vnext;
+ struct vnode *vq, *vnext;
int count;
loop:
@@ -1354,6 +1639,7 @@ int kinfo_vgetfailed;
static int
sysctl_vnode SYSCTL_HANDLER_ARGS
{
+ struct proc *p = curproc; /* XXX */
register struct mount *mp, *nmp;
struct vnode *vp;
int error;
@@ -1368,7 +1654,7 @@ sysctl_vnode SYSCTL_HANDLER_ARGS
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, p))
continue;
again:
for (vp = mp->mnt_vnodelist.lh_first;
@@ -1386,11 +1672,11 @@ again:
}
if ((error = SYSCTL_OUT(req, &vp, VPTRSZ)) ||
(error = SYSCTL_OUT(req, vp, VNODESZ))) {
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
return (error);
}
}
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
return (0);
@@ -1404,22 +1690,63 @@ SYSCTL_PROC(_kern, KERN_VNODE, vnode, CTLTYPE_OPAQUE|CTLFLAG_RD,
*/
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 (error);
+}
+
+/*
+ * Unmount all filesystems. The list is traversed in reverse order
+ * of mounting to avoid dependencies. Should only be called by halt().
+ */
+void
+vfs_unmountall()
+{
+ struct mount *mp, *nmp, *rootfs = NULL;
+ int error;
+
+ /* unmount all but rootfs */
+ for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
+ nmp = mp->mnt_list.cqe_prev;
+
+ if (mp->mnt_flag & MNT_ROOTFS) {
+ rootfs = mp;
+ continue;
+ }
+ error = dounmount(mp, MNT_FORCE, initproc);
+ if (error) {
+ printf("unmount of %s failed (", mp->mnt_stat.f_mntonname);
+ if (error == EBUSY)
+ printf("BUSY)\n");
+ else
+ printf("%d)\n", error);
+ }
+ }
+
+ /* and finally... */
+ if (rootfs) {
+ vfs_unmountroot(rootfs);
+ } else {
+ printf("no root filesystem\n");
}
- return (0);
}
/*
@@ -1565,8 +1892,8 @@ vfs_export_lookup(mp, nep, nam)
rnh = nep->ne_rtable[saddr->sa_family];
if (rnh != NULL) {
np = (struct netcred *)
- (*rnh->rnh_matchaddr) ((caddr_t) saddr,
- rnh);
+ (*rnh->rnh_matchaddr)((caddr_t)saddr,
+ rnh);
if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
np = NULL;
}
@@ -1580,7 +1907,6 @@ vfs_export_lookup(mp, nep, nam)
return (np);
}
-
/*
* perform msync on all vnodes under a mount point
* the mount point must be locked.
@@ -1639,10 +1965,10 @@ retry:
} else {
if (object->flags & OBJ_DEAD) {
if (waslocked)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
tsleep(object, PVM, "vodead", 0);
if (waslocked)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
goto retry;
}
if ((object->flags & OBJ_VFS_REF) == 0) {
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 22e16d84..83b6dec 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -50,6 +50,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/namei.h>
#include <sys/filedesc.h>
@@ -64,9 +65,11 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
+/* see if this is needed XXX JH
#ifdef UNION
#include <miscfs/union/union.h>
#endif
+*/
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -74,7 +77,8 @@
#include <vm/vm_extern.h>
#include <sys/sysctl.h>
-static int change_dir __P((struct nameidata *ndp, struct proc *p));
+static int change_dir __P((struct nameidata *ndp, struct proc *p));
+static void checkdirs __P((struct vnode *olddp));
/*
* Virtual File System System Calls
@@ -85,7 +89,7 @@ static int change_dir __P((struct nameidata *ndp, struct proc *p));
*/
#ifndef _SYS_SYSPROTO_H_
struct mount_args {
- int type;
+ char *type;
char *path;
int flags;
caddr_t data;
@@ -95,29 +99,32 @@ struct mount_args {
int
mount(p, uap, retval)
struct proc *p;
- register struct mount_args *uap;
- int *retval;
+ register struct mount_args /* {
+ syscallarg(char *) type;
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(caddr_t) data;
+ } */ *uap;
+ register_t *retval;
{
- register struct vnode *vp;
- register struct mount *mp;
+ struct vnode *vp;
+ struct mount *mp;
+ struct vfsconf *vfsp;
int error, flag = 0;
+ struct vattr va;
+ u_long fstypenum;
struct nameidata nd;
+ char fstypename[MFSNAMELEN];
/*
- * Must be super user
- */
- error = suser(p->p_ucred, &p->p_acflag);
- if (error)
- return (error);
- /*
* Get vnode to be covered
*/
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- if (uap->flags & MNT_UPDATE) {
+ if (SCARG(uap, flags) & MNT_UPDATE) {
if ((vp->v_flag & VROOT) == 0) {
vput(vp);
return (EINVAL);
@@ -128,68 +135,135 @@ mount(p, uap, retval)
* We only allow the filesystem to be reloaded if it
* is currently mounted read-only.
*/
- if ((uap->flags & MNT_RELOAD) &&
+ if ((SCARG(uap, flags) & MNT_RELOAD) &&
((mp->mnt_flag & MNT_RDONLY) == 0)) {
vput(vp);
return (EOPNOTSUPP); /* Needs translation */
}
mp->mnt_flag |=
- uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
- VOP_UNLOCK(vp);
+ SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
+ /*
+ * Only root, or the user that did the original mount is
+ * permitted to update it.
+ */
+ if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
+ (error = suser(p->p_ucred, &p->p_acflag))) {
+ vput(vp);
+ return (error);
+ }
+ /*
+ * Do not allow NFS export by non-root users. Silently
+ * enforce MNT_NOSUID and MNT_NODEV for non-root users.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ if (SCARG(uap, flags) & MNT_EXPORTED) {
+ vput(vp);
+ return (EPERM);
+ }
+ SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
+ }
+ if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
+ vput(vp);
+ return (EBUSY);
+ }
+ VOP_UNLOCK(vp, 0, p);
goto update;
}
- error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0);
- if (error)
+ /*
+ * If the user is not root, ensure that they own the directory
+ * onto which we are attempting to mount.
+ */
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
+ (va.va_uid != p->p_ucred->cr_uid &&
+ (error = suser(p->p_ucred, &p->p_acflag)))) {
+ vput(vp);
+ return (error);
+ }
+ /*
+ * Do not allow NFS export by non-root users. Silently
+ * enforce MNT_NOSUID and MNT_NODEV for non-root users.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ if (SCARG(uap, flags) & MNT_EXPORTED) {
+ vput(vp);
+ return (EPERM);
+ }
+ SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
+ }
+ if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
return (error);
if (vp->v_type != VDIR) {
vput(vp);
return (ENOTDIR);
}
- if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
- vput(vp);
- return (ENODEV);
- }
-
+#ifdef COMPAT_43
/*
- * Allocate and initialize the file system.
+ * Historically filesystem types were identified by number. If we
+ * get an integer for the filesystem type instead of a string, we
+ * check to see if it matches one of the historic filesystem types.
*/
- mp = (struct mount *)malloc((u_long)sizeof(struct mount),
- M_MOUNT, M_WAITOK);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = vfssw[uap->type];
- mp->mnt_vfc = vfsconf[uap->type];
- error = vfs_lock(mp);
- if (error) {
- free((caddr_t)mp, M_MOUNT);
+ fstypenum = (u_long)SCARG(uap, type);
+ if (fstypenum < maxvfsconf) {
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (vfsp->vfc_typenum == fstypenum)
+ break;
+ if (vfsp == NULL) {
+ vput(vp);
+ return (ENODEV);
+ }
+ strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
+ } else
+#endif /* COMPAT_43 */
+ if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) {
vput(vp);
return (error);
}
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (!strcmp(vfsp->vfc_name, fstypename))
+ break;
+ if (vfsp == NULL) {
+ vput(vp);
+ return (ENODEV);
+ }
if (vp->v_mountedhere != NULL) {
- vfs_unlock(mp);
- free((caddr_t)mp, M_MOUNT);
vput(vp);
return (EBUSY);
}
+
+ /*
+ * Allocate and initialize the filesystem.
+ */
+ 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, p);
+ mp->mnt_op = vfsp->vfc_vfsops;
+ mp->mnt_vfc = vfsp;
+ vfsp->vfc_refcount++;
+ mp->mnt_stat.f_type = vfsp->vfc_typenum;
+ mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
+ strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
vp->v_mountedhere = mp;
mp->mnt_vnodecovered = vp;
- vfsconf[uap->type]->vfc_refcount++;
-
+ mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
update:
/*
* Set the mount level flags.
*/
- if (uap->flags & MNT_RDONLY)
+ if (SCARG(uap, flags) & MNT_RDONLY)
mp->mnt_flag |= MNT_RDONLY;
else if (mp->mnt_flag & MNT_RDONLY)
mp->mnt_flag |= MNT_WANTRDWR;
mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME);
- mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
- MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | MNT_NOATIME);
+ mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
+ MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
+ MNT_NOATIME);
/*
* Mount the filesystem.
*/
- error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
+ error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
if (mp->mnt_flag & MNT_UPDATE) {
vrele(vp);
if (mp->mnt_flag & MNT_WANTRDWR)
@@ -198,6 +272,7 @@ update:
(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
if (error)
mp->mnt_flag = flag;
+ vfs_unbusy(mp, p);
return (error);
}
/*
@@ -205,23 +280,63 @@ update:
*/
cache_purge(vp);
if (!error) {
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
- VOP_UNLOCK(vp);
- vfs_unlock(mp);
- error = VFS_START(mp, 0, p);
- if (error)
+ simple_unlock(&mountlist_slock);
+ checkdirs(vp);
+ VOP_UNLOCK(vp, 0, p);
+ vfs_unbusy(mp, p);
+ if (error = VFS_START(mp, 0, p))
vrele(vp);
} else {
mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
- vfs_unlock(mp);
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
free((caddr_t)mp, M_MOUNT);
vput(vp);
- vfsconf[uap->type]->vfc_refcount--;
}
return (error);
}
/*
+ * Scan all active processes to see if any of them have a current
+ * or root directory onto which the new filesystem has just been
+ * mounted. If so, replace them with the new mount point.
+ */
+static void
+checkdirs(olddp)
+ struct vnode *olddp;
+{
+ struct filedesc *fdp;
+ struct vnode *newdp;
+ struct proc *p;
+
+ if (olddp->v_usecount == 1)
+ return;
+ if (VFS_ROOT(olddp->v_mountedhere, &newdp))
+ panic("mount: lost mount");
+ for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
+ fdp = p->p_fd;
+ if (fdp->fd_cdir == olddp) {
+ vrele(fdp->fd_cdir);
+ VREF(newdp);
+ fdp->fd_cdir = newdp;
+ }
+ if (fdp->fd_rdir == olddp) {
+ vrele(fdp->fd_rdir);
+ VREF(newdp);
+ fdp->fd_rdir = newdp;
+ }
+ }
+ if (rootvnode == olddp) {
+ vrele(rootvnode);
+ VREF(newdp);
+ rootvnode = newdp;
+ }
+ vput(newdp);
+}
+
+/*
* Unmount a file system.
*
* Note: unmount takes a path to the vnode mounted on as argument,
@@ -237,47 +352,51 @@ struct unmount_args {
int
unmount(p, uap, retval)
struct proc *p;
- register struct unmount_args *uap;
- int *retval;
+ register struct unmount_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct mount *mp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
+ mp = vp->v_mount;
/*
- * Unless this is a user mount, then must
- * have suser privilege.
+ * Only root, or the user that did the original mount is
+ * permitted to unmount this filesystem.
*/
- if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
+ if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
(error = suser(p->p_ucred, &p->p_acflag))) {
vput(vp);
return (error);
}
/*
- * Must be the root of the filesystem
+ * Don't allow unmounting the root file system.
*/
- if ((vp->v_flag & VROOT) == 0) {
+ if (mp->mnt_flag & MNT_ROOTFS) {
vput(vp);
return (EINVAL);
}
- mp = vp->v_mount;
- vput(vp);
/*
- * Don't allow unmount of the root filesystem
+ * Must be the root of the filesystem
*/
- if (mp->mnt_flag & MNT_ROOTFS)
+ if ((vp->v_flag & VROOT) == 0) {
+ vput(vp);
return (EINVAL);
-
- return (dounmount(mp, uap->flags, p));
+ }
+ vput(vp);
+ return (dounmount(mp, SCARG(uap, flags), p));
}
/*
@@ -292,74 +411,86 @@ dounmount(mp, flags, p)
struct vnode *coveredvp;
int error;
- coveredvp = mp->mnt_vnodecovered;
- if (vfs_busy(mp))
- return (EBUSY);
+ simple_lock(&mountlist_slock);
mp->mnt_flag |= MNT_UNMOUNT;
- error = vfs_lock(mp);
- if (error)
- return (error);
-
+ lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
mp->mnt_flag &=~ MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
vnode_pager_umount(mp); /* release cached vnodes */
cache_purgevfs(mp); /* remove cache entries for this file sys */
- if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
+ 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 {
+ mp->mnt_flag &= ~MNT_UNMOUNT;
+ lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
+ &mountlist_slock, p);
+ return (error);
+ }
+ CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
+ if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
+ coveredvp->v_mountedhere = (struct mount *)0;
vrele(coveredvp);
- CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
- mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
- vfs_unlock(mp);
- mp->mnt_vfc->vfc_refcount--;
- if (mp->mnt_vnodelist.lh_first != NULL)
- panic("unmount: dangling vnode");
- free((caddr_t)mp, M_MOUNT);
}
- return (error);
+ mp->mnt_vfc->vfc_refcount--;
+ if (mp->mnt_vnodelist.lh_first != NULL)
+ panic("unmount: dangling vnode");
+ lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
+ if (mp->mnt_flag & MNT_MWAIT)
+ wakeup((caddr_t)mp);
+ free((caddr_t)mp, M_MOUNT);
+ return (0);
}
/*
* Sync each mounted filesystem.
*/
-
#ifndef _SYS_SYSPROTO_H_
struct sync_args {
int dummy;
};
#endif
+#ifdef DEBUG
+int syncprt = 0;
+SYSCTL_INT(_debug, 0, syncprt, CTLFLAG_RW, &syncprt, 0, "");
+#endif
+
/* ARGSUSED */
int
sync(p, uap, retval)
struct proc *p;
struct sync_args *uap;
- int *retval;
+ register_t *retval;
{
- register struct mount *mp;
+ register struct mount *mp, *nmp;
int asyncflag;
- for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = mp->mnt_list.cqe_next) {
- /*
- * 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)) {
+ simple_lock(&mountlist_slock);
+ for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nmp = mp->mnt_list.cqe_next;
+ continue;
+ }
+ if ((mp->mnt_flag & MNT_RDONLY) == 0) {
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
- vfs_unbusy(mp);
}
+ simple_lock(&mountlist_slock);
+ nmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
+#ifdef DIAGNOSTIC
+ if (syncprt)
+ vfs_bufstats();
+#endif /* DIAGNOSTIC */
return (0);
}
@@ -378,20 +509,25 @@ struct quotactl_args {
int
quotactl(p, uap, retval)
struct proc *p;
- register struct quotactl_args *uap;
- int *retval;
+ register struct quotactl_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) cmd;
+ syscallarg(int) uid;
+ syscallarg(caddr_t) arg;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
mp = nd.ni_vp->v_mount;
vrele(nd.ni_vp);
- return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
+ return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
+ SCARG(uap, arg), p));
}
/*
@@ -407,17 +543,19 @@ struct statfs_args {
int
statfs(p, uap, retval)
struct proc *p;
- register struct statfs_args *uap;
- int *retval;
+ register struct statfs_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct statfs *) buf;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp;
register struct statfs *sp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
mp = nd.ni_vp->v_mount;
sp = &mp->mnt_stat;
@@ -426,7 +564,7 @@ statfs(p, uap, retval)
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
+ return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
}
/*
@@ -442,16 +580,18 @@ struct fstatfs_args {
int
fstatfs(p, uap, retval)
struct proc *p;
- register struct fstatfs_args *uap;
- int *retval;
+ register struct fstatfs_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct statfs *) buf;
+ } */ *uap;
+ register_t *retval;
{
struct file *fp;
struct mount *mp;
register struct statfs *sp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
mp = ((struct vnode *)fp->f_data)->v_mount;
sp = &mp->mnt_stat;
@@ -459,7 +599,7 @@ fstatfs(p, uap, retval)
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
+ return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
}
/*
@@ -475,48 +615,55 @@ struct getfsstat_args {
int
getfsstat(p, uap, retval)
struct proc *p;
- register struct getfsstat_args *uap;
- int *retval;
+ register struct getfsstat_args /* {
+ syscallarg(struct statfs *) buf;
+ syscallarg(long) bufsize;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp, *nmp;
register struct statfs *sp;
caddr_t sfsp;
long count, maxcount, error;
- maxcount = uap->bufsize / sizeof(struct statfs);
- sfsp = (caddr_t)uap->buf;
+ maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
+ sfsp = (caddr_t)SCARG(uap, buf);
count = 0;
+ simple_lock(&mountlist_slock);
for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
- if (vfs_busy(mp)) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
nmp = mp->mnt_list.cqe_next;
continue;
}
- if (sfsp && count < maxcount &&
- ((mp->mnt_flag & MNT_MLOCK) == 0)) {
+ if (sfsp && count < maxcount) {
sp = &mp->mnt_stat;
/*
* If MNT_NOWAIT is specified, do not refresh the
* fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
*/
- if (((uap->flags & MNT_NOWAIT) == 0 ||
- (uap->flags & MNT_WAIT)) &&
+ if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
+ (SCARG(uap, flags) & MNT_WAIT)) &&
(error = VFS_STATFS(mp, sp, p))) {
+ simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
continue;
}
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
if (error) {
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
return (error);
}
sfsp += sizeof(*sp);
}
count++;
+ simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
if (sfsp && count > maxcount)
*retval = maxcount;
else
@@ -536,27 +683,41 @@ struct fchdir_args {
int
fchdir(p, uap, retval)
struct proc *p;
- struct fchdir_args *uap;
- int *retval;
+ struct fchdir_args /* {
+ syscallarg(int) fd;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
- register struct vnode *vp;
+ struct vnode *vp, *tdp;
+ struct mount *mp;
struct file *fp;
int error;
- error = getvnode(fdp, uap->fd, &fp);
- if (error)
+ if (error = getvnode(fdp, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- VOP_LOCK(vp);
+ VREF(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type != VDIR)
error = ENOTDIR;
else
error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
- VOP_UNLOCK(vp);
- if (error)
+ while (!error && (mp = vp->v_mountedhere) != NULL) {
+ if (vfs_busy(mp, 0, 0, p))
+ continue;
+ error = VFS_ROOT(mp, &tdp);
+ vfs_unbusy(mp, p);
+ if (error)
+ break;
+ vput(vp);
+ vp = tdp;
+ }
+ if (error) {
+ vput(vp);
return (error);
- VREF(vp);
+ }
+ VOP_UNLOCK(vp, 0, p);
vrele(fdp->fd_cdir);
fdp->fd_cdir = vp;
return (0);
@@ -574,16 +735,18 @@ struct chdir_args {
int
chdir(p, uap, retval)
struct proc *p;
- struct chdir_args *uap;
- int *retval;
+ struct chdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = change_dir(&nd, p);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = change_dir(&nd, p))
return (error);
vrele(fdp->fd_cdir);
fdp->fd_cdir = nd.ni_vp;
@@ -602,8 +765,10 @@ struct chroot_args {
int
chroot(p, uap, retval)
struct proc *p;
- struct chroot_args *uap;
- int *retval;
+ struct chroot_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
int error;
@@ -612,9 +777,9 @@ chroot(p, uap, retval)
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = change_dir(&nd, p);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = change_dir(&nd, p))
return (error);
if (fdp->fd_rdir != NULL)
vrele(fdp->fd_rdir);
@@ -641,9 +806,10 @@ change_dir(ndp, p)
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, p);
return (error);
}
@@ -661,8 +827,12 @@ struct open_args {
int
open(p, uap, retval)
struct proc *p;
- register struct open_args *uap;
- int *retval;
+ register struct open_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
register struct file *fp;
@@ -677,17 +847,17 @@ open(p, uap, retval)
if (error)
return (error);
fp = nfp;
- flags = FFLAGS(uap->flags);
- cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
+ flags = FFLAGS(SCARG(uap, flags));
+ cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
p->p_dupfd = -indx - 1; /* XXX check for fdopen */
error = vn_open(&nd, flags, cmode);
if (error) {
ffree(fp);
if ((error == ENODEV || error == ENXIO) &&
- p->p_dupfd >= 0 && /* XXX from fdopen */
+ p->p_dupfd >= 0 && /* XXX from fdopen */
(error =
- dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
+ dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
*retval = indx;
return (0);
}
@@ -714,18 +884,17 @@ open(p, uap, retval)
type = F_FLOCK;
if ((flags & FNONBLOCK) == 0)
type |= F_WAIT;
- VOP_UNLOCK(vp);
- error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
- if (error) {
+ VOP_UNLOCK(vp, 0, p);
+ if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
ffree(fp);
fdp->fd_ofiles[indx] = NULL;
return (error);
}
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
fp->f_flag |= FHASLOCK;
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
*retval = indx;
return (0);
}
@@ -743,15 +912,22 @@ struct ocreat_args {
int
ocreat(p, uap, retval)
struct proc *p;
- register struct ocreat_args *uap;
- int *retval;
+ register struct ocreat_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
- struct open_args openuap;
-
- openuap.path = uap->path;
- openuap.mode = uap->mode;
- openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
- return (open(p, &openuap, retval));
+ struct open_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+ } */ nuap;
+
+ SCARG(&nuap, path) = SCARG(uap, path);
+ SCARG(&nuap, mode) = SCARG(uap, mode);
+ SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
+ return (open(p, &nuap, retval));
}
#endif /* COMPAT_43 */
@@ -769,30 +945,35 @@ struct mknod_args {
int
mknod(p, uap, retval)
struct proc *p;
- register struct mknod_args *uap;
- int *retval;
+ register struct mknod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ syscallarg(int) dev;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
+ int whiteout;
struct nameidata nd;
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp != NULL)
error = EEXIST;
else {
VATTR_NULL(&vattr);
- vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
- vattr.va_rdev = uap->dev;
+ vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
+ vattr.va_rdev = SCARG(uap, dev);
+ whiteout = 0;
- switch (uap->mode & S_IFMT) {
+ switch (SCARG(uap, mode) & S_IFMT) {
case S_IFMT: /* used by badsect to flag bad sectors */
vattr.va_type = VBAD;
break;
@@ -802,14 +983,25 @@ mknod(p, uap, retval)
case S_IFBLK:
vattr.va_type = VBLK;
break;
+ case S_IFWHT:
+ whiteout = 1;
+ break;
default:
error = EINVAL;
break;
}
}
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ if (whiteout) {
+ error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
+ if (error)
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ vput(nd.ni_dvp);
+ } else {
+ error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
+ &nd.ni_cnd, &vattr);
+ }
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == vp)
@@ -823,7 +1015,7 @@ mknod(p, uap, retval)
}
/*
- * Create named pipe.
+ * Create a named pipe.
*/
#ifndef _SYS_SYSPROTO_H_
struct mkfifo_args {
@@ -835,16 +1027,21 @@ struct mkfifo_args {
int
mkfifo(p, uap, retval)
struct proc *p;
- register struct mkfifo_args *uap;
- int *retval;
+ register struct mkfifo_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
+#ifndef FIFO
+ return (EOPNOTSUPP);
+#else
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -857,9 +1054,10 @@ mkfifo(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VFIFO;
- vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
+#endif /* FIFO */
}
/*
@@ -875,22 +1073,24 @@ struct link_args {
int
link(p, uap, retval)
struct proc *p;
- register struct link_args *uap;
- int *retval;
+ register struct link_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) link;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct nameidata nd;
int error;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
else {
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
error = namei(&nd);
if (!error) {
if (nd.ni_vp != NULL) {
@@ -903,10 +1103,9 @@ link(p, uap, retval)
vrele(nd.ni_vp);
error = EEXIST;
} else {
- LEASE_CHECK(nd.ni_dvp,
- p, p->p_ucred, LEASE_WRITE);
- LEASE_CHECK(vp,
- p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
+ LEASE_WRITE);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
}
}
@@ -928,8 +1127,11 @@ struct symlink_args {
int
symlink(p, uap, retval)
struct proc *p;
- register struct symlink_args *uap;
- int *retval;
+ register struct symlink_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) link;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
char *path;
@@ -937,12 +1139,10 @@ symlink(p, uap, retval)
struct nameidata nd;
MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
- error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
- if (error)
+ if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
goto out;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
+ if (error = namei(&nd))
goto out;
if (nd.ni_vp) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -956,7 +1156,7 @@ symlink(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
out:
FREE(path, M_NAMEI);
@@ -964,6 +1164,45 @@ out:
}
/*
+ * Delete a whiteout from the filesystem.
+ */
+/* ARGSUSED */
+int
+undelete(p, uap, retval)
+ struct proc *p;
+ register struct undelete_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
+{
+ int error;
+ struct nameidata nd;
+
+ NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ error = namei(&nd);
+ if (error)
+ return (error);
+
+ if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (nd.ni_vp)
+ vrele(nd.ni_vp);
+ return (EEXIST);
+ }
+
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ vput(nd.ni_dvp);
+ return (error);
+}
+
+/*
* Delete a name from the filesystem.
*/
#ifndef _SYS_SYSPROTO_H_
@@ -975,20 +1214,21 @@ struct unlink_args {
int
unlink(p, uap, retval)
struct proc *p;
- struct unlink_args *uap;
- int *retval;
+ struct unlink_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
int error;
struct nameidata nd;
- NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
@@ -1001,11 +1241,11 @@ unlink(p, uap, retval)
if (vp->v_flag & VROOT)
error = EBUSY;
else
- (void) vnode_pager_uncache(vp);
+ (void) vnode_pager_uncache(vp, p);
}
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -1013,7 +1253,8 @@ unlink(p, uap, retval)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
- vput(vp);
+ if (vp != NULLVP)
+ vput(vp);
}
return (error);
}
@@ -1032,8 +1273,13 @@ struct lseek_args {
int
lseek(p, uap, retval)
struct proc *p;
- register struct lseek_args *uap;
- int *retval;
+ register struct lseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) offset;
+ syscallarg(int) whence;
+ } */ *uap;
+ register_t *retval; /* XXX */
{
struct ucred *cred = p->p_ucred;
register struct filedesc *fdp = p->p_fd;
@@ -1041,23 +1287,23 @@ lseek(p, uap, retval)
struct vattr vattr;
int error;
- if ((u_int)uap->fd >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[uap->fd]) == NULL)
+ if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
return (EBADF);
if (fp->f_type != DTYPE_VNODE)
return (ESPIPE);
- switch (uap->whence) {
+ switch (SCARG(uap, whence)) {
case L_INCR:
- fp->f_offset += uap->offset;
+ fp->f_offset += SCARG(uap, offset);
break;
case L_XTND:
error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
if (error)
return (error);
- fp->f_offset = uap->offset + vattr.va_size;
+ fp->f_offset = SCARG(uap, offset) + vattr.va_size;
break;
case L_SET:
- fp->f_offset = uap->offset;
+ fp->f_offset = SCARG(uap, offset);
break;
default:
return (EINVAL);
@@ -1080,17 +1326,26 @@ struct olseek_args {
int
olseek(p, uap, retval)
struct proc *p;
- register struct olseek_args *uap;
- int *retval;
+ register struct olseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(long) offset;
+ syscallarg(int) whence;
+ } */ *uap;
+ register_t *retval;
{
- struct lseek_args nuap;
+ struct lseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) offset;
+ syscallarg(int) whence;
+ } */ nuap;
off_t qret;
int error;
- nuap.fd = uap->fd;
- nuap.offset = uap->offset;
- nuap.whence = uap->whence;
- error = lseek(p, &nuap, (int *)&qret);
+ SCARG(&nuap, fd) = SCARG(uap, fd);
+ SCARG(&nuap, offset) = SCARG(uap, offset);
+ SCARG(&nuap, whence) = SCARG(uap, whence);
+ error = lseek(p, &nuap, (register_t *) &qret);
*(long *)retval = qret;
return (error);
}
@@ -1108,8 +1363,11 @@ struct access_args {
int
access(p, uap, retval)
struct proc *p;
- register struct access_args *uap;
- int *retval;
+ register struct access_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct ucred *cred = p->p_ucred;
register struct vnode *vp;
@@ -1120,20 +1378,20 @@ access(p, uap, retval)
t_gid = cred->cr_groups[0];
cred->cr_uid = p->p_cred->p_ruid;
cred->cr_groups[0] = p->p_cred->p_rgid;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
goto out1;
vp = nd.ni_vp;
/* Flags == 0 means only check for existence. */
- if (uap->flags) {
+ if (SCARG(uap, flags)) {
flags = 0;
- if (uap->flags & R_OK)
+ if (SCARG(uap, flags) & R_OK)
flags |= VREAD;
- if (uap->flags & W_OK)
+ if (SCARG(uap, flags) & W_OK)
flags |= VWRITE;
- if (uap->flags & X_OK)
+ if (SCARG(uap, flags) & X_OK)
flags |= VEXEC;
if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
error = VOP_ACCESS(vp, flags, cred, p);
@@ -1159,24 +1417,27 @@ struct ostat_args {
int
ostat(p, uap, retval)
struct proc *p;
- register struct ostat_args *uap;
- int *retval;
+ register struct ostat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct ostat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct stat sb;
struct ostat osb;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
error = vn_stat(nd.ni_vp, &sb, p);
vput(nd.ni_vp);
if (error)
return (error);
cvtstat(&sb, &osb);
- error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
+ error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
return (error);
}
@@ -1193,8 +1454,11 @@ struct olstat_args {
int
olstat(p, uap, retval)
struct proc *p;
- register struct olstat_args *uap;
- int *retval;
+ register struct olstat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct ostat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct vnode *vp, *dvp;
struct stat sb, sb1;
@@ -1203,9 +1467,8 @@ olstat(p, uap, retval)
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
- uap->path, p);
- error = namei(&nd);
- if (error)
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
/*
* For symbolic links, always return the attributes of its
@@ -1240,7 +1503,7 @@ olstat(p, uap, retval)
sb.st_blocks = sb1.st_blocks;
}
cvtstat(&sb, &osb);
- error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
+ error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
return (error);
}
@@ -1287,22 +1550,25 @@ struct stat_args {
int
stat(p, uap, retval)
struct proc *p;
- register struct stat_args *uap;
- int *retval;
+ register struct stat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct stat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct stat sb;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
error = vn_stat(nd.ni_vp, &sb, p);
vput(nd.ni_vp);
if (error)
return (error);
- error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
+ error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
return (error);
}
@@ -1319,8 +1585,11 @@ struct lstat_args {
int
lstat(p, uap, retval)
struct proc *p;
- register struct lstat_args *uap;
- int *retval;
+ register struct lstat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct stat *) ub;
+ } */ *uap;
+ register_t *retval;
{
int error;
struct vnode *vp, *dvp;
@@ -1328,13 +1597,12 @@ lstat(p, uap, retval)
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
- uap->path, p);
- error = namei(&nd);
- if (error)
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
/*
- * For symbolic links, always return the attributes of its
- * containing directory, except for mode, size, and links.
+ * For symbolic links, always return the attributes of its containing
+ * directory, except for mode, size, inode number, and links.
*/
vp = nd.ni_vp;
dvp = nd.ni_dvp;
@@ -1363,8 +1631,9 @@ lstat(p, uap, retval)
sb.st_nlink = sb1.st_nlink;
sb.st_size = sb1.st_size;
sb.st_blocks = sb1.st_blocks;
+ sb.st_ino = sb1.st_ino;
}
- error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
+ error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
return (error);
}
@@ -1381,17 +1650,20 @@ struct pathconf_args {
int
pathconf(p, uap, retval)
struct proc *p;
- register struct pathconf_args *uap;
- int *retval;
+ register struct pathconf_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) name;
+ } */ *uap;
+ register_t *retval;
{
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
- error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
+ error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
vput(nd.ni_vp);
return (error);
}
@@ -1410,8 +1682,12 @@ struct readlink_args {
int
readlink(p, uap, retval)
struct proc *p;
- register struct readlink_args *uap;
- int *retval;
+ register struct readlink_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) buf;
+ syscallarg(int) count;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct iovec aiov;
@@ -1419,27 +1695,27 @@ readlink(p, uap, retval)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type != VLNK)
error = EINVAL;
else {
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
+ auio.uio_resid = SCARG(uap, count);
error = VOP_READLINK(vp, &auio, p->p_ucred);
}
vput(vp);
- *retval = uap->count - auio.uio_resid;
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
@@ -1456,23 +1732,25 @@ struct chflags_args {
int
chflags(p, uap, retval)
struct proc *p;
- register struct chflags_args *uap;
- int *retval;
+ register struct chflags_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_flags = uap->flags;
+ vattr.va_flags = SCARG(uap, flags);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1491,24 +1769,26 @@ struct fchflags_args {
int
fchflags(p, uap, retval)
struct proc *p;
- register struct fchflags_args *uap;
- int *retval;
+ register struct fchflags_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_flags = uap->flags;
+ vattr.va_flags = SCARG(uap, flags);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1525,23 +1805,25 @@ struct chmod_args {
int
chmod(p, uap, retval)
struct proc *p;
- register struct chmod_args *uap;
- int *retval;
+ register struct chmod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_mode = uap->mode & ALLPERMS;
+ vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1560,24 +1842,26 @@ struct fchmod_args {
int
fchmod(p, uap, retval)
struct proc *p;
- register struct fchmod_args *uap;
- int *retval;
+ register struct fchmod_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_mode = uap->mode & ALLPERMS;
+ vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1595,24 +1879,27 @@ struct chown_args {
int
chown(p, uap, retval)
struct proc *p;
- register struct chown_args *uap;
- int *retval;
+ register struct chown_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_uid = uap->uid;
- vattr.va_gid = uap->gid;
+ vattr.va_uid = SCARG(uap, uid);
+ vattr.va_gid = SCARG(uap, gid);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1632,25 +1919,28 @@ struct fchown_args {
int
fchown(p, uap, retval)
struct proc *p;
- register struct fchown_args *uap;
- int *retval;
+ register struct fchown_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_uid = uap->uid;
- vattr.va_gid = uap->gid;
+ vattr.va_uid = SCARG(uap, uid);
+ vattr.va_gid = SCARG(uap, gid);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1667,8 +1957,11 @@ struct utimes_args {
int
utimes(p, uap, retval)
struct proc *p;
- register struct utimes_args *uap;
- int *retval;
+ register struct utimes_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct timeval *) tptr;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct timeval tv[2];
@@ -1677,22 +1970,19 @@ utimes(p, uap, retval)
struct nameidata nd;
VATTR_NULL(&vattr);
- if (uap->tptr == NULL) {
+ if (SCARG(uap, tptr) == NULL) {
microtime(&tv[0]);
tv[1] = tv[0];
vattr.va_vaflags |= VA_UTIMES_NULL;
- } else {
- error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
- if (error)
- return (error);
- }
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
+ sizeof (tv)))
+ return (error);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
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;
@@ -1716,8 +2006,12 @@ struct truncate_args {
int
truncate(p, uap, retval)
struct proc *p;
- register struct truncate_args *uap;
- int *retval;
+ register struct truncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
@@ -1726,19 +2020,18 @@ truncate(p, uap, retval)
if (uap->length < 0)
return(EINVAL);
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EISDIR;
else if ((error = vn_writechk(vp)) == 0 &&
(error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
VATTR_NULL(&vattr);
- vattr.va_size = uap->length;
+ vattr.va_size = SCARG(uap, length);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
}
vput(vp);
@@ -1759,8 +2052,12 @@ struct ftruncate_args {
int
ftruncate(p, uap, retval)
struct proc *p;
- register struct ftruncate_args *uap;
- int *retval;
+ register struct ftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
@@ -1769,22 +2066,21 @@ ftruncate(p, uap, retval)
if (uap->length < 0)
return(EINVAL);
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FWRITE) == 0)
return (EINVAL);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EISDIR;
else if ((error = vn_writechk(vp)) == 0) {
VATTR_NULL(&vattr);
- vattr.va_size = uap->length;
+ vattr.va_size = SCARG(uap, length);
error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1802,13 +2098,20 @@ struct otruncate_args {
int
otruncate(p, uap, retval)
struct proc *p;
- register struct otruncate_args *uap;
- int *retval;
+ register struct otruncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(long) length;
+ } */ *uap;
+ register_t *retval;
{
- struct truncate_args nuap;
-
- nuap.path = uap->path;
- nuap.length = uap->length;
+ struct truncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ nuap;
+
+ SCARG(&nuap, path) = SCARG(uap, path);
+ SCARG(&nuap, length) = SCARG(uap, length);
return (truncate(p, &nuap, retval));
}
@@ -1825,13 +2128,20 @@ struct oftruncate_args {
int
oftruncate(p, uap, retval)
struct proc *p;
- register struct oftruncate_args *uap;
- int *retval;
+ register struct oftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(long) length;
+ } */ *uap;
+ register_t *retval;
{
- struct ftruncate_args nuap;
-
- nuap.fd = uap->fd;
- nuap.length = uap->length;
+ struct ftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ nuap;
+
+ SCARG(&nuap, fd) = SCARG(uap, fd);
+ SCARG(&nuap, length) = SCARG(uap, length);
return (ftruncate(p, &nuap, retval));
}
#endif /* COMPAT_43 || COMPAT_SUNOS */
@@ -1848,24 +2158,25 @@ struct fsync_args {
int
fsync(p, uap, retval)
struct proc *p;
- struct fsync_args *uap;
- int *retval;
+ struct fsync_args /* {
+ syscallarg(int) fd;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_object) {
vm_object_page_clean(vp->v_object, 0, 0 ,0, FALSE);
}
error = VOP_FSYNC(vp, fp->f_cred,
(vp->v_mount->mnt_flag & MNT_ASYNC) ? MNT_NOWAIT : MNT_WAIT, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1883,29 +2194,29 @@ struct rename_args {
int
rename(p, uap, retval)
struct proc *p;
- register struct rename_args *uap;
- int *retval;
+ register struct rename_args /* {
+ syscallarg(char *) from;
+ syscallarg(char *) to;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *tvp, *fvp, *tdvp;
struct nameidata fromnd, tond;
int error;
NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
- uap->from, p);
- error = namei(&fromnd);
- if (error)
+ SCARG(uap, from), p);
+ if (error = namei(&fromnd))
return (error);
fvp = fromnd.ni_vp;
NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
- UIO_USERSPACE, uap->to, p);
+ UIO_USERSPACE, SCARG(uap, to), p);
if (fromnd.ni_vp->v_type == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
- error = namei(&tond);
- if (error) {
+ if (error = namei(&tond)) {
/* Translate error code for rename("dir1", "dir2/."). */
if (error == EISDIR && fvp->v_type == VDIR)
error = EINVAL;
-
VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
vrele(fromnd.ni_dvp);
vrele(fvp);
@@ -1936,13 +2247,12 @@ rename(p, uap, retval)
error = -1;
out:
if (!error) {
- LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
- if (fromnd.ni_dvp != tdvp) {
- LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- }
+ VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
+ if (fromnd.ni_dvp != tdvp)
+ VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
if (tvp) {
- LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
- (void) vnode_pager_uncache(tvp);
+ VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
+ (void) vnode_pager_uncache(tvp, p);
}
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
@@ -1982,18 +2292,20 @@ struct mkdir_args {
int
mkdir(p, uap, retval)
struct proc *p;
- register struct mkdir_args *uap;
- int *retval;
+ register struct mkdir_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
nd.ni_cnd.cn_flags |= WILLBEDIR;
- error = namei(&nd);
- if (error)
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp != NULL) {
@@ -2007,8 +2319,8 @@ mkdir(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VDIR;
- vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (!error)
vput(nd.ni_vp);
@@ -2027,16 +2339,18 @@ struct rmdir_args {
int
rmdir(p, uap, retval)
struct proc *p;
- struct rmdir_args *uap;
- int *retval;
+ struct rmdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
int error;
struct nameidata nd;
- NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type != VDIR) {
@@ -2057,8 +2371,8 @@ rmdir(p, uap, retval)
error = EBUSY;
out:
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -2086,8 +2400,13 @@ struct ogetdirentries_args {
int
ogetdirentries(p, uap, retval)
struct proc *p;
- register struct ogetdirentries_args *uap;
- int *retval;
+ register struct ogetdirentries_args /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(u_int) count;
+ syscallarg(long *) basep;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
@@ -2095,30 +2414,31 @@ ogetdirentries(p, uap, retval)
struct iovec aiov, kiov;
struct dirent *dp, *edp;
caddr_t dirbuf;
- int error, readcnt;
+ int error, eofflag, readcnt;
long loff;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
vp = (struct vnode *)fp->f_data;
+unionread:
if (vp->v_type != VDIR)
return (EINVAL);
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
- VOP_LOCK(vp);
+ auio.uio_resid = SCARG(uap, count);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
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, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
+ NULL, NULL);
fp->f_offset = auio.uio_offset;
} else
# endif
@@ -2126,13 +2446,14 @@ ogetdirentries(p, uap, retval)
kuio = auio;
kuio.uio_iov = &kiov;
kuio.uio_segflg = UIO_SYSSPACE;
- kiov.iov_len = uap->count;
- MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
+ kiov.iov_len = SCARG(uap, count);
+ MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
kiov.iov_base = dirbuf;
- error = VOP_READDIR(vp, &kuio, fp->f_cred, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
+ NULL, NULL);
fp->f_offset = kuio.uio_offset;
if (error == 0) {
- readcnt = uap->count - kuio.uio_resid;
+ readcnt = SCARG(uap, count) - kuio.uio_resid;
edp = (struct dirent *)&dirbuf[readcnt];
for (dp = (struct dirent *)dirbuf; dp < edp; ) {
# if (BYTE_ORDER == LITTLE_ENDIAN)
@@ -2165,14 +2486,70 @@ ogetdirentries(p, uap, retval)
}
FREE(dirbuf, M_TEMP);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
- error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
- *retval = uap->count - auio.uio_resid;
+
+#ifdef UNION
+{
+ extern int (**union_vnodeop_p)();
+ extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
+ (vp->v_op == union_vnodeop_p)) {
+ struct vnode *lvp;
+
+ lvp = union_dircache(vp, p);
+ if (lvp != NULLVP) {
+ struct vattr va;
+
+ /*
+ * If the directory is opaque,
+ * then don't show lower entries
+ */
+ error = VOP_GETATTR(vp, &va, fp->f_cred, p);
+ if (va.va_flags & OPAQUE) {
+ vput(lvp);
+ lvp = NULL;
+ }
+ }
+
+ if (lvp != NULLVP) {
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
+ if (error) {
+ vput(lvp);
+ return (error);
+ }
+ VOP_UNLOCK(lvp, 0, p);
+ fp->f_data = (caddr_t) lvp;
+ fp->f_offset = 0;
+ error = vn_close(vp, FREAD, fp->f_cred, p);
+ if (error)
+ return (error);
+ vp = lvp;
+ goto unionread;
+ }
+ }
+}
+#endif /* UNION */
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
+ (vp->v_flag & VROOT) &&
+ (vp->v_mount->mnt_flag & MNT_UNION)) {
+ struct vnode *tvp = vp;
+ vp = vp->v_mount->mnt_vnodecovered;
+ VREF(vp);
+ fp->f_data = (caddr_t) vp;
+ fp->f_offset = 0;
+ vrele(tvp);
+ goto unionread;
+ }
+ error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
+ sizeof(long));
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
-#endif
+#endif /* COMPAT_43 */
/*
* Read a block of directory entries in a file system independent format.
@@ -2188,18 +2565,22 @@ struct getdirentries_args {
int
getdirentries(p, uap, retval)
struct proc *p;
- register struct getdirentries_args *uap;
- int *retval;
+ register struct getdirentries_args /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(u_int) count;
+ syscallarg(long *) basep;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
struct uio auio;
struct iovec aiov;
long loff;
- int error;
+ int error, eofflag;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
@@ -2207,51 +2588,66 @@ getdirentries(p, uap, retval)
unionread:
if (vp->v_type != VDIR)
return (EINVAL);
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
- VOP_LOCK(vp);
+ auio.uio_resid = SCARG(uap, count);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
loff = auio.uio_offset = fp->f_offset;
- error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
fp->f_offset = auio.uio_offset;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
#ifdef UNION
{
- if ((uap->count == auio.uio_resid) &&
+ extern int (**union_vnodeop_p)();
+ extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
(vp->v_op == union_vnodeop_p)) {
- struct vnode *tvp = vp;
+ struct vnode *lvp;
+
+ lvp = union_dircache(vp, p);
+ if (lvp != NULLVP) {
+ struct vattr va;
- vp = union_lowervp(vp);
- if (vp != NULLVP) {
- VOP_LOCK(vp);
- error = VOP_OPEN(vp, FREAD, fp->f_cred, p);
- VOP_UNLOCK(vp);
+ /*
+ * If the directory is opaque,
+ * then don't show lower entries
+ */
+ error = VOP_GETATTR(vp, &va, fp->f_cred, p);
+ if (va.va_flags & OPAQUE) {
+ vput(lvp);
+ lvp = NULL;
+ }
+ }
+ if (lvp != NULLVP) {
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
if (error) {
- vrele(vp);
+ vput(lvp);
return (error);
}
- fp->f_data = (caddr_t) vp;
+ VOP_UNLOCK(lvp, 0, p);
+ fp->f_data = (caddr_t) lvp;
fp->f_offset = 0;
- error = vn_close(tvp, FREAD, fp->f_cred, p);
+ error = vn_close(vp, FREAD, fp->f_cred, p);
if (error)
return (error);
+ vp = lvp;
goto unionread;
}
}
}
-#endif
+#endif /* UNION */
- if ((uap->count == auio.uio_resid) &&
- vp &&
+ if ((SCARG(uap, count) == auio.uio_resid) &&
(vp->v_flag & VROOT) &&
(vp->v_mount->mnt_flag & MNT_UNION)) {
struct vnode *tvp = vp;
@@ -2262,8 +2658,9 @@ unionread:
vrele(tvp);
goto unionread;
}
- error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
- *retval = uap->count - auio.uio_resid;
+ error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
+ sizeof(long));
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
@@ -2275,17 +2672,19 @@ struct umask_args {
int newmask;
};
#endif
-mode_t /* XXX */
+int
umask(p, uap, retval)
struct proc *p;
- struct umask_args *uap;
- int *retval;
+ struct umask_args /* {
+ syscallarg(int) newmask;
+ } */ *uap;
+ int *retval; /* XXX */
{
register struct filedesc *fdp;
fdp = p->p_fd;
*retval = fdp->fd_cmask;
- fdp->fd_cmask = uap->newmask & ALLPERMS;
+ fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
return (0);
}
@@ -2302,31 +2701,27 @@ struct revoke_args {
int
revoke(p, uap, retval)
struct proc *p;
- register struct revoke_args *uap;
- int *retval;
+ register struct revoke_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- if (vp->v_type != VCHR && vp->v_type != VBLK) {
- error = EINVAL;
- goto out;
- }
- error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
- if (error)
+ if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
goto out;
if (p->p_ucred->cr_uid != vattr.va_uid &&
(error = suser(p->p_ucred, &p->p_acflag)))
goto out;
if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
- vgoneall(vp);
+ VOP_REVOKE(vp, REVOKEALL);
out:
vrele(vp);
return (error);
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index f4e96e4..161ff0c 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -76,8 +76,6 @@ extern struct linker_set vfs_opv_descs_;
#define vfs_opv_descs ((struct vnodeopv_desc **)vfs_opv_descs_.ls_items)
extern struct linker_set vfs_set;
-struct vfsops *vfssw[MOUNT_MAXTYPE + 1];
-struct vfsconf *vfsconf[MOUNT_MAXTYPE + 1];
extern struct vnodeop_desc *vfs_op_descs[];
/* and the operations they perform */
@@ -239,23 +237,8 @@ static void
vfsinit(dummy)
void *dummy;
{
- struct vfsops **vfsp;
struct vfsconf **vfc;
- int i;
-
- /*
- * Initialize the VFS switch table
- */
- for(i = 0; i < MOUNT_MAXTYPE + 1; i++) {
- vfsconf[i] = &void_vfsconf;
- }
-
- vfc = (struct vfsconf **)vfs_set.ls_items;
- while(*vfc) {
- vfssw[(**vfc).vfc_index] = (**vfc).vfc_vfsops;
- vfsconf[(**vfc).vfc_index] = *vfc;
- vfc++;
- }
+ int maxtypenum;
/*
* Initialize the vnode table
@@ -274,11 +257,20 @@ vfsinit(dummy)
* Initialize each file system type.
*/
vattr_null(&va_null);
- for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) {
- if (*vfsp == NULL)
- continue;
- (*(*vfsp)->vfs_init)();
+ maxtypenum = 0;
+ vfc = (struct vfsconf **)vfs_set.ls_items;
+ vfsconf = *vfc; /* simulate Lite2 vfsconf array */
+ while (*vfc) {
+ struct vfsconf *vfsp = *vfc;
+
+ vfc++;
+ vfsp->vfc_next = *vfc;
+ if (maxtypenum <= vfsp->vfc_typenum)
+ maxtypenum = vfsp->vfc_typenum + 1;
+ (*vfsp->vfc_vfsops->vfs_init)(vfsp);
}
+ /* next vfc_typenum to be used */
+ maxvfsconf = maxtypenum;
}
/*
@@ -286,29 +278,81 @@ vfsinit(dummy)
*/
static int
-sysctl_vfs_vfsconf SYSCTL_HANDLER_ARGS
+sysctl_vfs_conf SYSCTL_HANDLER_ARGS
{
- int i, error;
+ int error;
+ struct vfsconf *vfsp;
if (req->newptr)
return EINVAL;
- for(i = 0; i < MOUNT_MAXTYPE + 1; i++) {
- error = SYSCTL_OUT(req, vfsconf[i], sizeof *vfsconf[i]);
- if(error)
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
+ error = SYSCTL_OUT(req, vfsp, sizeof *vfsp);
+ if (error)
return error;
}
- return (error);
-
+ return 0;
}
SYSCTL_PROC(_vfs, VFS_VFSCONF, vfsconf, CTLTYPE_OPAQUE|CTLFLAG_RD,
- 0, 0, sysctl_vfs_vfsconf, "S,vfsconf", "");
+ 0, 0, sysctl_vfs_conf, "S,vfsconf", "");
+
+#ifdef COMPAT_PRELITE2
+
+#define OVFS_MAXNAMELEN 32
+struct ovfsconf {
+ void *vfc_vfsops;
+ char vfc_name[OVFS_MAXNAMELEN];
+ int vfc_index;
+ int vfc_refcount;
+ int vfc_flags;
+};
+
+static int
+sysctl_ovfs_conf SYSCTL_HANDLER_ARGS
+{
+ int error;
+ struct vfsconf *vfsp;
+
+ if (req->newptr)
+ return EINVAL;
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
+ struct ovfsconf ovfs;
+ ovfs.vfc_vfsops = NULL;
+ strcpy(ovfs.vfc_name, vfsp->vfc_name);
+ ovfs.vfc_index = vfsp->vfc_typenum;
+ ovfs.vfc_refcount = vfsp->vfc_refcount;
+ ovfs.vfc_flags = vfsp->vfc_flags;
+ error = SYSCTL_OUT(req, &ovfs, sizeof ovfs);
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+SYSCTL_PROC(_vfs, VFS_OVFSCONF, ovfsconf, CTLTYPE_OPAQUE|CTLFLAG_RD,
+ 0, 0, sysctl_ovfs_conf, "S,ovfsconf", "");
+
+#endif /* COMPAT_PRELITE2 */
/*
* This goop is here to support a loadable NFS module... grumble...
*/
-void (*lease_check) __P((struct vnode *, struct proc *, struct ucred *, int))
+int (*lease_check_hook) __P((struct vop_lease_args *))
= 0;
void (*lease_updatetime) __P((int))
= 0;
+int
+lease_check(ap)
+ struct vop_lease_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ struct ucred *a_cred;
+ int a_flag;
+ } */ *ap;
+{
+ if (lease_check_hook)
+ return (*lease_check_hook)(ap);
+ else
+ return 0;
+}
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 1cadfd0..120821d 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -88,6 +88,7 @@ namei(ndp)
struct uio auio;
int error, linklen;
struct componentname *cnp = &ndp->ni_cnd;
+ struct proc *p = cnp->cn_proc;
ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;
#ifdef DIAGNOSTIC
@@ -169,7 +170,7 @@ namei(ndp)
return (0);
}
if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
- VOP_UNLOCK(ndp->ni_dvp);
+ VOP_UNLOCK(ndp->ni_dvp, 0, p);
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
error = ELOOP;
break;
@@ -269,6 +270,7 @@ lookup(ndp)
int trailing_slash;
int error = 0;
struct componentname *cnp = &ndp->ni_cnd;
+ struct proc *p = cnp->cn_proc;
/*
* Setup: break out flag bits into variables.
@@ -283,7 +285,7 @@ lookup(ndp)
cnp->cn_flags &= ~ISSYMLINK;
dp = ndp->ni_startdir;
ndp->ni_startdir = NULLVP;
- VOP_LOCK(dp);
+ vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
dirloop:
/*
@@ -351,21 +353,21 @@ dirloop:
* e.g. like "/." or ".".
*/
if (cnp->cn_nameptr[0] == '\0') {
- if (cnp->cn_nameiop != LOOKUP) {
- error = EISDIR;
- goto bad;
- }
if (dp->v_type != VDIR) {
error = ENOTDIR;
goto bad;
}
+ if (cnp->cn_nameiop != LOOKUP) {
+ error = EISDIR;
+ goto bad;
+ }
if (wantparent) {
ndp->ni_dvp = dp;
VREF(dp);
}
ndp->ni_vp = dp;
if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
- VOP_UNLOCK(dp);
+ VOP_UNLOCK(dp, 0, p);
if (cnp->cn_flags & SAVESTART)
panic("lookup: SAVESTART");
return (0);
@@ -396,7 +398,7 @@ dirloop:
dp = dp->v_mount->mnt_vnodecovered;
vput(tdp);
VREF(dp);
- VOP_LOCK(dp);
+ vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
}
}
@@ -405,8 +407,8 @@ dirloop:
*/
unionlookup:
ndp->ni_dvp = dp;
- error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp);
- if (error) {
+ ndp->ni_vp = NULL;
+ if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) {
#ifdef DIAGNOSTIC
if (ndp->ni_vp != NULL)
panic("leaf should be empty");
@@ -421,7 +423,7 @@ unionlookup:
dp = dp->v_mount->mnt_vnodecovered;
vput(tdp);
VREF(dp);
- VOP_LOCK(dp);
+ vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
goto unionlookup;
}
@@ -474,12 +476,10 @@ unionlookup:
*/
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;
- (void) tsleep((caddr_t)mp, PVFS, "lookup", 0);
+ if (vfs_busy(mp, 0, 0, p))
continue;
- }
- error = VFS_ROOT(dp->v_mountedhere, &tdp);
+ error = VFS_ROOT(mp, &tdp);
+ vfs_unbusy(mp, p);
if (error)
goto bad2;
vput(dp);
@@ -533,12 +533,12 @@ nextname:
if (!wantparent)
vrele(ndp->ni_dvp);
if ((cnp->cn_flags & LOCKLEAF) == 0)
- VOP_UNLOCK(dp);
+ VOP_UNLOCK(dp, 0, p);
return (0);
bad2:
if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0')
- VOP_UNLOCK(ndp->ni_dvp);
+ VOP_UNLOCK(ndp->ni_dvp, 0, p);
vrele(ndp->ni_dvp);
bad:
vput(dp);
@@ -555,7 +555,8 @@ relookup(dvp, vpp, cnp)
struct vnode *dvp, **vpp;
struct componentname *cnp;
{
- register struct vnode *dp = 0; /* the directory we are searching */
+ struct proc *p = cnp->cn_proc;
+ 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 */
@@ -576,7 +577,7 @@ relookup(dvp, vpp, cnp)
rdonly = cnp->cn_flags & RDONLY;
cnp->cn_flags &= ~ISSYMLINK;
dp = dvp;
- VOP_LOCK(dp);
+ vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
/* dirloop: */
/*
@@ -615,7 +616,7 @@ relookup(dvp, vpp, cnp)
goto bad;
}
if (!(cnp->cn_flags & LOCKLEAF))
- VOP_UNLOCK(dp);
+ VOP_UNLOCK(dp, 0, p);
*vpp = dp;
if (cnp->cn_flags & SAVESTART)
panic("lookup: SAVESTART");
@@ -628,8 +629,7 @@ relookup(dvp, vpp, cnp)
/*
* We now have a segment name to search for, and a directory to search.
*/
- error = VOP_LOOKUP(dp, vpp, cnp);
- if (error) {
+ if (error = VOP_LOOKUP(dp, vpp, cnp)) {
#ifdef DIAGNOSTIC
if (*vpp != NULL)
panic("leaf should be empty");
@@ -675,16 +675,16 @@ relookup(dvp, vpp, cnp)
/* ASSERT(dvp == ndp->ni_startdir) */
if (cnp->cn_flags & SAVESTART)
VREF(dvp);
-
+
if (!wantparent)
vrele(dvp);
if ((cnp->cn_flags & LOCKLEAF) == 0)
- VOP_UNLOCK(dp);
+ VOP_UNLOCK(dp, 0, p);
return (0);
bad2:
if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
vrele(dvp);
bad:
vput(dp);
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index fb8061b..5a84570 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
* Copyright (c) 1995 Artisoft, Inc. All Rights Reserved.
*
@@ -61,26 +61,33 @@
/*
* GLOBALS
*/
-int (*mountroot) __P((void *));
+
+/*
+ * These define the root filesystem, device, and root filesystem type.
+ */
+struct mount *rootfs;
struct vnode *rootvnode;
-struct vfsops *mountrootvfsops;
+char *mountrootfsname;
+/*
+ * vfs_init() will set maxvfsconf
+ * to the highest defined type number.
+ */
+int maxvfsconf;
+struct vfsconf *vfsconf;
/*
* Common root mount code shared by all filesystems
*/
-#define ROOTDIR "/"
#define ROOTNAME "root_device"
-
-
/*
- * vfs_mountroot
+ * vfs_mountrootfs
*
* Common entry point for root mounts
*
* PARAMETERS:
- * data pointer to the vfs_ops for the FS type mounting
+ * fsname name of the filesystem
*
* RETURNS: 0 Success
* !0 error number (errno.h)
@@ -97,67 +104,44 @@ struct vfsops *mountrootvfsops;
* fixing the other file systems, not this code!
*/
int
-vfs_mountroot(data)
- void *data;
+vfs_mountrootfs(fsname)
+ char *fsname;
{
struct mount *mp;
- u_int size;
int err = 0;
struct proc *p = curproc; /* XXX */
- struct vfsops *mnt_op = (struct vfsops *)data;
/*
* New root mount structure
*/
- mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = mnt_op;
- mp->mnt_flag = MNT_ROOTFS;
- mp->mnt_vnodecovered = NULLVP;
-
- /*
- * Lock mount point
- */
- if( ( err = vfs_lock(mp)) != 0)
- goto error_1;
-
- /* Save "last mounted on" info for mount point (NULL pad)*/
- copystr( ROOTDIR, /* mount point*/
- mp->mnt_stat.f_mntonname, /* save area*/
- MNAMELEN - 1, /* max size*/
- &size); /* real size*/
- bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
-
- /* Save "mounted from" info for mount point (NULL pad)*/
- copystr( ROOTNAME, /* device name*/
- mp->mnt_stat.f_mntfromname, /* save area*/
- MNAMELEN - 1, /* max size*/
- &size); /* real size*/
- bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+ err = vfs_rootmountalloc(fsname, ROOTNAME, &mp);
+ if (err)
+ return (err);
+ mp->mnt_flag |= MNT_ROOTFS;
/*
* Attempt the mount
*/
- err = VFS_MOUNT( mp, NULL, NULL, NULL, p);
- if( err)
+ err = VFS_MOUNT(mp, NULL, NULL, NULL, p);
+ if (err)
goto error_2;
+ simple_lock(&mountlist_slock);
/* Add fs to list of mounted file systems*/
- CIRCLEQ_INSERT_TAIL( &mountlist, mp, mnt_list);
+ CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
- /* Unlock mount point*/
- vfs_unlock(mp);
+ vfs_unbusy(mp, p);
/* root mount, update system time from FS specific data*/
- inittodr( mp->mnt_time);
+ inittodr(mp->mnt_time);
goto success;
error_2: /* mount error*/
- /* unlock before failing*/
- vfs_unlock( mp);
+ vfs_unbusy(mp, p);
error_1: /* lock error*/
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 43f8669..0dea7bd 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94
+ * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
* $FreeBSD$
*/
@@ -75,7 +75,9 @@
#ifdef DDB
extern void printlockedvnodes __P((void));
#endif
-extern void vclean __P((struct vnode *vp, int flags));
+static void vclean __P((struct vnode *vp, int flags, struct proc *p));
+extern void vgonel __P((struct vnode *vp, struct proc *p));
+unsigned long numvnodes;
extern void vfs_unmountroot __P((struct mount *rootfs));
enum vtype iftovt_tab[16] = {
@@ -91,15 +93,19 @@ int vttoif_tab[9] = {
* Insq/Remq for the vnode usage lists.
*/
#define bufinsvn(bp, dp) LIST_INSERT_HEAD(dp, bp, b_vnbufs)
-#define bufremvn(bp) { \
- LIST_REMOVE(bp, b_vnbufs); \
- (bp)->b_vnbufs.le_next = NOLIST; \
+#define bufremvn(bp) { \
+ LIST_REMOVE(bp, b_vnbufs); \
+ (bp)->b_vnbufs.le_next = NOLIST; \
}
-
TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */
static u_long freevnodes = 0;
struct mntlist mountlist; /* mounted filesystem list */
+struct simplelock mountlist_slock;
+static struct simplelock mntid_slock;
+struct simplelock mntvnode_slock;
+struct simplelock vnode_free_list_slock;
+static struct simplelock spechash_slock;
int desiredvnodes;
SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RW, &desiredvnodes, 0, "");
@@ -117,164 +123,153 @@ vntblinit()
{
desiredvnodes = maxproc + vm_object_cache_max;
+ simple_lock_init(&mntvnode_slock);
+ simple_lock_init(&mntid_slock);
+ simple_lock_init(&spechash_slock);
TAILQ_INIT(&vnode_free_list);
+ simple_lock_init(&vnode_free_list_slock);
CIRCLEQ_INIT(&mountlist);
}
/*
- * Lock a filesystem.
- * Used to prevent access to it while mounting and unmounting.
+ * Mark a mount point as busy. Used to synchronize access and to delay
+ * unmounting. Interlock is not released on failure.
*/
int
-vfs_lock(mp)
- register struct mount *mp;
+vfs_busy(mp, flags, interlkp, p)
+ struct mount *mp;
+ int flags;
+ struct simplelock *interlkp;
+ struct proc *p;
{
+ int lkflags;
- while (mp->mnt_flag & MNT_MLOCK) {
+ if (mp->mnt_flag & MNT_UNMOUNT) {
+ if (flags & LK_NOWAIT)
+ return (ENOENT);
mp->mnt_flag |= MNT_MWAIT;
- (void) tsleep((caddr_t) mp, PVFS, "vfslck", 0);
+ 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.
+ */
+ tsleep((caddr_t)mp, PVFS, "vfs_busy", 0);
+ if (interlkp) {
+ simple_lock(interlkp);
+ }
+ return (ENOENT);
}
- mp->mnt_flag |= MNT_MLOCK;
+ lkflags = LK_SHARED;
+ if (interlkp)
+ lkflags |= LK_INTERLOCK;
+ if (lockmgr(&mp->mnt_lock, lkflags, interlkp, p))
+ panic("vfs_busy: unexpected lock failure");
return (0);
}
/*
- * Unlock a locked filesystem.
- * Panic if filesystem is not locked.
+ * Free a busy filesystem.
*/
void
-vfs_unlock(mp)
- register struct mount *mp;
+vfs_unbusy(mp, p)
+ struct mount *mp;
+ struct proc *p;
{
- if ((mp->mnt_flag & MNT_MLOCK) == 0)
- panic("vfs_unlock: not locked");
- mp->mnt_flag &= ~MNT_MLOCK;
- if (mp->mnt_flag & MNT_MWAIT) {
- mp->mnt_flag &= ~MNT_MWAIT;
- wakeup((caddr_t) mp);
- }
+ lockmgr(&mp->mnt_lock, LK_RELEASE, NULL, p);
}
/*
- * Mark a mount point as busy.
- * Used to synchronize access and to delay unmounting.
+ * 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_busy(mp)
- register struct mount *mp;
+vfs_rootmountalloc(fstypename, devname, mpp)
+ char *fstypename;
+ char *devname;
+ struct mount **mpp;
{
+ struct proc *p = curproc; /* XXX */
+ struct vfsconf *vfsp;
+ struct mount *mp;
- while (mp->mnt_flag & MNT_MPBUSY) {
- mp->mnt_flag |= MNT_MPWANT;
- (void) tsleep((caddr_t) &mp->mnt_flag, PVFS, "vfsbsy", 0);
- }
- if (mp->mnt_flag & MNT_UNMOUNT)
- return (1);
- mp->mnt_flag |= MNT_MPBUSY;
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (!strcmp(vfsp->vfc_name, fstypename))
+ break;
+ if (vfsp == NULL)
+ return (ENODEV);
+ mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
+ bzero((char *)mp, (u_long)sizeof(struct mount));
+ lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
+ (void)vfs_busy(mp, LK_NOWAIT, 0, p);
+ LIST_INIT(&mp->mnt_vnodelist);
+ mp->mnt_vfc = vfsp;
+ mp->mnt_op = vfsp->vfc_vfsops;
+ mp->mnt_flag = MNT_RDONLY;
+ mp->mnt_vnodecovered = NULLVP;
+ vfsp->vfc_refcount++;
+ mp->mnt_stat.f_type = vfsp->vfc_typenum;
+ mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
+ strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
+ mp->mnt_stat.f_mntonname[0] = '/';
+ mp->mnt_stat.f_mntonname[1] = 0;
+ (void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0);
+ *mpp = mp;
return (0);
}
/*
- * Free a busy filesystem.
- * Panic if filesystem is not busy.
- */
-void
-vfs_unbusy(mp)
- register 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);
- }
-}
-
-void
-vfs_unmountroot(struct mount *rootfs)
-{
- struct mount *mp = rootfs;
- int error;
-
- if (vfs_busy(mp)) {
- printf("failed to unmount root\n");
- return;
- }
- mp->mnt_flag |= MNT_UNMOUNT;
- if ((error = vfs_lock(mp))) {
- printf("lock of root filesystem failed (%d)\n", error);
- return;
- }
- vnode_pager_umount(mp); /* release cached vnodes */
- cache_purgevfs(mp); /* remove cache entries for this file sys */
-
- if ((error = VFS_SYNC(mp, MNT_WAIT, initproc->p_ucred, initproc)))
- printf("sync of root filesystem failed (%d)\n", error);
-
- if ((error = VFS_UNMOUNT(mp, MNT_FORCE, initproc))) {
- printf("unmount of root filesystem failed (");
- if (error == EBUSY)
- printf("BUSY)\n");
- else
- printf("%d)\n", error);
- }
- mp->mnt_flag &= ~MNT_UNMOUNT;
- vfs_unbusy(mp);
-}
-
-/*
- * Unmount all filesystems. Should only be called by halt().
+ * Find an appropriate filesystem to use for the root. If a filesystem
+ * has not been preselected, walk through the list of known filesystems
+ * trying those that have mountroot routines, and try them until one
+ * works or we have tried them all.
*/
-void
-vfs_unmountall()
+#ifdef notdef /* XXX JH */
+int
+lite2_vfs_mountroot(void)
{
- struct mount *mp, *nmp, *rootfs = NULL;
+ struct vfsconf *vfsp;
+ extern int (*lite2_mountroot)(void);
int error;
- /* unmount all but rootfs */
- for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
- nmp = mp->mnt_list.cqe_prev;
-
- if (mp->mnt_flag & MNT_ROOTFS) {
- rootfs = mp;
+ if (lite2_mountroot != NULL)
+ return ((*lite2_mountroot)());
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
+ if (vfsp->vfc_mountroot == NULL)
continue;
- }
- error = dounmount(mp, MNT_FORCE, initproc);
- if (error) {
- printf("unmount of %s failed (", mp->mnt_stat.f_mntonname);
- if (error == EBUSY)
- printf("BUSY)\n");
- else
- printf("%d)\n", error);
- }
- }
-
- /* and finally... */
- if (rootfs) {
- vfs_unmountroot(rootfs);
- } else {
- printf("no root filesystem\n");
+ if ((error = (*vfsp->vfc_mountroot)()) == 0)
+ return (0);
+ printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error);
}
+ return (ENODEV);
}
+#endif
/*
* 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) {
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);
}
@@ -282,14 +277,16 @@ getvfs(fsid)
* Get a new unique fsid
*/
void
-getnewfsid(mp, mtype)
+vfs_getnewfsid(mp)
struct mount *mp;
- int mtype;
{
static u_short xxxfs_mntid;
fsid_t tfsid;
+ int mtype;
+ simple_lock(&mntid_slock);
+ mtype = mp->mnt_vfc->vfc_typenum;
mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);
mp->mnt_stat.f_fsid.val[1] = mtype;
if (xxxfs_mntid == 0)
@@ -297,12 +294,13 @@ getnewfsid(mp, mtype)
tfsid.val[0] = makedev(nblkdev + mtype, 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);
}
/*
@@ -326,6 +324,35 @@ vattr_null(vap)
vap->va_vaflags = 0;
}
+void
+vfs_unmountroot(struct mount *rootfs)
+{
+ struct proc *p = curproc; /* XXX */
+ struct mount *mp = rootfs;
+ int error;
+
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ printf("failed to unmount root\n");
+ return;
+ }
+ mp->mnt_flag |= MNT_UNMOUNT;
+ vnode_pager_umount(mp); /* release cached vnodes */
+ cache_purgevfs(mp); /* remove cache entries for this file sys */
+
+ if ((error = VFS_SYNC(mp, MNT_WAIT, initproc->p_ucred, initproc)))
+ printf("sync of root filesystem failed (%d)\n", error);
+
+ if ((error = VFS_UNMOUNT(mp, MNT_FORCE, initproc))) {
+ printf("unmount of root filesystem failed (");
+ if (error == EBUSY)
+ printf("BUSY)\n");
+ else
+ printf("%d)\n", error);
+ }
+ mp->mnt_flag &= ~MNT_UNMOUNT;
+ vfs_unbusy(mp, p);
+}
+
/*
* Routines having to do with the management of the vnode table.
*/
@@ -341,10 +368,11 @@ getnewvnode(tag, mp, vops, vpp)
vop_t **vops;
struct vnode **vpp;
{
- register struct vnode *vp;
+ struct proc *p = curproc; /* XXX */
+ struct vnode *vp;
+ simple_lock(&vnode_free_list_slock);
retry:
- vp = vnode_free_list.tqh_first;
/*
* we allocate a new vnode if
* 1. we don't have any free
@@ -357,12 +385,31 @@ retry:
*/
if (freevnodes < (numvnodes >> 2) ||
numvnodes < desiredvnodes ||
- vp == NULL) {
+ vnode_free_list.tqh_first == NULL) {
+ 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 {
+ 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)
+ panic("free vnode isn't");
TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
if (vp->v_usage > 0) {
--vp->v_usage;
@@ -370,14 +417,16 @@ retry:
goto retry;
}
freevnodes--;
- if (vp->v_usecount)
- panic("free vnode isn't");
/* 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
{
@@ -421,6 +470,7 @@ insmntque(vp, mp)
register struct mount *mp;
{
+ simple_lock(&mntvnode_slock);
/*
* Delete from old mount point vnode list, if on one.
*/
@@ -429,9 +479,12 @@ insmntque(vp, mp)
/*
* Insert into list of vnodes for the new mount point, if available.
*/
- if ((vp->v_mount = mp) == NULL)
+ if ((vp->v_mount = mp) == NULL) {
+ simple_unlock(&mntvnode_slock);
return;
+ }
LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
+ simple_unlock(&mntvnode_slock);
}
/*
@@ -723,7 +776,8 @@ checkalias(nvp, nvp_rdev, mp)
dev_t nvp_rdev;
struct mount *mp;
{
- register struct vnode *vp;
+ struct proc *p = curproc; /* XXX */
+ struct vnode *vp;
struct vnode **vpp;
if (nvp->v_type != VBLK && nvp->v_type != VCHR)
@@ -731,18 +785,24 @@ checkalias(nvp, nvp_rdev, mp)
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))
+ simple_unlock(&spechash_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
goto loop;
+ }
+ simple_lock(&spechash_slock);
break;
}
@@ -753,16 +813,19 @@ loop:
nvp->v_hashchain = vpp;
nvp->v_specnext = *vpp;
nvp->v_specflags = 0;
+ simple_unlock(&spechash_slock);
*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, p);
+ 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;
@@ -779,47 +842,162 @@ loop:
* been changed to a new file system type).
*/
int
-vget(vp, lockflag)
+vget(vp, flags, p)
register struct vnode *vp;
- int lockflag;
+ int flags;
+ struct proc *p;
{
+ 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.
+ * If the vnode is in the process of being cleaned out for
+ * another use, we wait for the cleaning to finish and then
+ * return failure. Cleaning is determined by checking that
+ * the VXLOCK flag is set.
*/
- 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;
- (void) tsleep((caddr_t) vp, PINOD, "vget", 0);
- return (1);
+ simple_unlock(&vp->v_interlock);
+ tsleep((caddr_t)vp, PINOD, "vget", 0);
+ return (ENOENT);
}
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);
freevnodes--;
}
vp->v_usecount++;
-
/*
* Create the VM object, if needed
*/
if ((vp->v_type == VREG) &&
((vp->v_object == NULL) ||
(vp->v_object->flags & OBJ_VFS_REF) == 0)) {
+ /*
+ * XXX vfs_object_create probably needs the interlock.
+ */
+ simple_unlock(&vp->v_interlock);
vfs_object_create(vp, curproc, curproc->p_ucred, 0);
+ simple_lock(&vp->v_interlock);
+ }
+ if (flags & LK_TYPE_MASK) {
+ if (error = vn_lock(vp, flags | LK_INTERLOCK, p))
+ vrele(vp);
+ return (error);
}
- if (lockflag)
- VOP_LOCK(vp);
+ simple_unlock(&vp->v_interlock);
+ return (0);
+}
+
+/*
+ * Stubs to use when there is no locking to be done on the underlying object.
+ * A minimal shared lock is necessary to ensure that the underlying object
+ * is not revoked while an operation is in progress. So, an active shared
+ * count is maintained in an auxillary vnode lock structure.
+ */
+int
+vop_nolock(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+#ifdef notyet
+ /*
+ * This code cannot be used until all the non-locking filesystems
+ * (notably NFS) are converted to properly lock and release nodes.
+ * Also, certain vnode operations change the locking state within
+ * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
+ * and symlink). Ideally these operations should not change the
+ * lock state, but should be changed to let the caller of the
+ * function unlock them. Otherwise all intermediate vnode layers
+ * (such as union, umapfs, etc) must catch these functions to do
+ * the necessary locking at their layer. Note that the inactive
+ * and lookup operations also change their lock state, but this
+ * cannot be avoided, so these two operations will always need
+ * to be handled in intermediate layers.
+ */
+ struct vnode *vp = ap->a_vp;
+ int vnflags, flags = ap->a_flags;
+ if (vp->v_vnlock == NULL) {
+ if ((flags & LK_TYPE_MASK) == LK_DRAIN)
+ return (0);
+ MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
+ M_VNODE, M_WAITOK);
+ lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
+ }
+ switch (flags & LK_TYPE_MASK) {
+ case LK_DRAIN:
+ vnflags = LK_DRAIN;
+ break;
+ case LK_EXCLUSIVE:
+ case LK_SHARED:
+ vnflags = LK_SHARED;
+ break;
+ case LK_UPGRADE:
+ case LK_EXCLUPGRADE:
+ case LK_DOWNGRADE:
+ return (0);
+ case LK_RELEASE:
+ default:
+ panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
+ }
+ if (flags & LK_INTERLOCK)
+ vnflags |= LK_INTERLOCK;
+ return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
+#else /* for now */
+ /*
+ * Since we are not using the lock manager, we must clear
+ * the interlock here.
+ */
+ if (ap->a_flags & LK_INTERLOCK) {
+ simple_unlock(&ap->a_vp->v_interlock);
+ }
return (0);
+#endif
+}
+
+/*
+ * Decrement the active use count.
+ */
+int
+vop_nounlock(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ if (vp->v_vnlock == NULL)
+ return (0);
+ return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p));
+}
+
+/*
+ * Return whether or not the node is in use.
+ */
+int
+vop_noislocked(ap)
+ struct vop_islocked_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ if (vp->v_vnlock == NULL)
+ return (0);
+ return (lockstatus(vp->v_vnlock));
}
+/* #ifdef DIAGNOSTIC */
/*
* Vnode reference, just increment the count
*/
@@ -827,6 +1005,7 @@ void
vref(vp)
struct vnode *vp;
{
+ simple_lock(&vp->v_interlock);
if (vp->v_usecount <= 0)
panic("vref used where vget required");
@@ -840,8 +1019,11 @@ vref(vp)
* the object is created. This is necessary to
* keep the system from re-entrantly doing it
* multiple times.
+ * XXX vfs_object_create probably needs the interlock?
*/
+ simple_unlock(&vp->v_interlock);
vfs_object_create(vp, curproc, curproc->p_ucred, 0);
+ simple_lock(&vp->v_interlock);
}
}
@@ -850,9 +1032,9 @@ vref(vp)
*/
void
vput(vp)
- register struct vnode *vp;
+ struct vnode *vp;
{
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curproc);
vrele(vp);
}
@@ -862,33 +1044,38 @@ vput(vp)
*/
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 == 1) &&
vp->v_object &&
(vp->v_object->flags & OBJ_VFS_REF)) {
vp->v_object->flags &= ~OBJ_VFS_REF;
+ simple_unlock(&vp->v_interlock);
vm_object_deallocate(vp->v_object);
return;
}
- if (vp->v_usecount > 0)
+ if (vp->v_usecount > 0) {
+ simple_unlock(&vp->v_interlock);
return;
+ }
if (vp->v_usecount < 0) {
#ifdef DIAGNOSTIC
vprint("vrele: negative ref count", vp);
#endif
- panic("vrele: negative reference cnt");
+ panic("vrele: negative ref cnt");
}
+ simple_lock(&vnode_free_list_slock);
if (vp->v_flag & VAGE) {
if(vp->v_tag != VT_TFS)
TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
@@ -898,9 +1085,12 @@ vrele(vp)
if(vp->v_tag != VT_TFS)
TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
}
+ simple_unlock(&vnode_free_list_slock);
+
freevnodes++;
- VOP_INACTIVE(vp);
+ if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0)
+ VOP_INACTIVE(vp, p);
}
#ifdef DIAGNOSTIC
@@ -912,7 +1102,9 @@ vhold(vp)
register struct vnode *vp;
{
+ simple_lock(&vp->v_interlock);
vp->v_holdcnt++;
+ simple_unlock(&vp->v_interlock);
}
/*
@@ -923,9 +1115,11 @@ holdrele(vp)
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 */
@@ -948,11 +1142,11 @@ vflush(mp, skipvp, flags)
struct vnode *skipvp;
int flags;
{
- register struct vnode *vp, *nvp;
+ struct proc *p = curproc; /* XXX */
+ 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) {
/*
@@ -967,24 +1161,34 @@ loop:
*/
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.
*/
if ((flags & WRITECLOSE) &&
- (vp->v_writecount == 0 || vp->v_type != VREG))
+ (vp->v_writecount == 0 || vp->v_type != VREG)) {
+ simple_unlock(&vp->v_interlock);
continue;
+ }
if (vp->v_object && (vp->v_object->flags & OBJ_VFS_REF)) {
+ simple_unlock(&vp->v_interlock);
+ simple_unlock(&mntvnode_slock);
vm_object_reference(vp->v_object);
pager_cache(vp->v_object, FALSE);
vp->v_object->flags &= ~OBJ_VFS_REF;
vm_object_deallocate(vp->v_object);
+ simple_lock(&mntvnode_slock);
+ simple_lock(&vp->v_interlock);
}
/*
@@ -992,7 +1196,9 @@ loop:
* 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;
}
@@ -1002,21 +1208,25 @@ loop:
* 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 DIAGNOSTIC
if (busyprt)
vprint("vflush: busy vnode", vp);
#endif
+ simple_unlock(&vp->v_interlock);
busy++;
}
+ simple_unlock(&mntvnode_slock);
if (busy)
return (EBUSY);
return (0);
@@ -1025,8 +1235,8 @@ loop:
/*
* Disassociate the underlying file system from a vnode.
*/
-void
-vclean(struct vnode *vp, int flags)
+static void
+vclean(struct vnode *vp, int flags, struct proc *p)
{
int active;
@@ -1036,15 +1246,7 @@ vclean(struct vnode *vp, int flags)
* generate a race against ourselves to recycle it.
*/
if ((active = vp->v_usecount))
- 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);
+ vp->v_usecount++;
/*
* Prevent the vnode from being recycled or brought into use while we
* clean it out.
@@ -1053,31 +1255,48 @@ vclean(struct vnode *vp, int flags)
panic("vclean: deadlock");
vp->v_flag |= VXLOCK;
/*
- * Clean out any buffers associated with the vnode.
+ * 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.
*/
- if (flags & DOCLOSE)
- vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
+ VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, p);
/*
- * Any other processes trying to obtain this lock must first wait for
- * VXLOCK to clear, then call the new lock operation.
+ * Clean out any buffers associated with the vnode.
*/
- VOP_UNLOCK(vp);
+ if (flags & DOCLOSE)
+ vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0);
/*
- * If purging an active vnode, it must be closed and deactivated
- * before being reclaimed.
+ * If purging an active vnode, it must be closed and
+ * 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, p);
+ VOP_INACTIVE(vp, p);
+ } else {
+ /*
+ * Any other processes trying to obtain this lock must first
+ * wait for VXLOCK to clear, then call the new lock operation.
+ */
+ VOP_UNLOCK(vp, 0, p);
}
/*
* 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.
@@ -1092,46 +1311,91 @@ vclean(struct vnode *vp, int flags)
}
/*
- * Eliminate all activity associated with the requested vnode
+ * Eliminate all activity associated with the requested vnode
* and with all vnodes aliased to the requested vnode.
*/
-void
-vgoneall(vp)
- register struct vnode *vp;
+int
+vop_revoke(ap)
+ struct vop_revoke_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ } */ *ap;
{
- register struct vnode *vq;
+ struct vnode *vp, *vq;
+ struct proc *p = curproc; /* XXX */
+
+#ifdef DIAGNOSTIC
+ if ((ap->a_flags & REVOKEALL) == 0)
+ panic("vop_revoke");
+#endif
+
+ vp = ap->a_vp;
+ simple_lock(&vp->v_interlock);
if (vp->v_flag & VALIASED) {
/*
- * If a vgone (or vclean) is already in progress, wait until
- * it is done and return.
+ * If a vgone (or vclean) is already in progress,
+ * wait until it is done and return.
*/
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t) vp, PINOD, "vgall", 0);
- return;
+ 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.
+ * 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.
+ * 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;
}
- vgone(vp);
+ vgonel(vp, p);
+ return (0);
+}
+
+/*
+ * Recycle an unused vnode to the front of the free list.
+ * Release the passed interlock if the vnode will be recycled.
+ */
+int
+vrecycle(vp, inter_lkp, p)
+ struct vnode *vp;
+ struct simplelock *inter_lkp;
+ struct proc *p;
+{
+
+ simple_lock(&vp->v_interlock);
+ if (vp->v_usecount == 0) {
+ if (inter_lkp) {
+ simple_unlock(inter_lkp);
+ }
+ vgonel(vp, p);
+ return (1);
+ }
+ simple_unlock(&vp->v_interlock);
+ return (0);
}
/*
@@ -1142,16 +1406,31 @@ void
vgone(vp)
register 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)
+ struct vnode *vp;
+ struct proc *p;
+{
+ struct vnode *vq;
struct vnode *vx;
/*
- * If a vgone (or vclean) is already in progress, wait until it is
- * done and return.
+ * 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;
- (void) tsleep((caddr_t) vp, PINOD, "vgone", 0);
+ simple_unlock(&vp->v_interlock);
+ tsleep((caddr_t)vp, PINOD, "vgone", 0);
return;
}
@@ -1162,18 +1441,18 @@ vgone(vp)
/*
* Clean out the filesystem specific data.
*/
- vclean(vp, DOCLOSE);
+ vclean(vp, DOCLOSE, p);
/*
* Delete from old mount point vnode list, if on one.
*/
- if (vp->v_mount != NULL) {
- LIST_REMOVE(vp, v_mntvnodes);
- vp->v_mount = NULL;
- }
+ if (vp->v_mount != NULL)
+ insmntque(vp, (struct mount *)0);
/*
- * If special device, remove it from special device alias list.
+ * 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 {
@@ -1202,28 +1481,34 @@ vgone(vp)
vx->v_flag &= ~VALIASED;
vp->v_flag &= ~VALIASED;
}
+ simple_unlock(&spechash_slock);
FREE(vp->v_specinfo, M_VNODE);
vp->v_specinfo = NULL;
}
+
/*
- * If it is on the freelist and not already at the head, move it to
- * the head of the list. The test of the back pointer and the
- * reference count of zero is because it will be removed from the free
- * list by getnewvnode, but will not have its reference count
- * incremented until after calling vgone. If the reference count were
- * incremented first, vgone would (incorrectly) try to close the
- * previous instance of the underlying object. So, the back pointer is
- * explicitly set to `0xdeadb' in getnewvnode after removing it from
- * the freelist to ensure that we do not try to move it here.
+ * If it is on the freelist and not already at the head,
+ * move it to the head of the list. The test of the back
+ * pointer and the reference count of zero is because
+ * it will be removed from the free list by getnewvnode,
+ * but will not have its reference count incremented until
+ * after calling vgone. If the reference count were
+ * incremented first, vgone would (incorrectly) try to
+ * close the previous instance of the underlying object.
+ * So, the back pointer is explicitly set to `0xdeadb' in
+ * getnewvnode after removing it from the freelist to ensure
+ * that we do not try to move it here.
*/
- if (vp->v_usecount == 0 &&
- vp->v_freelist.tqe_prev != (struct vnode **) 0xdeadb &&
- vnode_free_list.tqh_first != vp) {
- if(vp->v_tag != VT_TFS) {
+ 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;
}
@@ -1254,7 +1539,7 @@ int
vcount(vp)
register struct vnode *vp;
{
- register struct vnode *vq, *vnext;
+ struct vnode *vq, *vnext;
int count;
loop:
@@ -1354,6 +1639,7 @@ int kinfo_vgetfailed;
static int
sysctl_vnode SYSCTL_HANDLER_ARGS
{
+ struct proc *p = curproc; /* XXX */
register struct mount *mp, *nmp;
struct vnode *vp;
int error;
@@ -1368,7 +1654,7 @@ sysctl_vnode SYSCTL_HANDLER_ARGS
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, p))
continue;
again:
for (vp = mp->mnt_vnodelist.lh_first;
@@ -1386,11 +1672,11 @@ again:
}
if ((error = SYSCTL_OUT(req, &vp, VPTRSZ)) ||
(error = SYSCTL_OUT(req, vp, VNODESZ))) {
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
return (error);
}
}
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
return (0);
@@ -1404,22 +1690,63 @@ SYSCTL_PROC(_kern, KERN_VNODE, vnode, CTLTYPE_OPAQUE|CTLFLAG_RD,
*/
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 (error);
+}
+
+/*
+ * Unmount all filesystems. The list is traversed in reverse order
+ * of mounting to avoid dependencies. Should only be called by halt().
+ */
+void
+vfs_unmountall()
+{
+ struct mount *mp, *nmp, *rootfs = NULL;
+ int error;
+
+ /* unmount all but rootfs */
+ for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
+ nmp = mp->mnt_list.cqe_prev;
+
+ if (mp->mnt_flag & MNT_ROOTFS) {
+ rootfs = mp;
+ continue;
+ }
+ error = dounmount(mp, MNT_FORCE, initproc);
+ if (error) {
+ printf("unmount of %s failed (", mp->mnt_stat.f_mntonname);
+ if (error == EBUSY)
+ printf("BUSY)\n");
+ else
+ printf("%d)\n", error);
+ }
+ }
+
+ /* and finally... */
+ if (rootfs) {
+ vfs_unmountroot(rootfs);
+ } else {
+ printf("no root filesystem\n");
}
- return (0);
}
/*
@@ -1565,8 +1892,8 @@ vfs_export_lookup(mp, nep, nam)
rnh = nep->ne_rtable[saddr->sa_family];
if (rnh != NULL) {
np = (struct netcred *)
- (*rnh->rnh_matchaddr) ((caddr_t) saddr,
- rnh);
+ (*rnh->rnh_matchaddr)((caddr_t)saddr,
+ rnh);
if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
np = NULL;
}
@@ -1580,7 +1907,6 @@ vfs_export_lookup(mp, nep, nam)
return (np);
}
-
/*
* perform msync on all vnodes under a mount point
* the mount point must be locked.
@@ -1639,10 +1965,10 @@ retry:
} else {
if (object->flags & OBJ_DEAD) {
if (waslocked)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
tsleep(object, PVM, "vodead", 0);
if (waslocked)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
goto retry;
}
if ((object->flags & OBJ_VFS_REF) == 0) {
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 22e16d84..83b6dec 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -50,6 +50,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/namei.h>
#include <sys/filedesc.h>
@@ -64,9 +65,11 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
+/* see if this is needed XXX JH
#ifdef UNION
#include <miscfs/union/union.h>
#endif
+*/
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -74,7 +77,8 @@
#include <vm/vm_extern.h>
#include <sys/sysctl.h>
-static int change_dir __P((struct nameidata *ndp, struct proc *p));
+static int change_dir __P((struct nameidata *ndp, struct proc *p));
+static void checkdirs __P((struct vnode *olddp));
/*
* Virtual File System System Calls
@@ -85,7 +89,7 @@ static int change_dir __P((struct nameidata *ndp, struct proc *p));
*/
#ifndef _SYS_SYSPROTO_H_
struct mount_args {
- int type;
+ char *type;
char *path;
int flags;
caddr_t data;
@@ -95,29 +99,32 @@ struct mount_args {
int
mount(p, uap, retval)
struct proc *p;
- register struct mount_args *uap;
- int *retval;
+ register struct mount_args /* {
+ syscallarg(char *) type;
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(caddr_t) data;
+ } */ *uap;
+ register_t *retval;
{
- register struct vnode *vp;
- register struct mount *mp;
+ struct vnode *vp;
+ struct mount *mp;
+ struct vfsconf *vfsp;
int error, flag = 0;
+ struct vattr va;
+ u_long fstypenum;
struct nameidata nd;
+ char fstypename[MFSNAMELEN];
/*
- * Must be super user
- */
- error = suser(p->p_ucred, &p->p_acflag);
- if (error)
- return (error);
- /*
* Get vnode to be covered
*/
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- if (uap->flags & MNT_UPDATE) {
+ if (SCARG(uap, flags) & MNT_UPDATE) {
if ((vp->v_flag & VROOT) == 0) {
vput(vp);
return (EINVAL);
@@ -128,68 +135,135 @@ mount(p, uap, retval)
* We only allow the filesystem to be reloaded if it
* is currently mounted read-only.
*/
- if ((uap->flags & MNT_RELOAD) &&
+ if ((SCARG(uap, flags) & MNT_RELOAD) &&
((mp->mnt_flag & MNT_RDONLY) == 0)) {
vput(vp);
return (EOPNOTSUPP); /* Needs translation */
}
mp->mnt_flag |=
- uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
- VOP_UNLOCK(vp);
+ SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
+ /*
+ * Only root, or the user that did the original mount is
+ * permitted to update it.
+ */
+ if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
+ (error = suser(p->p_ucred, &p->p_acflag))) {
+ vput(vp);
+ return (error);
+ }
+ /*
+ * Do not allow NFS export by non-root users. Silently
+ * enforce MNT_NOSUID and MNT_NODEV for non-root users.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ if (SCARG(uap, flags) & MNT_EXPORTED) {
+ vput(vp);
+ return (EPERM);
+ }
+ SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
+ }
+ if (vfs_busy(mp, LK_NOWAIT, 0, p)) {
+ vput(vp);
+ return (EBUSY);
+ }
+ VOP_UNLOCK(vp, 0, p);
goto update;
}
- error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0);
- if (error)
+ /*
+ * If the user is not root, ensure that they own the directory
+ * onto which we are attempting to mount.
+ */
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) ||
+ (va.va_uid != p->p_ucred->cr_uid &&
+ (error = suser(p->p_ucred, &p->p_acflag)))) {
+ vput(vp);
+ return (error);
+ }
+ /*
+ * Do not allow NFS export by non-root users. Silently
+ * enforce MNT_NOSUID and MNT_NODEV for non-root users.
+ */
+ if (p->p_ucred->cr_uid != 0) {
+ if (SCARG(uap, flags) & MNT_EXPORTED) {
+ vput(vp);
+ return (EPERM);
+ }
+ SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
+ }
+ if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0))
return (error);
if (vp->v_type != VDIR) {
vput(vp);
return (ENOTDIR);
}
- if ((u_long)uap->type > MOUNT_MAXTYPE || vfssw[uap->type] == NULL) {
- vput(vp);
- return (ENODEV);
- }
-
+#ifdef COMPAT_43
/*
- * Allocate and initialize the file system.
+ * Historically filesystem types were identified by number. If we
+ * get an integer for the filesystem type instead of a string, we
+ * check to see if it matches one of the historic filesystem types.
*/
- mp = (struct mount *)malloc((u_long)sizeof(struct mount),
- M_MOUNT, M_WAITOK);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = vfssw[uap->type];
- mp->mnt_vfc = vfsconf[uap->type];
- error = vfs_lock(mp);
- if (error) {
- free((caddr_t)mp, M_MOUNT);
+ fstypenum = (u_long)SCARG(uap, type);
+ if (fstypenum < maxvfsconf) {
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (vfsp->vfc_typenum == fstypenum)
+ break;
+ if (vfsp == NULL) {
+ vput(vp);
+ return (ENODEV);
+ }
+ strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN);
+ } else
+#endif /* COMPAT_43 */
+ if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) {
vput(vp);
return (error);
}
+ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
+ if (!strcmp(vfsp->vfc_name, fstypename))
+ break;
+ if (vfsp == NULL) {
+ vput(vp);
+ return (ENODEV);
+ }
if (vp->v_mountedhere != NULL) {
- vfs_unlock(mp);
- free((caddr_t)mp, M_MOUNT);
vput(vp);
return (EBUSY);
}
+
+ /*
+ * Allocate and initialize the filesystem.
+ */
+ 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, p);
+ mp->mnt_op = vfsp->vfc_vfsops;
+ mp->mnt_vfc = vfsp;
+ vfsp->vfc_refcount++;
+ mp->mnt_stat.f_type = vfsp->vfc_typenum;
+ mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
+ strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
vp->v_mountedhere = mp;
mp->mnt_vnodecovered = vp;
- vfsconf[uap->type]->vfc_refcount++;
-
+ mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
update:
/*
* Set the mount level flags.
*/
- if (uap->flags & MNT_RDONLY)
+ if (SCARG(uap, flags) & MNT_RDONLY)
mp->mnt_flag |= MNT_RDONLY;
else if (mp->mnt_flag & MNT_RDONLY)
mp->mnt_flag |= MNT_WANTRDWR;
mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME);
- mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
- MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE | MNT_NOATIME);
+ mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
+ MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
+ MNT_NOATIME);
/*
* Mount the filesystem.
*/
- error = VFS_MOUNT(mp, uap->path, uap->data, &nd, p);
+ error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
if (mp->mnt_flag & MNT_UPDATE) {
vrele(vp);
if (mp->mnt_flag & MNT_WANTRDWR)
@@ -198,6 +272,7 @@ update:
(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
if (error)
mp->mnt_flag = flag;
+ vfs_unbusy(mp, p);
return (error);
}
/*
@@ -205,23 +280,63 @@ update:
*/
cache_purge(vp);
if (!error) {
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
- VOP_UNLOCK(vp);
- vfs_unlock(mp);
- error = VFS_START(mp, 0, p);
- if (error)
+ simple_unlock(&mountlist_slock);
+ checkdirs(vp);
+ VOP_UNLOCK(vp, 0, p);
+ vfs_unbusy(mp, p);
+ if (error = VFS_START(mp, 0, p))
vrele(vp);
} else {
mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
- vfs_unlock(mp);
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
free((caddr_t)mp, M_MOUNT);
vput(vp);
- vfsconf[uap->type]->vfc_refcount--;
}
return (error);
}
/*
+ * Scan all active processes to see if any of them have a current
+ * or root directory onto which the new filesystem has just been
+ * mounted. If so, replace them with the new mount point.
+ */
+static void
+checkdirs(olddp)
+ struct vnode *olddp;
+{
+ struct filedesc *fdp;
+ struct vnode *newdp;
+ struct proc *p;
+
+ if (olddp->v_usecount == 1)
+ return;
+ if (VFS_ROOT(olddp->v_mountedhere, &newdp))
+ panic("mount: lost mount");
+ for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
+ fdp = p->p_fd;
+ if (fdp->fd_cdir == olddp) {
+ vrele(fdp->fd_cdir);
+ VREF(newdp);
+ fdp->fd_cdir = newdp;
+ }
+ if (fdp->fd_rdir == olddp) {
+ vrele(fdp->fd_rdir);
+ VREF(newdp);
+ fdp->fd_rdir = newdp;
+ }
+ }
+ if (rootvnode == olddp) {
+ vrele(rootvnode);
+ VREF(newdp);
+ rootvnode = newdp;
+ }
+ vput(newdp);
+}
+
+/*
* Unmount a file system.
*
* Note: unmount takes a path to the vnode mounted on as argument,
@@ -237,47 +352,51 @@ struct unmount_args {
int
unmount(p, uap, retval)
struct proc *p;
- register struct unmount_args *uap;
- int *retval;
+ register struct unmount_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct mount *mp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
+ mp = vp->v_mount;
/*
- * Unless this is a user mount, then must
- * have suser privilege.
+ * Only root, or the user that did the original mount is
+ * permitted to unmount this filesystem.
*/
- if (((vp->v_mount->mnt_flag & MNT_USER) == 0) &&
+ if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
(error = suser(p->p_ucred, &p->p_acflag))) {
vput(vp);
return (error);
}
/*
- * Must be the root of the filesystem
+ * Don't allow unmounting the root file system.
*/
- if ((vp->v_flag & VROOT) == 0) {
+ if (mp->mnt_flag & MNT_ROOTFS) {
vput(vp);
return (EINVAL);
}
- mp = vp->v_mount;
- vput(vp);
/*
- * Don't allow unmount of the root filesystem
+ * Must be the root of the filesystem
*/
- if (mp->mnt_flag & MNT_ROOTFS)
+ if ((vp->v_flag & VROOT) == 0) {
+ vput(vp);
return (EINVAL);
-
- return (dounmount(mp, uap->flags, p));
+ }
+ vput(vp);
+ return (dounmount(mp, SCARG(uap, flags), p));
}
/*
@@ -292,74 +411,86 @@ dounmount(mp, flags, p)
struct vnode *coveredvp;
int error;
- coveredvp = mp->mnt_vnodecovered;
- if (vfs_busy(mp))
- return (EBUSY);
+ simple_lock(&mountlist_slock);
mp->mnt_flag |= MNT_UNMOUNT;
- error = vfs_lock(mp);
- if (error)
- return (error);
-
+ lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock, p);
mp->mnt_flag &=~ MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
vnode_pager_umount(mp); /* release cached vnodes */
cache_purgevfs(mp); /* remove cache entries for this file sys */
- if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 ||
+ 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 {
+ mp->mnt_flag &= ~MNT_UNMOUNT;
+ lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
+ &mountlist_slock, p);
+ return (error);
+ }
+ CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
+ if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
+ coveredvp->v_mountedhere = (struct mount *)0;
vrele(coveredvp);
- CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
- mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0;
- vfs_unlock(mp);
- mp->mnt_vfc->vfc_refcount--;
- if (mp->mnt_vnodelist.lh_first != NULL)
- panic("unmount: dangling vnode");
- free((caddr_t)mp, M_MOUNT);
}
- return (error);
+ mp->mnt_vfc->vfc_refcount--;
+ if (mp->mnt_vnodelist.lh_first != NULL)
+ panic("unmount: dangling vnode");
+ lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock, p);
+ if (mp->mnt_flag & MNT_MWAIT)
+ wakeup((caddr_t)mp);
+ free((caddr_t)mp, M_MOUNT);
+ return (0);
}
/*
* Sync each mounted filesystem.
*/
-
#ifndef _SYS_SYSPROTO_H_
struct sync_args {
int dummy;
};
#endif
+#ifdef DEBUG
+int syncprt = 0;
+SYSCTL_INT(_debug, 0, syncprt, CTLFLAG_RW, &syncprt, 0, "");
+#endif
+
/* ARGSUSED */
int
sync(p, uap, retval)
struct proc *p;
struct sync_args *uap;
- int *retval;
+ register_t *retval;
{
- register struct mount *mp;
+ register struct mount *mp, *nmp;
int asyncflag;
- for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = mp->mnt_list.cqe_next) {
- /*
- * 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)) {
+ simple_lock(&mountlist_slock);
+ for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nmp = mp->mnt_list.cqe_next;
+ continue;
+ }
+ if ((mp->mnt_flag & MNT_RDONLY) == 0) {
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
- vfs_unbusy(mp);
}
+ simple_lock(&mountlist_slock);
+ nmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
+#ifdef DIAGNOSTIC
+ if (syncprt)
+ vfs_bufstats();
+#endif /* DIAGNOSTIC */
return (0);
}
@@ -378,20 +509,25 @@ struct quotactl_args {
int
quotactl(p, uap, retval)
struct proc *p;
- register struct quotactl_args *uap;
- int *retval;
+ register struct quotactl_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) cmd;
+ syscallarg(int) uid;
+ syscallarg(caddr_t) arg;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
mp = nd.ni_vp->v_mount;
vrele(nd.ni_vp);
- return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p));
+ return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
+ SCARG(uap, arg), p));
}
/*
@@ -407,17 +543,19 @@ struct statfs_args {
int
statfs(p, uap, retval)
struct proc *p;
- register struct statfs_args *uap;
- int *retval;
+ register struct statfs_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct statfs *) buf;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp;
register struct statfs *sp;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
mp = nd.ni_vp->v_mount;
sp = &mp->mnt_stat;
@@ -426,7 +564,7 @@ statfs(p, uap, retval)
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
+ return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
}
/*
@@ -442,16 +580,18 @@ struct fstatfs_args {
int
fstatfs(p, uap, retval)
struct proc *p;
- register struct fstatfs_args *uap;
- int *retval;
+ register struct fstatfs_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct statfs *) buf;
+ } */ *uap;
+ register_t *retval;
{
struct file *fp;
struct mount *mp;
register struct statfs *sp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
mp = ((struct vnode *)fp->f_data)->v_mount;
sp = &mp->mnt_stat;
@@ -459,7 +599,7 @@ fstatfs(p, uap, retval)
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)));
+ return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
}
/*
@@ -475,48 +615,55 @@ struct getfsstat_args {
int
getfsstat(p, uap, retval)
struct proc *p;
- register struct getfsstat_args *uap;
- int *retval;
+ register struct getfsstat_args /* {
+ syscallarg(struct statfs *) buf;
+ syscallarg(long) bufsize;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct mount *mp, *nmp;
register struct statfs *sp;
caddr_t sfsp;
long count, maxcount, error;
- maxcount = uap->bufsize / sizeof(struct statfs);
- sfsp = (caddr_t)uap->buf;
+ maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
+ sfsp = (caddr_t)SCARG(uap, buf);
count = 0;
+ simple_lock(&mountlist_slock);
for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
- if (vfs_busy(mp)) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
nmp = mp->mnt_list.cqe_next;
continue;
}
- if (sfsp && count < maxcount &&
- ((mp->mnt_flag & MNT_MLOCK) == 0)) {
+ if (sfsp && count < maxcount) {
sp = &mp->mnt_stat;
/*
* If MNT_NOWAIT is specified, do not refresh the
* fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
*/
- if (((uap->flags & MNT_NOWAIT) == 0 ||
- (uap->flags & MNT_WAIT)) &&
+ if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
+ (SCARG(uap, flags) & MNT_WAIT)) &&
(error = VFS_STATFS(mp, sp, p))) {
+ simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
continue;
}
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
if (error) {
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
return (error);
}
sfsp += sizeof(*sp);
}
count++;
+ simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
if (sfsp && count > maxcount)
*retval = maxcount;
else
@@ -536,27 +683,41 @@ struct fchdir_args {
int
fchdir(p, uap, retval)
struct proc *p;
- struct fchdir_args *uap;
- int *retval;
+ struct fchdir_args /* {
+ syscallarg(int) fd;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
- register struct vnode *vp;
+ struct vnode *vp, *tdp;
+ struct mount *mp;
struct file *fp;
int error;
- error = getvnode(fdp, uap->fd, &fp);
- if (error)
+ if (error = getvnode(fdp, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- VOP_LOCK(vp);
+ VREF(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type != VDIR)
error = ENOTDIR;
else
error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
- VOP_UNLOCK(vp);
- if (error)
+ while (!error && (mp = vp->v_mountedhere) != NULL) {
+ if (vfs_busy(mp, 0, 0, p))
+ continue;
+ error = VFS_ROOT(mp, &tdp);
+ vfs_unbusy(mp, p);
+ if (error)
+ break;
+ vput(vp);
+ vp = tdp;
+ }
+ if (error) {
+ vput(vp);
return (error);
- VREF(vp);
+ }
+ VOP_UNLOCK(vp, 0, p);
vrele(fdp->fd_cdir);
fdp->fd_cdir = vp;
return (0);
@@ -574,16 +735,18 @@ struct chdir_args {
int
chdir(p, uap, retval)
struct proc *p;
- struct chdir_args *uap;
- int *retval;
+ struct chdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = change_dir(&nd, p);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = change_dir(&nd, p))
return (error);
vrele(fdp->fd_cdir);
fdp->fd_cdir = nd.ni_vp;
@@ -602,8 +765,10 @@ struct chroot_args {
int
chroot(p, uap, retval)
struct proc *p;
- struct chroot_args *uap;
- int *retval;
+ struct chroot_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
int error;
@@ -612,9 +777,9 @@ chroot(p, uap, retval)
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = change_dir(&nd, p);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = change_dir(&nd, p))
return (error);
if (fdp->fd_rdir != NULL)
vrele(fdp->fd_rdir);
@@ -641,9 +806,10 @@ change_dir(ndp, p)
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, p);
return (error);
}
@@ -661,8 +827,12 @@ struct open_args {
int
open(p, uap, retval)
struct proc *p;
- register struct open_args *uap;
- int *retval;
+ register struct open_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct filedesc *fdp = p->p_fd;
register struct file *fp;
@@ -677,17 +847,17 @@ open(p, uap, retval)
if (error)
return (error);
fp = nfp;
- flags = FFLAGS(uap->flags);
- cmode = ((uap->mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
+ flags = FFLAGS(SCARG(uap, flags));
+ cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
p->p_dupfd = -indx - 1; /* XXX check for fdopen */
error = vn_open(&nd, flags, cmode);
if (error) {
ffree(fp);
if ((error == ENODEV || error == ENXIO) &&
- p->p_dupfd >= 0 && /* XXX from fdopen */
+ p->p_dupfd >= 0 && /* XXX from fdopen */
(error =
- dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
+ dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {
*retval = indx;
return (0);
}
@@ -714,18 +884,17 @@ open(p, uap, retval)
type = F_FLOCK;
if ((flags & FNONBLOCK) == 0)
type |= F_WAIT;
- VOP_UNLOCK(vp);
- error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
- if (error) {
+ VOP_UNLOCK(vp, 0, p);
+ if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
ffree(fp);
fdp->fd_ofiles[indx] = NULL;
return (error);
}
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
fp->f_flag |= FHASLOCK;
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
*retval = indx;
return (0);
}
@@ -743,15 +912,22 @@ struct ocreat_args {
int
ocreat(p, uap, retval)
struct proc *p;
- register struct ocreat_args *uap;
- int *retval;
+ register struct ocreat_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
- struct open_args openuap;
-
- openuap.path = uap->path;
- openuap.mode = uap->mode;
- openuap.flags = O_WRONLY | O_CREAT | O_TRUNC;
- return (open(p, &openuap, retval));
+ struct open_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+ } */ nuap;
+
+ SCARG(&nuap, path) = SCARG(uap, path);
+ SCARG(&nuap, mode) = SCARG(uap, mode);
+ SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
+ return (open(p, &nuap, retval));
}
#endif /* COMPAT_43 */
@@ -769,30 +945,35 @@ struct mknod_args {
int
mknod(p, uap, retval)
struct proc *p;
- register struct mknod_args *uap;
- int *retval;
+ register struct mknod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ syscallarg(int) dev;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
+ int whiteout;
struct nameidata nd;
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp != NULL)
error = EEXIST;
else {
VATTR_NULL(&vattr);
- vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
- vattr.va_rdev = uap->dev;
+ vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
+ vattr.va_rdev = SCARG(uap, dev);
+ whiteout = 0;
- switch (uap->mode & S_IFMT) {
+ switch (SCARG(uap, mode) & S_IFMT) {
case S_IFMT: /* used by badsect to flag bad sectors */
vattr.va_type = VBAD;
break;
@@ -802,14 +983,25 @@ mknod(p, uap, retval)
case S_IFBLK:
vattr.va_type = VBLK;
break;
+ case S_IFWHT:
+ whiteout = 1;
+ break;
default:
error = EINVAL;
break;
}
}
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ if (whiteout) {
+ error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
+ if (error)
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ vput(nd.ni_dvp);
+ } else {
+ error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
+ &nd.ni_cnd, &vattr);
+ }
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == vp)
@@ -823,7 +1015,7 @@ mknod(p, uap, retval)
}
/*
- * Create named pipe.
+ * Create a named pipe.
*/
#ifndef _SYS_SYSPROTO_H_
struct mkfifo_args {
@@ -835,16 +1027,21 @@ struct mkfifo_args {
int
mkfifo(p, uap, retval)
struct proc *p;
- register struct mkfifo_args *uap;
- int *retval;
+ register struct mkfifo_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
+#ifndef FIFO
+ return (EOPNOTSUPP);
+#else
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
if (nd.ni_vp != NULL) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -857,9 +1054,10 @@ mkfifo(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VFIFO;
- vattr.va_mode = (uap->mode & ALLPERMS) &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
+#endif /* FIFO */
}
/*
@@ -875,22 +1073,24 @@ struct link_args {
int
link(p, uap, retval)
struct proc *p;
- register struct link_args *uap;
- int *retval;
+ register struct link_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) link;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct nameidata nd;
int error;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
else {
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
error = namei(&nd);
if (!error) {
if (nd.ni_vp != NULL) {
@@ -903,10 +1103,9 @@ link(p, uap, retval)
vrele(nd.ni_vp);
error = EEXIST;
} else {
- LEASE_CHECK(nd.ni_dvp,
- p, p->p_ucred, LEASE_WRITE);
- LEASE_CHECK(vp,
- p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred,
+ LEASE_WRITE);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
}
}
@@ -928,8 +1127,11 @@ struct symlink_args {
int
symlink(p, uap, retval)
struct proc *p;
- register struct symlink_args *uap;
- int *retval;
+ register struct symlink_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) link;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
char *path;
@@ -937,12 +1139,10 @@ symlink(p, uap, retval)
struct nameidata nd;
MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
- error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
- if (error)
+ if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL))
goto out;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->link, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
+ if (error = namei(&nd))
goto out;
if (nd.ni_vp) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -956,7 +1156,7 @@ symlink(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
out:
FREE(path, M_NAMEI);
@@ -964,6 +1164,45 @@ out:
}
/*
+ * Delete a whiteout from the filesystem.
+ */
+/* ARGSUSED */
+int
+undelete(p, uap, retval)
+ struct proc *p;
+ register struct undelete_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
+{
+ int error;
+ struct nameidata nd;
+
+ NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ error = namei(&nd);
+ if (error)
+ return (error);
+
+ if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (nd.ni_vp)
+ vrele(nd.ni_vp);
+ return (EEXIST);
+ }
+
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE))
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ vput(nd.ni_dvp);
+ return (error);
+}
+
+/*
* Delete a name from the filesystem.
*/
#ifndef _SYS_SYSPROTO_H_
@@ -975,20 +1214,21 @@ struct unlink_args {
int
unlink(p, uap, retval)
struct proc *p;
- struct unlink_args *uap;
- int *retval;
+ struct unlink_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
int error;
struct nameidata nd;
- NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EPERM; /* POSIX */
@@ -1001,11 +1241,11 @@ unlink(p, uap, retval)
if (vp->v_flag & VROOT)
error = EBUSY;
else
- (void) vnode_pager_uncache(vp);
+ (void) vnode_pager_uncache(vp, p);
}
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -1013,7 +1253,8 @@ unlink(p, uap, retval)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
- vput(vp);
+ if (vp != NULLVP)
+ vput(vp);
}
return (error);
}
@@ -1032,8 +1273,13 @@ struct lseek_args {
int
lseek(p, uap, retval)
struct proc *p;
- register struct lseek_args *uap;
- int *retval;
+ register struct lseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) offset;
+ syscallarg(int) whence;
+ } */ *uap;
+ register_t *retval; /* XXX */
{
struct ucred *cred = p->p_ucred;
register struct filedesc *fdp = p->p_fd;
@@ -1041,23 +1287,23 @@ lseek(p, uap, retval)
struct vattr vattr;
int error;
- if ((u_int)uap->fd >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[uap->fd]) == NULL)
+ if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
return (EBADF);
if (fp->f_type != DTYPE_VNODE)
return (ESPIPE);
- switch (uap->whence) {
+ switch (SCARG(uap, whence)) {
case L_INCR:
- fp->f_offset += uap->offset;
+ fp->f_offset += SCARG(uap, offset);
break;
case L_XTND:
error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
if (error)
return (error);
- fp->f_offset = uap->offset + vattr.va_size;
+ fp->f_offset = SCARG(uap, offset) + vattr.va_size;
break;
case L_SET:
- fp->f_offset = uap->offset;
+ fp->f_offset = SCARG(uap, offset);
break;
default:
return (EINVAL);
@@ -1080,17 +1326,26 @@ struct olseek_args {
int
olseek(p, uap, retval)
struct proc *p;
- register struct olseek_args *uap;
- int *retval;
+ register struct olseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(long) offset;
+ syscallarg(int) whence;
+ } */ *uap;
+ register_t *retval;
{
- struct lseek_args nuap;
+ struct lseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) offset;
+ syscallarg(int) whence;
+ } */ nuap;
off_t qret;
int error;
- nuap.fd = uap->fd;
- nuap.offset = uap->offset;
- nuap.whence = uap->whence;
- error = lseek(p, &nuap, (int *)&qret);
+ SCARG(&nuap, fd) = SCARG(uap, fd);
+ SCARG(&nuap, offset) = SCARG(uap, offset);
+ SCARG(&nuap, whence) = SCARG(uap, whence);
+ error = lseek(p, &nuap, (register_t *) &qret);
*(long *)retval = qret;
return (error);
}
@@ -1108,8 +1363,11 @@ struct access_args {
int
access(p, uap, retval)
struct proc *p;
- register struct access_args *uap;
- int *retval;
+ register struct access_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct ucred *cred = p->p_ucred;
register struct vnode *vp;
@@ -1120,20 +1378,20 @@ access(p, uap, retval)
t_gid = cred->cr_groups[0];
cred->cr_uid = p->p_cred->p_ruid;
cred->cr_groups[0] = p->p_cred->p_rgid;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
goto out1;
vp = nd.ni_vp;
/* Flags == 0 means only check for existence. */
- if (uap->flags) {
+ if (SCARG(uap, flags)) {
flags = 0;
- if (uap->flags & R_OK)
+ if (SCARG(uap, flags) & R_OK)
flags |= VREAD;
- if (uap->flags & W_OK)
+ if (SCARG(uap, flags) & W_OK)
flags |= VWRITE;
- if (uap->flags & X_OK)
+ if (SCARG(uap, flags) & X_OK)
flags |= VEXEC;
if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
error = VOP_ACCESS(vp, flags, cred, p);
@@ -1159,24 +1417,27 @@ struct ostat_args {
int
ostat(p, uap, retval)
struct proc *p;
- register struct ostat_args *uap;
- int *retval;
+ register struct ostat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct ostat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct stat sb;
struct ostat osb;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
error = vn_stat(nd.ni_vp, &sb, p);
vput(nd.ni_vp);
if (error)
return (error);
cvtstat(&sb, &osb);
- error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
+ error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
return (error);
}
@@ -1193,8 +1454,11 @@ struct olstat_args {
int
olstat(p, uap, retval)
struct proc *p;
- register struct olstat_args *uap;
- int *retval;
+ register struct olstat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct ostat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct vnode *vp, *dvp;
struct stat sb, sb1;
@@ -1203,9 +1467,8 @@ olstat(p, uap, retval)
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
- uap->path, p);
- error = namei(&nd);
- if (error)
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
/*
* For symbolic links, always return the attributes of its
@@ -1240,7 +1503,7 @@ olstat(p, uap, retval)
sb.st_blocks = sb1.st_blocks;
}
cvtstat(&sb, &osb);
- error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb));
+ error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
return (error);
}
@@ -1287,22 +1550,25 @@ struct stat_args {
int
stat(p, uap, retval)
struct proc *p;
- register struct stat_args *uap;
- int *retval;
+ register struct stat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct stat *) ub;
+ } */ *uap;
+ register_t *retval;
{
struct stat sb;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
error = vn_stat(nd.ni_vp, &sb, p);
vput(nd.ni_vp);
if (error)
return (error);
- error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
+ error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
return (error);
}
@@ -1319,8 +1585,11 @@ struct lstat_args {
int
lstat(p, uap, retval)
struct proc *p;
- register struct lstat_args *uap;
- int *retval;
+ register struct lstat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct stat *) ub;
+ } */ *uap;
+ register_t *retval;
{
int error;
struct vnode *vp, *dvp;
@@ -1328,13 +1597,12 @@ lstat(p, uap, retval)
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
- uap->path, p);
- error = namei(&nd);
- if (error)
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
/*
- * For symbolic links, always return the attributes of its
- * containing directory, except for mode, size, and links.
+ * For symbolic links, always return the attributes of its containing
+ * directory, except for mode, size, inode number, and links.
*/
vp = nd.ni_vp;
dvp = nd.ni_dvp;
@@ -1363,8 +1631,9 @@ lstat(p, uap, retval)
sb.st_nlink = sb1.st_nlink;
sb.st_size = sb1.st_size;
sb.st_blocks = sb1.st_blocks;
+ sb.st_ino = sb1.st_ino;
}
- error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));
+ error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb));
return (error);
}
@@ -1381,17 +1650,20 @@ struct pathconf_args {
int
pathconf(p, uap, retval)
struct proc *p;
- register struct pathconf_args *uap;
- int *retval;
+ register struct pathconf_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) name;
+ } */ *uap;
+ register_t *retval;
{
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
- error = VOP_PATHCONF(nd.ni_vp, uap->name, retval);
+ error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
vput(nd.ni_vp);
return (error);
}
@@ -1410,8 +1682,12 @@ struct readlink_args {
int
readlink(p, uap, retval)
struct proc *p;
- register struct readlink_args *uap;
- int *retval;
+ register struct readlink_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) buf;
+ syscallarg(int) count;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct iovec aiov;
@@ -1419,27 +1695,27 @@ readlink(p, uap, retval)
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type != VLNK)
error = EINVAL;
else {
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
+ auio.uio_resid = SCARG(uap, count);
error = VOP_READLINK(vp, &auio, p->p_ucred);
}
vput(vp);
- *retval = uap->count - auio.uio_resid;
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
@@ -1456,23 +1732,25 @@ struct chflags_args {
int
chflags(p, uap, retval)
struct proc *p;
- register struct chflags_args *uap;
- int *retval;
+ register struct chflags_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_flags = uap->flags;
+ vattr.va_flags = SCARG(uap, flags);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1491,24 +1769,26 @@ struct fchflags_args {
int
fchflags(p, uap, retval)
struct proc *p;
- register struct fchflags_args *uap;
- int *retval;
+ register struct fchflags_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_flags = uap->flags;
+ vattr.va_flags = SCARG(uap, flags);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1525,23 +1805,25 @@ struct chmod_args {
int
chmod(p, uap, retval)
struct proc *p;
- register struct chmod_args *uap;
- int *retval;
+ register struct chmod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_mode = uap->mode & ALLPERMS;
+ vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1560,24 +1842,26 @@ struct fchmod_args {
int
fchmod(p, uap, retval)
struct proc *p;
- register struct fchmod_args *uap;
- int *retval;
+ register struct fchmod_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_mode = uap->mode & ALLPERMS;
+ vattr.va_mode = SCARG(uap, mode) & ALLPERMS;
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1595,24 +1879,27 @@ struct chown_args {
int
chown(p, uap, retval)
struct proc *p;
- register struct chown_args *uap;
- int *retval;
+ register struct chown_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_uid = uap->uid;
- vattr.va_gid = uap->gid;
+ vattr.va_uid = SCARG(uap, uid);
+ vattr.va_gid = SCARG(uap, gid);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
vput(vp);
return (error);
@@ -1632,25 +1919,28 @@ struct fchown_args {
int
fchown(p, uap, retval)
struct proc *p;
- register struct fchown_args *uap;
- int *retval;
+ register struct fchown_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
VATTR_NULL(&vattr);
- vattr.va_uid = uap->uid;
- vattr.va_gid = uap->gid;
+ vattr.va_uid = SCARG(uap, uid);
+ vattr.va_gid = SCARG(uap, gid);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1667,8 +1957,11 @@ struct utimes_args {
int
utimes(p, uap, retval)
struct proc *p;
- register struct utimes_args *uap;
- int *retval;
+ register struct utimes_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct timeval *) tptr;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct timeval tv[2];
@@ -1677,22 +1970,19 @@ utimes(p, uap, retval)
struct nameidata nd;
VATTR_NULL(&vattr);
- if (uap->tptr == NULL) {
+ if (SCARG(uap, tptr) == NULL) {
microtime(&tv[0]);
tv[1] = tv[0];
vattr.va_vaflags |= VA_UTIMES_NULL;
- } else {
- error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv));
- if (error)
- return (error);
- }
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv,
+ sizeof (tv)))
+ return (error);
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
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;
@@ -1716,8 +2006,12 @@ struct truncate_args {
int
truncate(p, uap, retval)
struct proc *p;
- register struct truncate_args *uap;
- int *retval;
+ register struct truncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
@@ -1726,19 +2020,18 @@ truncate(p, uap, retval)
if (uap->length < 0)
return(EINVAL);
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EISDIR;
else if ((error = vn_writechk(vp)) == 0 &&
(error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
VATTR_NULL(&vattr);
- vattr.va_size = uap->length;
+ vattr.va_size = SCARG(uap, length);
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
}
vput(vp);
@@ -1759,8 +2052,12 @@ struct ftruncate_args {
int
ftruncate(p, uap, retval)
struct proc *p;
- register struct ftruncate_args *uap;
- int *retval;
+ register struct ftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ *uap;
+ register_t *retval;
{
struct vattr vattr;
struct vnode *vp;
@@ -1769,22 +2066,21 @@ ftruncate(p, uap, retval)
if (uap->length < 0)
return(EINVAL);
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FWRITE) == 0)
return (EINVAL);
vp = (struct vnode *)fp->f_data;
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_type == VDIR)
error = EISDIR;
else if ((error = vn_writechk(vp)) == 0) {
VATTR_NULL(&vattr);
- vattr.va_size = uap->length;
+ vattr.va_size = SCARG(uap, length);
error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1802,13 +2098,20 @@ struct otruncate_args {
int
otruncate(p, uap, retval)
struct proc *p;
- register struct otruncate_args *uap;
- int *retval;
+ register struct otruncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(long) length;
+ } */ *uap;
+ register_t *retval;
{
- struct truncate_args nuap;
-
- nuap.path = uap->path;
- nuap.length = uap->length;
+ struct truncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ nuap;
+
+ SCARG(&nuap, path) = SCARG(uap, path);
+ SCARG(&nuap, length) = SCARG(uap, length);
return (truncate(p, &nuap, retval));
}
@@ -1825,13 +2128,20 @@ struct oftruncate_args {
int
oftruncate(p, uap, retval)
struct proc *p;
- register struct oftruncate_args *uap;
- int *retval;
+ register struct oftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(long) length;
+ } */ *uap;
+ register_t *retval;
{
- struct ftruncate_args nuap;
-
- nuap.fd = uap->fd;
- nuap.length = uap->length;
+ struct ftruncate_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) pad;
+ syscallarg(off_t) length;
+ } */ nuap;
+
+ SCARG(&nuap, fd) = SCARG(uap, fd);
+ SCARG(&nuap, length) = SCARG(uap, length);
return (ftruncate(p, &nuap, retval));
}
#endif /* COMPAT_43 || COMPAT_SUNOS */
@@ -1848,24 +2158,25 @@ struct fsync_args {
int
fsync(p, uap, retval)
struct proc *p;
- struct fsync_args *uap;
- int *retval;
+ struct fsync_args /* {
+ syscallarg(int) fd;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
int error;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
vp = (struct vnode *)fp->f_data;
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (vp->v_object) {
vm_object_page_clean(vp->v_object, 0, 0 ,0, FALSE);
}
error = VOP_FSYNC(vp, fp->f_cred,
(vp->v_mount->mnt_flag & MNT_ASYNC) ? MNT_NOWAIT : MNT_WAIT, p);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1883,29 +2194,29 @@ struct rename_args {
int
rename(p, uap, retval)
struct proc *p;
- register struct rename_args *uap;
- int *retval;
+ register struct rename_args /* {
+ syscallarg(char *) from;
+ syscallarg(char *) to;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *tvp, *fvp, *tdvp;
struct nameidata fromnd, tond;
int error;
NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
- uap->from, p);
- error = namei(&fromnd);
- if (error)
+ SCARG(uap, from), p);
+ if (error = namei(&fromnd))
return (error);
fvp = fromnd.ni_vp;
NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
- UIO_USERSPACE, uap->to, p);
+ UIO_USERSPACE, SCARG(uap, to), p);
if (fromnd.ni_vp->v_type == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
- error = namei(&tond);
- if (error) {
+ if (error = namei(&tond)) {
/* Translate error code for rename("dir1", "dir2/."). */
if (error == EISDIR && fvp->v_type == VDIR)
error = EINVAL;
-
VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
vrele(fromnd.ni_dvp);
vrele(fvp);
@@ -1936,13 +2247,12 @@ rename(p, uap, retval)
error = -1;
out:
if (!error) {
- LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);
- if (fromnd.ni_dvp != tdvp) {
- LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- }
+ VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
+ if (fromnd.ni_dvp != tdvp)
+ VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
if (tvp) {
- LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);
- (void) vnode_pager_uncache(tvp);
+ VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
+ (void) vnode_pager_uncache(tvp, p);
}
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
@@ -1982,18 +2292,20 @@ struct mkdir_args {
int
mkdir(p, uap, retval)
struct proc *p;
- register struct mkdir_args *uap;
- int *retval;
+ register struct mkdir_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
nd.ni_cnd.cn_flags |= WILLBEDIR;
- error = namei(&nd);
- if (error)
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp != NULL) {
@@ -2007,8 +2319,8 @@ mkdir(p, uap, retval)
}
VATTR_NULL(&vattr);
vattr.va_type = VDIR;
- vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask;
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (!error)
vput(nd.ni_vp);
@@ -2027,16 +2339,18 @@ struct rmdir_args {
int
rmdir(p, uap, retval)
struct proc *p;
- struct rmdir_args *uap;
- int *retval;
+ struct rmdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
int error;
struct nameidata nd;
- NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
+ SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
if (vp->v_type != VDIR) {
@@ -2057,8 +2371,8 @@ rmdir(p, uap, retval)
error = EBUSY;
out:
if (!error) {
- LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
- LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
@@ -2086,8 +2400,13 @@ struct ogetdirentries_args {
int
ogetdirentries(p, uap, retval)
struct proc *p;
- register struct ogetdirentries_args *uap;
- int *retval;
+ register struct ogetdirentries_args /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(u_int) count;
+ syscallarg(long *) basep;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
@@ -2095,30 +2414,31 @@ ogetdirentries(p, uap, retval)
struct iovec aiov, kiov;
struct dirent *dp, *edp;
caddr_t dirbuf;
- int error, readcnt;
+ int error, eofflag, readcnt;
long loff;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
vp = (struct vnode *)fp->f_data;
+unionread:
if (vp->v_type != VDIR)
return (EINVAL);
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
- VOP_LOCK(vp);
+ auio.uio_resid = SCARG(uap, count);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
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, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
+ NULL, NULL);
fp->f_offset = auio.uio_offset;
} else
# endif
@@ -2126,13 +2446,14 @@ ogetdirentries(p, uap, retval)
kuio = auio;
kuio.uio_iov = &kiov;
kuio.uio_segflg = UIO_SYSSPACE;
- kiov.iov_len = uap->count;
- MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
+ kiov.iov_len = SCARG(uap, count);
+ MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK);
kiov.iov_base = dirbuf;
- error = VOP_READDIR(vp, &kuio, fp->f_cred, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
+ NULL, NULL);
fp->f_offset = kuio.uio_offset;
if (error == 0) {
- readcnt = uap->count - kuio.uio_resid;
+ readcnt = SCARG(uap, count) - kuio.uio_resid;
edp = (struct dirent *)&dirbuf[readcnt];
for (dp = (struct dirent *)dirbuf; dp < edp; ) {
# if (BYTE_ORDER == LITTLE_ENDIAN)
@@ -2165,14 +2486,70 @@ ogetdirentries(p, uap, retval)
}
FREE(dirbuf, M_TEMP);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
- error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
- *retval = uap->count - auio.uio_resid;
+
+#ifdef UNION
+{
+ extern int (**union_vnodeop_p)();
+ extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
+ (vp->v_op == union_vnodeop_p)) {
+ struct vnode *lvp;
+
+ lvp = union_dircache(vp, p);
+ if (lvp != NULLVP) {
+ struct vattr va;
+
+ /*
+ * If the directory is opaque,
+ * then don't show lower entries
+ */
+ error = VOP_GETATTR(vp, &va, fp->f_cred, p);
+ if (va.va_flags & OPAQUE) {
+ vput(lvp);
+ lvp = NULL;
+ }
+ }
+
+ if (lvp != NULLVP) {
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
+ if (error) {
+ vput(lvp);
+ return (error);
+ }
+ VOP_UNLOCK(lvp, 0, p);
+ fp->f_data = (caddr_t) lvp;
+ fp->f_offset = 0;
+ error = vn_close(vp, FREAD, fp->f_cred, p);
+ if (error)
+ return (error);
+ vp = lvp;
+ goto unionread;
+ }
+ }
+}
+#endif /* UNION */
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
+ (vp->v_flag & VROOT) &&
+ (vp->v_mount->mnt_flag & MNT_UNION)) {
+ struct vnode *tvp = vp;
+ vp = vp->v_mount->mnt_vnodecovered;
+ VREF(vp);
+ fp->f_data = (caddr_t) vp;
+ fp->f_offset = 0;
+ vrele(tvp);
+ goto unionread;
+ }
+ error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
+ sizeof(long));
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
-#endif
+#endif /* COMPAT_43 */
/*
* Read a block of directory entries in a file system independent format.
@@ -2188,18 +2565,22 @@ struct getdirentries_args {
int
getdirentries(p, uap, retval)
struct proc *p;
- register struct getdirentries_args *uap;
- int *retval;
+ register struct getdirentries_args /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(u_int) count;
+ syscallarg(long *) basep;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct file *fp;
struct uio auio;
struct iovec aiov;
long loff;
- int error;
+ int error, eofflag;
- error = getvnode(p->p_fd, uap->fd, &fp);
- if (error)
+ if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp))
return (error);
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
@@ -2207,51 +2588,66 @@ getdirentries(p, uap, retval)
unionread:
if (vp->v_type != VDIR)
return (EINVAL);
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
+ aiov.iov_base = SCARG(uap, buf);
+ aiov.iov_len = SCARG(uap, count);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- auio.uio_resid = uap->count;
- VOP_LOCK(vp);
+ auio.uio_resid = SCARG(uap, count);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
loff = auio.uio_offset = fp->f_offset;
- error = VOP_READDIR(vp, &auio, fp->f_cred, NULL, NULL, NULL);
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
fp->f_offset = auio.uio_offset;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
#ifdef UNION
{
- if ((uap->count == auio.uio_resid) &&
+ extern int (**union_vnodeop_p)();
+ extern struct vnode *union_dircache __P((struct vnode*, struct proc*));
+
+ if ((SCARG(uap, count) == auio.uio_resid) &&
(vp->v_op == union_vnodeop_p)) {
- struct vnode *tvp = vp;
+ struct vnode *lvp;
+
+ lvp = union_dircache(vp, p);
+ if (lvp != NULLVP) {
+ struct vattr va;
- vp = union_lowervp(vp);
- if (vp != NULLVP) {
- VOP_LOCK(vp);
- error = VOP_OPEN(vp, FREAD, fp->f_cred, p);
- VOP_UNLOCK(vp);
+ /*
+ * If the directory is opaque,
+ * then don't show lower entries
+ */
+ error = VOP_GETATTR(vp, &va, fp->f_cred, p);
+ if (va.va_flags & OPAQUE) {
+ vput(lvp);
+ lvp = NULL;
+ }
+ }
+ if (lvp != NULLVP) {
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
if (error) {
- vrele(vp);
+ vput(lvp);
return (error);
}
- fp->f_data = (caddr_t) vp;
+ VOP_UNLOCK(lvp, 0, p);
+ fp->f_data = (caddr_t) lvp;
fp->f_offset = 0;
- error = vn_close(tvp, FREAD, fp->f_cred, p);
+ error = vn_close(vp, FREAD, fp->f_cred, p);
if (error)
return (error);
+ vp = lvp;
goto unionread;
}
}
}
-#endif
+#endif /* UNION */
- if ((uap->count == auio.uio_resid) &&
- vp &&
+ if ((SCARG(uap, count) == auio.uio_resid) &&
(vp->v_flag & VROOT) &&
(vp->v_mount->mnt_flag & MNT_UNION)) {
struct vnode *tvp = vp;
@@ -2262,8 +2658,9 @@ unionread:
vrele(tvp);
goto unionread;
}
- error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));
- *retval = uap->count - auio.uio_resid;
+ error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep),
+ sizeof(long));
+ *retval = SCARG(uap, count) - auio.uio_resid;
return (error);
}
@@ -2275,17 +2672,19 @@ struct umask_args {
int newmask;
};
#endif
-mode_t /* XXX */
+int
umask(p, uap, retval)
struct proc *p;
- struct umask_args *uap;
- int *retval;
+ struct umask_args /* {
+ syscallarg(int) newmask;
+ } */ *uap;
+ int *retval; /* XXX */
{
register struct filedesc *fdp;
fdp = p->p_fd;
*retval = fdp->fd_cmask;
- fdp->fd_cmask = uap->newmask & ALLPERMS;
+ fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS;
return (0);
}
@@ -2302,31 +2701,27 @@ struct revoke_args {
int
revoke(p, uap, retval)
struct proc *p;
- register struct revoke_args *uap;
- int *retval;
+ register struct revoke_args /* {
+ syscallarg(char *) path;
+ } */ *uap;
+ register_t *retval;
{
register struct vnode *vp;
struct vattr vattr;
int error;
struct nameidata nd;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);
- error = namei(&nd);
- if (error)
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+ if (error = namei(&nd))
return (error);
vp = nd.ni_vp;
- if (vp->v_type != VCHR && vp->v_type != VBLK) {
- error = EINVAL;
- goto out;
- }
- error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
- if (error)
+ if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
goto out;
if (p->p_ucred->cr_uid != vattr.va_uid &&
(error = suser(p->p_ucred, &p->p_acflag)))
goto out;
if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))
- vgoneall(vp);
+ VOP_REVOKE(vp, REVOKEALL);
out:
vrele(vp);
return (error);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 0ba5c45..98842c6 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -96,10 +96,11 @@ vn_open(ndp, fmode, cmode)
VATTR_NULL(vap);
vap->va_type = VREG;
vap->va_mode = cmode;
- LEASE_CHECK(ndp->ni_dvp, p, cred, LEASE_WRITE);
- error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
- &ndp->ni_cnd, vap);
- if (error)
+ if (fmode & O_EXCL)
+ vap->va_vaflags |= VA_EXCLUSIVE;
+ VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE);
+ if (error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
+ &ndp->ni_cnd, vap))
return (error);
fmode &= ~O_TRUNC;
vp = ndp->ni_vp;
@@ -149,9 +150,9 @@ vn_open(ndp, fmode, cmode)
}
}
if (fmode & O_TRUNC) {
- VOP_UNLOCK(vp); /* XXX */
- LEASE_CHECK(vp, p, cred, LEASE_WRITE);
- VOP_LOCK(vp); /* XXX */
+ VOP_UNLOCK(vp, 0, p); /* XXX */
+ VOP_LEASE(vp, p, cred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
VATTR_NULL(vap);
vap->va_size = 0;
error = VOP_SETATTR(vp, vap, cred, p);
@@ -179,8 +180,7 @@ bad:
/*
* 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)
@@ -237,7 +237,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
int error;
if ((ioflg & IO_NODELOCKED) == 0)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
aiov.iov_base = base;
@@ -258,7 +258,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
if (auio.uio_resid && error == 0)
error = EIO;
if ((ioflg & IO_NODELOCKED) == 0)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -271,12 +271,13 @@ vn_read(fp, uio, cred)
struct uio *uio;
struct ucred *cred;
{
- register struct vnode *vp = (struct vnode *)fp->f_data;
+ struct vnode *vp = (struct vnode *)fp->f_data;
+ struct proc *p = uio->uio_procp;
int count, error;
int flag, seq;
- LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_READ);
- VOP_LOCK(vp);
+ VOP_LEASE(vp, p, cred, LEASE_READ);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
uio->uio_offset = fp->f_offset;
count = uio->uio_resid;
flag = 0;
@@ -313,7 +314,7 @@ vn_read(fp, uio, cred)
error = VOP_READ(vp, uio, flag, cred);
fp->f_offset += count - uio->uio_resid;
fp->f_nextread = fp->f_offset;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -326,15 +327,19 @@ vn_write(fp, uio, cred)
struct uio *uio;
struct ucred *cred;
{
- register struct vnode *vp = (struct vnode *)fp->f_data;
- int count, error, ioflag = 0;
+ struct vnode *vp = (struct vnode *)fp->f_data;
+ struct proc *p = uio->uio_procp;
+ int count, error, ioflag = IO_UNIT;
if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
ioflag |= IO_APPEND;
if (fp->f_flag & FNONBLOCK)
ioflag |= IO_NDELAY;
- LEASE_CHECK(vp, uio->uio_procp, cred, LEASE_WRITE);
- VOP_LOCK(vp);
+ if ((fp->f_flag & O_FSYNC) ||
+ (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
+ ioflag |= IO_SYNC;
+ VOP_LEASE(vp, p, cred, LEASE_WRITE);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
uio->uio_offset = fp->f_offset;
count = uio->uio_resid;
error = VOP_WRITE(vp, uio, ioflag, cred);
@@ -342,7 +347,7 @@ vn_write(fp, uio, cred)
fp->f_offset = uio->uio_offset;
else
fp->f_offset += count - uio->uio_resid;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -402,7 +407,7 @@ vn_stat(vp, sb, p)
sb->st_rdev = vap->va_rdev;
sb->st_size = vap->va_size;
sb->st_atimespec = vap->va_atime;
- sb->st_mtimespec= vap->va_mtime;
+ sb->st_mtimespec = vap->va_mtime;
sb->st_ctimespec = vap->va_ctime;
sb->st_blksize = vap->va_blocksize;
sb->st_flags = vap->va_flags;
@@ -495,3 +500,34 @@ vn_closefile(fp, p)
return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
fp->f_cred, p));
}
+
+/*
+ * Check that the vnode is still valid, and if so
+ * acquire requested lock.
+ */
+int
+vn_lock(vp, flags, p)
+ struct vnode *vp;
+ int flags;
+ struct proc *p;
+{
+ int error;
+
+ do {
+ if ((flags & LK_INTERLOCK) == 0) {
+ simple_lock(&vp->v_interlock);
+ }
+ if (vp->v_flag & VXLOCK) {
+ vp->v_flag |= VXWANT;
+ simple_unlock(&vp->v_interlock);
+ tsleep((caddr_t)vp, PINOD, "vn_lock", 0);
+ error = ENOENT;
+ } else {
+ error = VOP_LOCK(vp, flags | LK_INTERLOCK, p);
+ if (error == 0)
+ return (error);
+ }
+ flags &= ~LK_INTERLOCK;
+ } while (flags & LK_RETRY);
+ return (error);
+}
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index a8fb13b..7e3338f 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -30,8 +30,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
-# $FreeBSD$
+# @(#)vnode_if.src 8.12 (Berkeley) 5/14/95
+# $Id: vnode_if.src,v 1.9.2000.1 1996/09/17 14:32:01 peter Exp $
+#
+
+#
+# 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 +64,10 @@ vop_lookup {
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 +75,21 @@ vop_create {
IN struct vattr *vap;
};
+#
+#% whiteout dvp L L L
+#% whiteout cnp - - -
+#% whiteout flag - - -
+#
+vop_whiteout {
+ IN WILLRELE struct vnode *dvp;
+ IN struct componentname *cnp;
+ IN int flags;
+};
+
+#
+#% mknod dvp L U U
+#% mknod vpp - X -
+#
vop_mknod {
IN WILLRELE struct vnode *dvp;
OUT WILLRELE struct vnode **vpp;
@@ -53,6 +97,9 @@ vop_mknod {
IN struct vattr *vap;
};
+#
+#% open vp L L L
+#
vop_open {
IN struct vnode *vp;
IN int mode;
@@ -60,6 +107,9 @@ vop_open {
IN struct proc *p;
};
+#
+#% close vp U U U
+#
vop_close {
IN struct vnode *vp;
IN int fflag;
@@ -67,6 +117,9 @@ vop_close {
IN struct proc *p;
};
+#
+#% access vp L L L
+#
vop_access {
IN struct vnode *vp;
IN int mode;
@@ -74,6 +127,9 @@ vop_access {
IN struct proc *p;
};
+#
+#% getattr vp = = =
+#
vop_getattr {
IN struct vnode *vp;
IN struct vattr *vap;
@@ -81,6 +137,9 @@ vop_getattr {
IN struct proc *p;
};
+#
+#% setattr vp L L L
+#
vop_setattr {
IN struct vnode *vp;
IN struct vattr *vap;
@@ -88,6 +147,9 @@ vop_setattr {
IN struct proc *p;
};
+#
+#% read vp L L L
+#
vop_read {
IN struct vnode *vp;
INOUT struct uio *uio;
@@ -95,6 +157,9 @@ vop_read {
IN struct ucred *cred;
};
+#
+#% write vp L L L
+#
vop_write {
IN struct vnode *vp;
INOUT struct uio *uio;
@@ -102,16 +167,33 @@ vop_write {
IN struct ucred *cred;
};
+#
+#% lease vp = = =
+#
+vop_lease {
+ IN struct vnode *vp;
+ IN struct proc *p;
+ IN struct ucred *cred;
+ IN int flag;
+};
+
+#
+#% ioctl vp U U U
+#
vop_ioctl {
IN struct vnode *vp;
- IN int command;
+ IN u_long command;
IN caddr_t data;
IN int fflag;
IN struct ucred *cred;
IN struct proc *p;
};
+#
+#% select vp U U U
+#
# Needs work? (fflags)
+#
vop_select {
IN struct vnode *vp;
IN int which;
@@ -120,6 +202,17 @@ vop_select {
IN struct proc *p;
};
+#
+#% revoke vp U U U
+#
+vop_revoke {
+ IN struct vnode *vp;
+ IN int flags;
+};
+
+#
+# XXX - not used
+#
vop_mmap {
IN struct vnode *vp;
IN int fflags;
@@ -127,6 +220,9 @@ vop_mmap {
IN struct proc *p;
};
+#
+#% fsync vp L L L
+#
vop_fsync {
IN struct vnode *vp;
IN struct ucred *cred;
@@ -134,7 +230,10 @@ vop_fsync {
IN struct proc *p;
};
-# Needs word: Is newoff right? What's it mean?
+#
+# XXX - not used
+# Needs work: Is newoff right? What's it mean?
+#
vop_seek {
IN struct vnode *vp;
IN off_t oldoff;
@@ -142,18 +241,32 @@ vop_seek {
IN struct ucred *cred;
};
+#
+#% remove dvp L U U
+#% remove vp L U U
+#
vop_remove {
IN WILLRELE struct vnode *dvp;
IN WILLRELE struct vnode *vp;
IN struct componentname *cnp;
};
+#
+#% link vp U U U
+#% link tdvp L U U
+#
vop_link {
IN WILLRELE struct vnode *tdvp;
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;
@@ -163,6 +276,10 @@ vop_rename {
IN struct componentname *tcnp;
};
+#
+#% mkdir dvp L U U
+#% mkdir vpp - L -
+#
vop_mkdir {
IN WILLRELE struct vnode *dvp;
OUT struct vnode **vpp;
@@ -170,12 +287,24 @@ vop_mkdir {
IN struct vattr *vap;
};
+#
+#% rmdir dvp L U U
+#% rmdir vp L U U
+#
vop_rmdir {
IN WILLRELE struct vnode *dvp;
IN WILLRELE struct vnode *vp;
IN struct componentname *cnp;
};
+#
+#% symlink dvp L U U
+#% symlink vpp - U -
+#
+# XXX - note that the return vnode has already been VRELE'ed
+# by the filesystem layer. To use it you must use vget,
+# possibly with a further namei.
+#
vop_symlink {
IN WILLRELE struct vnode *dvp;
OUT WILLRELE struct vnode **vpp;
@@ -184,42 +313,73 @@ vop_symlink {
IN char *target;
};
+#
+#% readdir vp L L L
+#
vop_readdir {
IN struct vnode *vp;
INOUT struct uio *uio;
IN struct ucred *cred;
INOUT int *eofflag;
- INOUT int *ncookies;
- INOUT u_int **cookies;
+ OUT int *ncookies;
+ INOUT u_long **cookies;
};
+#
+#% readlink vp L L L
+#
vop_readlink {
IN struct vnode *vp;
INOUT struct uio *uio;
IN struct ucred *cred;
};
+#
+#% abortop dvp = = =
+#
vop_abortop {
IN struct vnode *dvp;
IN struct componentname *cnp;
};
+#
+#% inactive vp L U U
+#
vop_inactive {
IN struct vnode *vp;
+ IN struct proc *p;
};
+#
+#% reclaim vp U U U
+#
vop_reclaim {
IN struct vnode *vp;
+ IN struct proc *p;
};
+#
+#% lock vp U L U
+#
vop_lock {
IN struct vnode *vp;
+ IN int flags;
+ IN struct proc *p;
};
+#
+#% unlock vp L U L
+#
vop_unlock {
IN struct vnode *vp;
+ IN int flags;
+ IN struct proc *p;
};
+#
+#% bmap vp L L L
+#% bmap vpp - U -
+#
vop_bmap {
IN struct vnode *vp;
IN daddr_t bn;
@@ -229,24 +389,39 @@ vop_bmap {
OUT int *runb;
};
+#
+# 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 int *retval;
+ OUT register_t *retval;
};
+#
+#% advlock vp U U U
+#
vop_advlock {
IN struct vnode *vp;
IN caddr_t id;
@@ -255,6 +430,9 @@ vop_advlock {
IN int flags;
};
+#
+#% blkatoff vp L L L
+#
vop_blkatoff {
IN struct vnode *vp;
IN off_t offset;
@@ -262,6 +440,9 @@ vop_blkatoff {
OUT struct buf **bpp;
};
+#
+#% valloc pvp L L L
+#
vop_valloc {
IN struct vnode *pvp;
IN int mode;
@@ -269,17 +450,26 @@ vop_valloc {
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;
@@ -288,6 +478,9 @@ vop_truncate {
IN struct proc *p;
};
+#
+#% update vp L L L
+#
vop_update {
IN struct vnode *vp;
IN struct timeval *access;
@@ -312,7 +505,9 @@ vop_putpages {
IN vm_ooffset_t offset;
};
+#
# Needs work: no vp?
+#
#vop_bwrite {
# IN struct buf *bp;
#};
diff --git a/sys/miscfs/deadfs/dead_vnops.c b/sys/miscfs/deadfs/dead_vnops.c
index f22425c..6d83c61 100644
--- a/sys/miscfs/deadfs/dead_vnops.c
+++ b/sys/miscfs/deadfs/dead_vnops.c
@@ -77,11 +77,11 @@ static int dead_select __P((struct vop_select_args *));
#define dead_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
#define dead_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
static int dead_lock __P((struct vop_lock_args *));
-#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define dead_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
static int dead_bmap __P((struct vop_bmap_args *));
static int dead_strategy __P((struct vop_strategy_args *));
static int dead_print __P((struct vop_print_args *));
-#define dead_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define dead_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
#define dead_pathconf ((int (*) __P((struct vop_pathconf_args *)))dead_ebadf)
#define dead_advlock ((int (*) __P((struct vop_advlock_args *)))dead_ebadf)
#define dead_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))dead_badop)
@@ -191,11 +191,20 @@ dead_read(ap)
if (chkvnlock(ap->a_vp))
panic("dead_read: lock");
+#if 0
+ /* Lite2 behaviour */
+ /*
+ * Return EOF for tty devices, EIO for others
+ */
+ if ((ap->a_vp->v_flag & VISTTY) == 0)
+ return (EIO);
+#else
/*
* Return EOF for character devices, EIO for others
*/
if (ap->a_vp->v_type != VCHR)
return (EIO);
+#endif
return (0);
}
@@ -282,12 +291,23 @@ static int
dead_lock(ap)
struct vop_lock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
- if (!chkvnlock(ap->a_vp))
+ /*
+ * Since we are not using the lock manager, we must clear
+ * the interlock here.
+ */
+ if (ap->a_flags & LK_INTERLOCK) {
+ simple_unlock(&vp->v_interlock);
+ ap->a_flags &= ~LK_INTERLOCK;
+ }
+ if (!chkvnlock(vp))
return (0);
- return (VCALL(ap->a_vp, VOFFSET(vop_lock), ap));
+ return (VCALL(vp, VOFFSET(vop_lock), ap));
}
/*
diff --git a/sys/miscfs/fdesc/fdesc.h b/sys/miscfs/fdesc/fdesc.h
index d754655..b4eff1f 100644
--- a/sys/miscfs/fdesc/fdesc.h
+++ b/sys/miscfs/fdesc/fdesc.h
@@ -61,8 +61,7 @@ typedef enum {
} fdntype;
struct fdescnode {
- struct fdescnode *fd_forw; /* Hash chain */
- struct fdescnode *fd_back;
+ LIST_ENTRY(fdescnode) fd_hash; /* Hash list */
struct vnode *fd_vnode; /* Back ptr to vnode */
fdntype fd_type; /* Type of this node */
unsigned fd_fd; /* Fd to be dup'ed */
@@ -74,7 +73,7 @@ struct fdescnode {
#define VTOFDESC(vp) ((struct fdescnode *)(vp)->v_data)
extern dev_t devctty;
-extern int fdesc_init __P((void));
+extern int fdesc_init __P((struct vfsconf *));
extern int fdesc_root __P((struct mount *, struct vnode **));
extern int fdesc_allocvp __P((fdntype, int, struct mount *, struct vnode **));
extern vop_t **fdesc_vnodeop_p;
diff --git a/sys/miscfs/fdesc/fdesc_vfsops.c b/sys/miscfs/fdesc/fdesc_vfsops.c
index 5f6703b..135052e 100644
--- a/sys/miscfs/fdesc/fdesc_vfsops.c
+++ b/sys/miscfs/fdesc/fdesc_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -108,7 +108,7 @@ fdesc_mount(mp, path, data, ndp, p)
/* XXX -- don't mark as local to work around fts() problems */
/*mp->mnt_flag |= MNT_LOCAL;*/
mp->mnt_data = (qaddr_t) fmp;
- getnewfsid(mp, MOUNT_FDESC);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -137,12 +137,8 @@ fdesc_unmount(mp, mntflags, p)
int flags = 0;
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
@@ -176,6 +172,7 @@ fdesc_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
/*
@@ -183,24 +180,12 @@ fdesc_root(mp, vpp)
*/
vp = VFSTOFDESC(mp)->f_root;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
static int
-fdesc_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
fdesc_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
@@ -233,7 +218,6 @@ fdesc_statfs(mp, sbp, p)
if (fdp->fd_nfiles < lim)
freefd += (lim - fdp->fd_nfiles);
- sbp->f_type = MOUNT_FDESC;
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
@@ -243,6 +227,7 @@ fdesc_statfs(mp, sbp, p)
sbp->f_files = lim + 1; /* Allow for "." */
sbp->f_ffree = freefd; /* See comments above */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -261,41 +246,15 @@ fdesc_sync(mp, waitfor, cred, p)
return (0);
}
-/*
- * Fdesc flat namespace lookup.
- * Currently unsupported.
- */
-static int
-fdesc_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-fdesc_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-fdesc_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+#define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
static struct vfsops fdesc_vfsops = {
fdesc_mount,
diff --git a/sys/miscfs/fdesc/fdesc_vnops.c b/sys/miscfs/fdesc/fdesc_vnops.c
index 1fe511b..795dfd8 100644
--- a/sys/miscfs/fdesc/fdesc_vnops.c
+++ b/sys/miscfs/fdesc/fdesc_vnops.c
@@ -77,22 +77,14 @@ FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
#endif
#define NFDCACHE 4
-#define FD_NHASH(ix) ((ix) & NFDCACHE-1)
-
-/*
- * Cache head
- */
-struct fdcache {
- struct fdescnode *fc_forw;
- struct fdescnode *fc_back;
-};
-
-static struct fdcache fdcache[NFDCACHE];
+#define FD_NHASH(ix) \
+ (&fdhashtbl[(ix) & fdhash])
+LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
+u_long fdhash;
static int fdesc_attr __P((int fd, struct vattr *vap, struct ucred *cred,
struct proc *p));
static int fdesc_badop __P((void));
-static int fdesc_enotsupp __P((void));
static int fdesc_getattr __P((struct vop_getattr_args *ap));
static struct fdcache *
fdesc_hash __P((int ix));
@@ -115,28 +107,15 @@ static int fdesc_write __P((struct vop_write_args *ap));
* Initialise cache headers
*/
int
-fdesc_init()
+fdesc_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct fdcache *fc;
devctty = makedev(nchrdev, 0);
-
- for (fc = fdcache; fc < fdcache + NFDCACHE; fc++)
- fc->fc_forw = fc->fc_back = (struct fdescnode *) fc;
+ fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
return (0);
}
-/*
- * Compute hash list for given target vnode
- */
-static struct fdcache *
-fdesc_hash(ix)
- int ix;
-{
-
- return (&fdcache[FD_NHASH(ix)]);
-}
-
int
fdesc_allocvp(ftype, ix, mp, vpp)
fdntype ftype;
@@ -144,15 +123,16 @@ fdesc_allocvp(ftype, ix, mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- struct fdcache *fc;
+ struct proc *p = curproc; /* XXX */
+ struct fdhashhead *fc;
struct fdescnode *fd;
int error = 0;
+ fc = FD_NHASH(ix);
loop:
- fc = fdesc_hash(ix);
- for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) {
+ for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
- if (vget(fd->fd_vnode, 0))
+ if (vget(fd->fd_vnode, 0, p))
goto loop;
*vpp = fd->fd_vnode;
return (error);
@@ -188,8 +168,7 @@ loop:
fd->fd_fd = -1;
fd->fd_link = 0;
fd->fd_ix = ix;
- fc = fdesc_hash(ix);
- insque(fd, fc);
+ LIST_INSERT_HEAD(fc, fd, fd_hash);
out:;
fdcache_lock &= ~FDL_LOCKED;
@@ -216,31 +195,28 @@ fdesc_lookup(ap)
{
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
- char *pname;
- struct proc *p;
- int nfiles;
- unsigned fd = 0;
+ struct componentname *cnp = ap->a_cnp;
+ char *pname = cnp->cn_nameptr;
+ struct proc *p = cnp->cn_proc;
+ int nfiles = p->p_fd->fd_nfiles;
+ unsigned fd;
int error;
struct vnode *fvp;
char *ln;
- if (ap->a_cnp->cn_nameiop == DELETE ||
- ap->a_cnp->cn_nameiop == RENAME) {
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
error = EROFS;
goto bad;
}
- pname = ap->a_cnp->cn_nameptr;
- if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
+ VOP_UNLOCK(dvp, 0, p);
+ if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
- VREF(dvp);
- VOP_LOCK(dvp);
+ VREF(dvp);
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return (0);
}
- p = ap->a_cnp->cn_proc;
- nfiles = p->p_fd->fd_nfiles;
-
switch (VTOFDESC(dvp)->fd_type) {
default:
case Flink:
@@ -250,17 +226,17 @@ fdesc_lookup(ap)
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(fvp, LK_SHARED | LK_RETRY, p);
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;
@@ -271,12 +247,12 @@ fdesc_lookup(ap)
goto bad;
*vpp = fvp;
fvp->v_type = VFIFO;
- VOP_LOCK(fvp);
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
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";
@@ -302,7 +278,7 @@ fdesc_lookup(ap)
VTOFDESC(fvp)->fd_link = ln;
*vpp = fvp;
fvp->v_type = VLNK;
- VOP_LOCK(fvp);
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
return (0);
} else {
error = ENOENT;
@@ -312,9 +288,10 @@ fdesc_lookup(ap)
/* FALL THROUGH */
case Fdevfd:
- if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
- error = fdesc_root(dvp->v_mount, vpp);
- return (error);
+ if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
+ if (error = fdesc_root(dvp->v_mount, vpp))
+ goto bad;
+ return (0);
}
fd = 0;
@@ -338,11 +315,13 @@ fdesc_lookup(ap)
if (error)
goto bad;
VTOFDESC(fvp)->fd_fd = fd;
+ vn_lock(fvp, LK_SHARED | LK_RETRY, p);
*vpp = fvp;
return (0);
}
bad:;
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
*vpp = NULL;
return (error);
}
@@ -402,10 +381,10 @@ fdesc_attr(fd, vap, cred, p)
error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
if (error == 0 && vap->va_type == VDIR) {
/*
- * don't allow directories to show up because
- * that causes loops in the namespace.
+ * directories can cause loops in the namespace,
+ * so turn off the 'x' bits to avoid trouble.
*/
- vap->va_type = VFIFO;
+ vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
}
break;
@@ -591,6 +570,9 @@ fdesc_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
struct uio *uio = ap->a_uio;
@@ -598,6 +580,13 @@ fdesc_readdir(ap)
int i;
int error;
+ /*
+ * We don't allow exporting fdesc mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("fdesc_readdir: not hungry");
+
switch (VTOFDESC(ap->a_vp)->fd_type) {
case Fctty:
return (0);
@@ -814,6 +803,7 @@ static int
fdesc_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
@@ -822,6 +812,7 @@ fdesc_inactive(ap)
* Clear out the v_type field to avoid
* nasty things happening in vgone().
*/
+ VOP_UNLOCK(vp, 0, ap->a_p);
vp->v_type = VNON;
return (0);
}
@@ -833,8 +824,9 @@ fdesc_reclaim(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+ struct fdescnode *fd = VTOFDESC(vp);
- remque(VTOFDESC(vp));
+ LIST_REMOVE(fd, fd_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = 0;
@@ -907,16 +899,6 @@ fdesc_vfree(ap)
}
/*
- * /dev/fd vnode unsupported operation
- */
-static int
-fdesc_enotsupp()
-{
-
- return (EOPNOTSUPP);
-}
-
-/*
* /dev/fd "should never get here" operation
*/
static int
@@ -927,38 +909,39 @@ fdesc_badop()
/* NOTREACHED */
}
-#define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp)
-#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp)
+#define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
+#define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
#define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
#define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
-#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp)
+#define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
+#define fdesc_revoke vop_revoke
#define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
-#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp)
-#define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp)
-#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp)
-#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp)
-#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp)
-#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp)
+#define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
+#define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
+#define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
+#define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
+#define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
+#define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
#define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
-#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
#define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
#define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
-#define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
-#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp)
+#define fdesc_islocked \
+ ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
+#define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
#define fdesc_blkatoff \
- ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp)
-#define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp)
+ ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
#define fdesc_valloc ((int(*) __P(( \
struct vnode *pvp, \
int mode, \
struct ucred *cred, \
- struct vnode **vpp))) fdesc_enotsupp)
+ struct vnode **vpp))) eopnotsupp)
#define fdesc_truncate \
- ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp)
-#define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp)
-#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp)
+ ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
+#define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
+#define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
static vop_t **fdesc_vnodeop_p;
static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
@@ -975,6 +958,7 @@ static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
{ &vop_write_desc, (vop_t *)fdesc_write }, /* write */
{ &vop_ioctl_desc, (vop_t *)fdesc_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fdesc_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fdesc_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fdesc_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)fdesc_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fdesc_seek }, /* seek */
diff --git a/sys/miscfs/fifofs/fifo.h b/sys/miscfs/fifofs/fifo.h
index efeaf85..6562159 100644
--- a/sys/miscfs/fifofs/fifo.h
+++ b/sys/miscfs/fifofs/fifo.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)fifo.h 8.2 (Berkeley) 2/2/94
+ * @(#)fifo.h 8.6 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -51,8 +51,10 @@ int fifo_close __P((struct vop_close_args *));
#define fifo_setattr ((int (*) __P((struct vop_setattr_args *)))fifo_ebadf)
int fifo_read __P((struct vop_read_args *));
int fifo_write __P((struct vop_write_args *));
+#define fifo_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
int fifo_ioctl __P((struct vop_ioctl_args *));
int fifo_select __P((struct vop_select_args *));
+#define fifo_revoke vop_revoke
#define fifo_mmap ((int (*) __P((struct vop_mmap_args *)))fifo_badop)
#define fifo_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define fifo_seek ((int (*) __P((struct vop_seek_args *)))fifo_badop)
@@ -65,11 +67,13 @@ int fifo_select __P((struct vop_select_args *));
#define fifo_readdir ((int (*) __P((struct vop_readdir_args *)))fifo_badop)
#define fifo_readlink ((int (*) __P((struct vop_readlink_args *)))fifo_badop)
#define fifo_abortop ((int (*) __P((struct vop_abortop_args *)))fifo_badop)
-#define fifo_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
+int fifo_inactive __P((struct vop_inactive_args *));
#define fifo_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
+#define fifo_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define fifo_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
int fifo_bmap __P((struct vop_bmap_args *));
#define fifo_strategy ((int (*) __P((struct vop_strategy_args *)))fifo_badop)
-#define fifo_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
int fifo_pathconf __P((struct vop_pathconf_args *));
int fifo_advlock __P((struct vop_advlock_args *));
#define fifo_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))fifo_badop)
diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
index 240354f..8f915ec 100644
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ b/sys/miscfs/fifofs/fifo_vnops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -30,12 +30,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)fifo_vnops.c 8.2 (Berkeley) 1/4/94
+ * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95
* $FreeBSD$
*/
#include <sys/param.h>
-#include <sys/kernel.h>
+#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/namei.h>
@@ -44,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>
@@ -64,8 +63,6 @@ struct fifoinfo {
};
static int fifo_ebadf __P((void));
-static int fifo_unlock __P((struct vop_unlock_args *));
-static int fifo_lock __P((struct vop_lock_args *));
static int fifo_print __P((struct vop_print_args *));
vop_t **fifo_vnodeop_p;
@@ -81,8 +78,10 @@ static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)fifo_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)fifo_read }, /* read */
{ &vop_write_desc, (vop_t *)fifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)fifo_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
@@ -149,8 +148,9 @@ fifo_open(ap)
struct proc *a_p;
} */ *ap;
{
- 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 char openstr[] = "fifo";
@@ -158,14 +158,14 @@ fifo_open(ap)
if ((fip = vp->v_fifoinfo) == NULL) {
MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
vp->v_fifoinfo = fip;
- error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, ap->a_p);
+ error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_p);
if (error) {
free(fip, M_VNODE);
vp->v_fifoinfo = NULL;
return (error);
}
fip->fi_readsock = rso;
- error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, ap->a_p);
+ error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_p);
if (error) {
(void)soclose(rso);
free(fip, M_VNODE);
@@ -185,60 +185,52 @@ fifo_open(ap)
wso->so_state |= SS_CANTRCVMORE;
rso->so_state |= SS_CANTSENDMORE;
}
- error = 0;
- if ((ap->a_mode & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
- if (fip->fi_readers == 0) {
+ if (ap->a_mode & FREAD) {
+ fip->fi_readers++;
+ if (fip->fi_readers == 1) {
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
if (fip->fi_writers > 0)
wakeup((caddr_t)&fip->fi_writers);
}
- if (fip->fi_writers == 0) {
+ }
+ if (ap->a_mode & FWRITE) {
+ fip->fi_writers++;
+ if (fip->fi_writers == 1) {
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
if (fip->fi_readers > 0)
wakeup((caddr_t)&fip->fi_readers);
}
- fip->fi_readers++;
- fip->fi_writers++;
}
- else if (ap->a_mode & FREAD) {
- fip->fi_readers++;
- if (fip->fi_readers == 1) {
- fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
- if (fip->fi_writers > 0)
- wakeup((caddr_t)&fip->fi_writers);
+ if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) {
+ while (fip->fi_writers == 0) {
+ VOP_UNLOCK(vp, 0, p);
+ error = tsleep((caddr_t)&fip->fi_readers,
+ PCATCH | PSOCK, openstr, 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (error)
+ goto bad;
}
- if (!(ap->a_mode & O_NONBLOCK))
- while (fip->fi_writers == 0) {
- VOP_UNLOCK(vp);
- error = tsleep((caddr_t)&fip->fi_readers,
- PCATCH | PSOCK, openstr, 0);
- VOP_LOCK(vp);
- if (error)
- break;
- }
}
- else {
- fip->fi_writers++;
- if (fip->fi_readers == 0 && (ap->a_mode & O_NONBLOCK)) {
- error = ENXIO;
- } else {
- if (fip->fi_writers == 1) {
- fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
- if (fip->fi_readers > 0)
- wakeup((caddr_t)&fip->fi_readers);
+ if (ap->a_mode & FWRITE) {
+ if (ap->a_mode & O_NONBLOCK) {
+ if (fip->fi_readers == 0) {
+ error = ENXIO;
+ goto bad;
}
+ } else {
while (fip->fi_readers == 0) {
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = tsleep((caddr_t)&fip->fi_writers,
PCATCH | PSOCK, openstr, 0);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
if (error)
- break;
+ goto bad;
}
}
}
- if (error)
- VOP_CLOSE(vp, ap->a_mode, ap->a_cred, ap->a_p);
+ return (0);
+bad:
+ VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p);
return (error);
}
@@ -255,8 +247,9 @@ fifo_read(ap)
struct ucred *a_cred;
} */ *ap;
{
- 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;
+ struct proc *p = uio->uio_procp;
int error, startresid;
#ifdef DIAGNOSTIC
@@ -268,10 +261,10 @@ fifo_read(ap)
if (ap->a_ioflag & IO_NDELAY)
rso->so_state |= SS_NBIO;
startresid = uio->uio_resid;
- VOP_UNLOCK(ap->a_vp);
- error = soreceive(rso, (struct mbuf **)0, uio,
- (struct mbuf **)0, (struct mbuf **)0, (int*)0);
- VOP_LOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
+ error = soreceive(rso, (struct mbuf **)0, uio, (struct mbuf **)0,
+ (struct mbuf **)0, (int *)0);
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
/*
* Clear EOF indication after first such return.
*/
@@ -296,6 +289,7 @@ fifo_write(ap)
} */ *ap;
{
struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
+ struct proc *p = ap->a_uio->uio_procp;
int error;
#ifdef DIAGNOSTIC
@@ -304,9 +298,9 @@ fifo_write(ap)
#endif
if (ap->a_ioflag & IO_NDELAY)
wso->so_state |= SS_NBIO;
- VOP_UNLOCK(ap->a_vp);
+ VOP_UNLOCK(ap->a_vp, 0, p);
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, p);
if (ap->a_ioflag & IO_NDELAY)
wso->so_state &= ~SS_NBIO;
return (error);
@@ -328,14 +322,23 @@ fifo_ioctl(ap)
} */ *ap;
{
struct file filetmp;
+ int error;
if (ap->a_command == FIONBIO)
return (0);
- if (ap->a_fflag & FREAD)
+ if (ap->a_fflag & FREAD) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- else
+ error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
+ if (error)
+ return (error);
+ }
+ if (ap->a_fflag & FWRITE) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
- return (soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p));
+ error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
+ if (error)
+ return (error);
+ }
+ return (0);
}
/* ARGSUSED */
@@ -350,12 +353,33 @@ fifo_select(ap)
} */ *ap;
{
struct file filetmp;
+ int ready;
- if (ap->a_fflags & FREAD)
+ if (ap->a_fflags & FREAD) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- else
+ ready = soo_select(&filetmp, ap->a_which, ap->a_p);
+ if (ready)
+ return (ready);
+ }
+ if (ap->a_fflags & FWRITE) {
filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
- return (soo_select(&filetmp, ap->a_which, ap->a_p));
+ ready = soo_select(&filetmp, ap->a_which, ap->a_p);
+ if (ready)
+ return (ready);
+ }
+ return (0);
+}
+
+int
+fifo_inactive(ap)
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
+ return (0);
}
/*
@@ -385,31 +409,6 @@ fifo_bmap(ap)
}
/*
- * At the moment we do not do any locking.
- */
-/* ARGSUSED */
-static int
-fifo_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/* ARGSUSED */
-static int
-fifo_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/*
* Device close routine
*/
/* ARGSUSED */
@@ -426,16 +425,16 @@ fifo_close(ap)
register struct fifoinfo *fip = vp->v_fifoinfo;
int error1, error2;
- if (ap->a_fflag & FWRITE) {
- fip->fi_writers--;
- if (fip->fi_writers == 0)
- socantrcvmore(fip->fi_readsock);
- }
if (ap->a_fflag & FREAD) {
fip->fi_readers--;
if (fip->fi_readers == 0)
socantsendmore(fip->fi_writesock);
}
+ if (ap->a_fflag & FWRITE) {
+ fip->fi_writers--;
+ if (fip->fi_writers == 0)
+ socantrcvmore(fip->fi_readsock);
+ }
if (vp->v_usecount > 1)
return (0);
error1 = soclose(fip->fi_readsock);
diff --git a/sys/miscfs/kernfs/kernfs.h b/sys/miscfs/kernfs/kernfs.h
index 69496a4..2795bb3 100644
--- a/sys/miscfs/kernfs/kernfs.h
+++ b/sys/miscfs/kernfs/kernfs.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)kernfs.h 8.4 (Berkeley) 1/21/94
+ * @(#)kernfs.h 8.6 (Berkeley) 3/29/95
* $FreeBSD$
*/
@@ -51,7 +51,18 @@ struct kernfs_node {
#define VFSTOKERNFS(mp) ((struct kernfs_mount *)((mp)->mnt_data))
#define VTOKERN(vp) ((struct kernfs_node *)(vp)->v_data)
+#define kernfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define kernfs_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define kernfs_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+#define kernfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define kernfs_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define kernfs_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
extern vop_t **kernfs_vnodeop_p;
extern struct vfsops kernfs_vfsops;
-extern struct vnode *rrootvp;
+extern dev_t rrootdev;
#endif /* KERNEL */
diff --git a/sys/miscfs/kernfs/kernfs_vfsops.c b/sys/miscfs/kernfs/kernfs_vfsops.c
index 4c045e7..b774487 100644
--- a/sys/miscfs/kernfs/kernfs_vfsops.c
+++ b/sys/miscfs/kernfs/kernfs_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)kernfs_vfsops.c 8.4 (Berkeley) 1/21/94
+ * @(#)kernfs_vfsops.c 8.10 (Berkeley) 5/14/95
* $FreeBSD$
*/
@@ -55,88 +55,52 @@
#include <miscfs/specfs/specdev.h>
#include <miscfs/kernfs/kernfs.h>
-struct vnode *rrootvp;
+dev_t rrootdev = NODEV;
static int cdevvp __P((dev_t dev, struct vnode **vpp));
-static int kernfs_init __P((void));
+static int kernfs_init __P((struct vfsconf *vfsp));
static int kernfs_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
static int kernfs_start __P((struct mount *mp, int flags, struct proc *p));
static int kernfs_unmount __P((struct mount *mp, int mntflags,
struct proc *p));
static int kernfs_root __P((struct mount *mp, struct vnode **vpp));
-static int kernfs_quotactl __P((struct mount *mp, int cmd, uid_t uid,
- caddr_t arg, struct proc *p));
static int kernfs_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int kernfs_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
-static int kernfs_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int kernfs_fhtovp __P((struct mount *mp, struct fid *fhp,
- struct mbuf *nam, struct vnode **vpp,
- int *exflagsp, struct ucred **credanonp));
-static int kernfs_vptofh __P((struct vnode *vp, struct fid *fhp));
-/*
- * Create a vnode for a character device.
- */
static int
-cdevvp(dev, vpp)
- dev_t dev;
- struct vnode **vpp;
+kernfs_init(vfsp)
+ struct vfsconf *vfsp;
{
- register struct vnode *vp;
- struct vnode *nvp;
- int error;
- if (dev == NODEV)
- return (0);
- error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
- if (error) {
- *vpp = 0;
- return (error);
- }
- vp = nvp;
- vp->v_type = VCHR;
- nvp = checkalias(vp, dev, (struct mount *)0);
- if (nvp) {
- vput(vp);
- vp = nvp;
- }
- *vpp = vp;
return (0);
}
-static int
-kernfs_init()
+void
+kernfs_get_rrootdev()
{
- int cmaj;
+ static int tried = 0;
int bmaj = major(rootdev);
- int error = ENXIO;
+ int cmaj;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_init\n"); /* printed during system boot */
-#endif
+ if (tried) {
+ /* Already did it once. */
+ return;
+ }
+ tried = 1;
if (!bdevsw[bmaj]) {
panic("root dev has no bdevsw");
}
+ if (rootdev == NODEV)
+ return;
for (cmaj = 0; cmaj < nchrdev; cmaj++) {
- if (cdevsw[cmaj]
- && (cdevsw[cmaj]->d_open == bdevsw[bmaj]->d_open)) {
- dev_t cdev = makedev(cmaj, minor(rootdev));
- error = cdevvp(cdev, &rrootvp);
- if (error == 0)
- break;
- }
+ rrootdev = makedev(cmaj, minor(rootdev));
+ if (chrtoblk(rrootdev) == rootdev)
+ return;
}
-
- if (error) {
- printf("kernfs: no raw boot device\n");
- rrootvp = 0;
- }
- return (0);
+ rrootdev = NODEV;
+ printf("kernfs_get_rrootdev: no raw root device\n");
}
/*
@@ -182,7 +146,7 @@ kernfs_mount(mp, path, data, ndp, p)
fmp->kf_root = rvp;
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) fmp;
- getnewfsid(mp, MOUNT_KERNFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -192,6 +156,8 @@ kernfs_mount(mp, path, data, ndp, p)
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
#endif
+
+ kernfs_get_rrootdev();
return (0);
}
@@ -218,12 +184,8 @@ kernfs_unmount(mp, mntflags, p)
printf("kernfs_unmount(mp = %x)\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
@@ -263,6 +225,7 @@ kernfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef KERNFS_DIAGNOSTIC
@@ -274,23 +237,12 @@ kernfs_root(mp, vpp)
*/
vp = VFSTOKERNFS(mp)->kf_root;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
static int
-kernfs_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
- return (EOPNOTSUPP);
-}
-
-static int
kernfs_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
@@ -300,7 +252,6 @@ kernfs_statfs(mp, sbp, p)
printf("kernfs_statfs(mp = %x)\n", mp);
#endif
- sbp->f_type = MOUNT_KERNFS;
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
@@ -310,6 +261,7 @@ kernfs_statfs(mp, sbp, p)
sbp->f_files = 0;
sbp->f_ffree = 0;
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -317,53 +269,6 @@ kernfs_statfs(mp, sbp, p)
return (0);
}
-static int
-kernfs_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
-
- return (0);
-}
-
-/*
- * Kernfs flat namespace lookup.
- * Currently unsupported.
- */
-static int
-kernfs_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-
-static int
-kernfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-kernfs_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
- return (EOPNOTSUPP);
-}
-
static struct vfsops kernfs_vfsops = {
kernfs_mount,
kernfs_start,
diff --git a/sys/miscfs/kernfs/kernfs_vnops.c b/sys/miscfs/kernfs/kernfs_vnops.c
index afd30e7..108c443 100644
--- a/sys/miscfs/kernfs/kernfs_vnops.c
+++ b/sys/miscfs/kernfs/kernfs_vnops.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)kernfs_vnops.c 8.6 (Berkeley) 2/10/94
+ * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -67,41 +67,44 @@
#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
static struct kern_target {
+ u_char kt_type;
+ u_char kt_namlen;
char *kt_name;
void *kt_data;
-#define KTT_NULL 1
-#define KTT_TIME 5
-#define KTT_INT 17
-#define KTT_STRING 31
-#define KTT_HOSTNAME 47
-#define KTT_BOOTFILE 49
-#define KTT_AVENRUN 53
- int kt_tag;
- int kt_rw;
- int kt_vtype;
- struct vnode **kt_vp;
+#define KTT_NULL 1
+#define KTT_TIME 5
+#define KTT_INT 17
+#define KTT_STRING 31
+#define KTT_HOSTNAME 47
+#define KTT_BOOTFILE 49
+#define KTT_AVENRUN 53
+#define KTT_DEVICE 71
+ u_char kt_tag;
+ u_char kt_vtype;
+ mode_t kt_mode;
} kern_targets[] = {
/* NOTE: The name must be less than UIO_MX-16 chars in length */
- /* name data tag ro/rw type vnodep*/
- { ".", 0, KTT_NULL, VREAD, VDIR, NULL },
- { "..", 0, KTT_NULL, VREAD, VDIR, NULL },
- { "boottime", &boottime.tv_sec, KTT_INT, VREAD, VREG, NULL },
- { "copyright", copyright, KTT_STRING, VREAD, VREG, NULL },
- { "hostname", 0, KTT_HOSTNAME,VREAD|VWRITE,VREG, NULL },
- { "bootfile", 0, KTT_BOOTFILE, VREAD, VREG, NULL },
- { "hz", &hz, KTT_INT, VREAD, VREG, NULL },
- { "loadavg", 0, KTT_AVENRUN, VREAD, VREG, NULL },
- { "pagesize", &cnt.v_page_size, KTT_INT, VREAD, VREG, NULL },
- { "physmem", &physmem, KTT_INT, VREAD, VREG, NULL },
+#define N(s) sizeof(s)-1, s
+ /* name data tag type ro/rw */
+ { DT_DIR, N("."), 0, KTT_NULL, VDIR, DIR_MODE },
+ { DT_DIR, N(".."), 0, KTT_NULL, VDIR, DIR_MODE },
+ { DT_REG, N("boottime"), &boottime.tv_sec, KTT_INT, VREG, READ_MODE },
+ { DT_REG, N("copyright"), copyright, KTT_STRING, VREG, READ_MODE },
+ { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE },
+ { DT_REG, N("bootfile"), 0, KTT_BOOTFILE, VREG, READ_MODE },
+ { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE },
+ { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE },
+ { DT_REG, N("pagesize"), &cnt.v_page_size, KTT_INT, VREG, READ_MODE },
+ { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE },
#if 0
- { "root", 0, KTT_NULL, VREAD, VDIR, &rootdir},
- { "rootdev", 0, KTT_NULL, VREAD, VBLK, &rootvp },
- { "rrootdev", 0, KTT_NULL, VREAD, VCHR, &rrootvp},
+ { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE },
+ { DT_BLK, N("rootdev"), &rootdev, KTT_DEVICE, VBLK, READ_MODE },
+ { DT_CHR, N("rrootdev"), &rrootdev, KTT_DEVICE, VCHR, READ_MODE },
#endif
- { "time", 0, KTT_TIME, VREAD, VREG, NULL },
- { "version", version, KTT_STRING, VREAD, VREG, NULL },
+ { DT_REG, N("time"), 0, KTT_TIME, VREG, READ_MODE },
+ { DT_REG, N("version"), version, KTT_STRING, VREG, READ_MODE },
+#undef N
};
-
static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
static int kernfs_access __P((struct vop_access_args *ap));
@@ -130,6 +133,7 @@ kernfs_xread(kt, buf, len, lenp)
int len;
int *lenp;
{
+
switch (kt->kt_tag) {
case KTT_TIME: {
struct timeval tv;
@@ -183,14 +187,12 @@ kernfs_xread(kt, buf, len, lenp)
case KTT_AVENRUN:
sprintf(buf, "%ld %ld %ld %ld\n",
- averunnable.ldavg[0],
- averunnable.ldavg[1],
- averunnable.ldavg[2],
- averunnable.fscale);
+ averunnable.ldavg[0], averunnable.ldavg[1],
+ averunnable.ldavg[2], averunnable.fscale);
break;
default:
- return (EINVAL);
+ return (EIO);
}
*lenp = strlen(buf);
@@ -203,15 +205,15 @@ kernfs_xwrite(kt, buf, len)
char *buf;
int len;
{
+
switch (kt->kt_tag) {
- case KTT_HOSTNAME: {
+ case KTT_HOSTNAME:
/* XXX BOGUS !!! no check for the length */
if (buf[len-1] == '\n')
--len;
bcopy(buf, hostname, len);
hostname[len] = '\0';
return (0);
- }
default:
return (EIO);
@@ -231,26 +233,32 @@ kernfs_lookup(ap)
struct componentname * a_cnp;
} */ *ap;
{
+ struct componentname *cnp = ap->a_cnp;
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
- struct componentname *cnp = ap->a_cnp;
+ char *pname = cnp->cn_nameptr;
+ struct proc *p = cnp->cn_proc;
+ struct kern_target *kt;
struct vnode *fvp;
int nameiop = cnp->cn_nameiop;
int error, i;
- char *pname;
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_lookup(%x)\n", ap);
printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp);
-#endif
- pname = cnp->cn_nameptr;
-#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_lookup(%s)\n", pname);
#endif
+
+ *vpp = NULLVP;
+
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
+ return (EROFS);
+
+ VOP_UNLOCK(dvp, 0, p);
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- /*VOP_LOCK(dvp);*/
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
return (0);
}
@@ -258,91 +266,58 @@ kernfs_lookup(ap)
if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
*vpp = rootdir;
VREF(rootdir);
- VOP_LOCK(rootdir);
+ vn_lock(rootdir, LK_SHARED | LK_RETRY, p)
return (0);
}
#endif
- error = ENOENT;
-
- for (i = 0; i < nkern_targets; i++) {
- struct kern_target *kt = &kern_targets[i];
- if (cnp->cn_namelen == strlen(kt->kt_name) &&
- bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) {
- error = 0;
- break;
- }
+ for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) {
+ if (cnp->cn_namelen == kt->kt_namlen &&
+ bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
+ goto found;
}
#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_lookup: i = %d, error = %d\n", i, error);
+ printf("kernfs_lookup: i = %d, failed", i);
#endif
- /*
- * If the name wasn't found, and this is not a LOOKUP
- * request, we return EOPNOTSUPP so that the initial namei()
- * fails and the higher level routines will not try to call
- * our VOP_* functions.
- */
- if (error) {
- if (nameiop != LOOKUP)
- error = EOPNOTSUPP;
- goto bad;
- }
-
- /*
- * DELETE requests are not supported.
- */
- if (nameiop == DELETE) {
- error = EOPNOTSUPP;
- goto bad;
- }
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
+ return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
- /*
- * Allow CREATE requests if the name in question can
- * be written to. This allows open(name, O_RDWR | O_CREAT)
- * to work. Otherwise CREATE requests are not supported.
- */
- if (nameiop == CREATE && (kern_targets[i].kt_rw & VWRITE == 0)) {
- error = EOPNOTSUPP;
- goto bad;
- }
-
- /*
- * Check if this name has already has a vnode associated with it.
- */
- if (kern_targets[i].kt_vp) {
- if (*kern_targets[i].kt_vp) {
- *vpp = *kern_targets[i].kt_vp;
- VREF(*vpp);
- VOP_LOCK(*vpp);
- return (0);
+found:
+ if (kt->kt_tag == KTT_DEVICE) {
+ dev_t *dp = kt->kt_data;
+ loop:
+ if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) {
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
+ return (ENOENT);
}
- error = ENXIO;
- goto bad;
+ *vpp = fvp;
+ if (vget(fvp, LK_EXCLUSIVE, p))
+ goto loop;
+ return (0);
}
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_lookup: allocate new vnode\n");
#endif
- error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
- if (error)
- goto bad;
- MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK);
- VTOKERN(fvp)->kf_kt = &kern_targets[i];
- fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
+ if (error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p,
+ &fvp)) {
+ vn_lock(dvp, LK_SHARED | LK_RETRY, p);
+ 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, p);
*vpp = fvp;
+
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_lookup: newvp = %x\n", fvp);
#endif
return (0);
-
-bad:;
- *vpp = NULL;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_lookup: error = %d\n", error);
-#endif
- return (error);
}
static int
@@ -354,22 +329,8 @@ kernfs_open(ap)
struct proc *a_p;
} */ *ap;
{
- struct vnode *vp = ap->a_vp;
-
- /*
- * Can always open the root (modulo perms)
- */
- if (vp->v_flag & VROOT)
- return (0);
-
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_open, mode = %x, file = %s\n",
- ap->a_mode, VTOKERN(vp)->kf_kt->kt_name);
-#endif
-
- if ((ap->a_mode & FWRITE) && !(VTOKERN(vp)->kf_kt->kt_rw & VWRITE))
- return (EOPNOTSUPP);
+ /* Only need to check access permissions. */
return (0);
}
@@ -382,33 +343,45 @@ kernfs_access(ap)
struct proc *a_p;
} */ *ap;
{
- struct vnode *vp = ap->a_vp;
- struct ucred *cred = ap->a_cred;
- mode_t mode = ap->a_mode;
-
- if (mode & VEXEC) {
- if (vp->v_flag & VROOT)
- return (0);
- return (EACCES);
- }
+ register struct vnode *vp = ap->a_vp;
+ register struct ucred *cred = ap->a_cred;
+ mode_t amode = ap->a_mode;
+ mode_t fmode =
+ (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode;
+ mode_t mask = 0;
+ register gid_t *gp;
+ int i;
- if (cred->cr_uid == 0) {
- if ((vp->v_flag & VROOT) == 0) {
- struct kern_target *kt = VTOKERN(vp)->kf_kt;
+ /* Some files are simply not modifiable. */
+ if ((amode & VWRITE) && (fmode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0)
+ return (EPERM);
- if ((mode & VWRITE) && !(kt->kt_rw & VWRITE))
- return (EROFS);
- }
+ /* Root can do anything else. */
+ if (cred->cr_uid == 0)
return (0);
- }
- if (mode & VWRITE)
- return (EACCES);
+ /* Check for group 0 (wheel) permissions. */
+ for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
+ if (*gp == 0) {
+ if (amode & VEXEC)
+ mask |= S_IXGRP;
+ if (amode & VREAD)
+ mask |= S_IRGRP;
+ if (amode & VWRITE)
+ mask |= S_IWGRP;
+ return ((fmode & mask) == mask ? 0 : EACCES);
+ }
- return (0);
+ /* Otherwise, check everyone else. */
+ if (amode & VEXEC)
+ mask |= S_IXOTH;
+ if (amode & VREAD)
+ mask |= S_IROTH;
+ if (amode & VWRITE)
+ mask |= S_IWOTH;
+ return ((fmode & mask) == mask ? 0 : EACCES);
}
-
static int
kernfs_getattr(ap)
struct vop_getattr_args /* {
@@ -420,6 +393,7 @@ kernfs_getattr(ap)
{
struct vnode *vp = ap->a_vp;
struct vattr *vap = ap->a_vap;
+ struct timeval tv;
int error = 0;
char strbuf[KSTRING];
@@ -428,7 +402,7 @@ kernfs_getattr(ap)
vap->va_uid = 0;
vap->va_gid = 0;
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
- /* vap->va_qsize = 0; */
+ vap->va_size = 0;
vap->va_blocksize = DEV_BSIZE;
{
struct timeval tv;
@@ -440,7 +414,6 @@ kernfs_getattr(ap)
vap->va_gen = 0;
vap->va_flags = 0;
vap->va_rdev = 0;
- /* vap->va_qbytes = 0; */
vap->va_bytes = 0;
if (vp->v_flag & VROOT) {
@@ -459,14 +432,13 @@ kernfs_getattr(ap)
printf("kernfs_getattr: stat target %s\n", kt->kt_name);
#endif
vap->va_type = kt->kt_vtype;
- vap->va_mode = (kt->kt_rw & VWRITE ? WRITE_MODE : READ_MODE);
+ vap->va_mode = kt->kt_mode;
vap->va_nlink = 1;
- vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
+ vap->va_fileid = 1 + (kt - kern_targets) / sizeof(*kt);
error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes);
vap->va_size = nbytes;
}
- vp->v_type = vap->va_type;
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_getattr: return error %d\n", error);
#endif
@@ -509,7 +481,7 @@ kernfs_read(ap)
int error, len;
char *cp;
- if (vp->v_flag & VROOT)
+ if (vp->v_type == VDIR)
return (EOPNOTSUPP);
kt = VTOKERN(vp)->kf_kt;
@@ -519,12 +491,11 @@ kernfs_read(ap)
#endif
len = 0;
- error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
- if (error)
+ if (error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len))
return (error);
- cp = strbuf + off;
- len -= off;
- return (uiomove(cp, len, uio));
+ if (len <= off)
+ return (0);
+ return (uiomove(&strbuf[off], len - off, uio));
}
static int
@@ -542,8 +513,8 @@ kernfs_write(ap)
int error, xlen;
char strbuf[KSTRING];
- if (vp->v_flag & VROOT)
- return (0);
+ if (vp->v_type == VDIR)
+ return (EOPNOTSUPP);
kt = VTOKERN(vp)->kf_kt;
@@ -551,8 +522,7 @@ kernfs_write(ap)
return (EINVAL);
xlen = min(uio->uio_resid, KSTRING-1);
- error = uiomove(strbuf, xlen, uio);
- if (error)
+ if (error = uiomove(strbuf, xlen, uio))
return (error);
if (uio->uio_resid != 0)
@@ -563,33 +533,52 @@ kernfs_write(ap)
return (kernfs_xwrite(kt, strbuf, xlen));
}
-
static int
kernfs_readdir(ap)
struct vop_readdir_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
+ int error, i;
struct uio *uio = ap->a_uio;
- int i;
- int error;
+ struct kern_target *kt;
+ struct dirent d;
+
+ if (ap->a_vp->v_type != VDIR)
+ return (ENOTDIR);
+
+ /*
+ * We don't allow exporting kernfs mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies != NULL)
+ panic("kernfs_readdir: not hungry");
i = uio->uio_offset / UIO_MX;
error = 0;
- while (uio->uio_resid > 0 && i < nkern_targets) {
- struct dirent d;
+ for (kt = &kern_targets[i];
+ uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) {
struct dirent *dp = &d;
- struct kern_target *kt = &kern_targets[i];
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_readdir: i = %d\n", i);
#endif
- bzero((caddr_t) dp, UIO_MX);
+ if (kt->kt_tag == KTT_DEVICE) {
+ dev_t *dp = kt->kt_data;
+ struct vnode *fvp;
+
+ if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp))
+ continue;
+ }
- dp->d_namlen = strlen(kt->kt_name);
- bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
+ bzero((caddr_t)dp, UIO_MX);
+ dp->d_namlen = kt->kt_namlen;
+ bcopy(kt->kt_name, dp->d_name, kt->kt_namlen+1);
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_readdir: name = %s, len = %d\n",
@@ -600,14 +589,12 @@ kernfs_readdir(ap)
*/
dp->d_reclen = UIO_MX;
dp->d_fileno = i + 3;
- dp->d_type = DT_UNKNOWN; /* XXX */
+ dp->d_type = kt->kt_type;
/*
* And ship to userland
*/
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
+ if (error = uiomove((caddr_t)dp, UIO_MX, uio))
break;
- i++;
}
uio->uio_offset = i * UIO_MX;
@@ -619,18 +606,20 @@ static int
kernfs_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+#ifdef KERNFS_DIAGNOSTIC
+ printf("kernfs_inactive(%x)\n", vp);
+#endif
/*
* Clear out the v_type field to avoid
* nasty things happening in vgone().
*/
+ VOP_UNLOCK(vp, 0, ap->a_p);
vp->v_type = VNON;
-#ifdef KERNFS_DIAGNOSTIC
- printf("kernfs_inactive(%x)\n", vp);
-#endif
return (0);
}
@@ -641,6 +630,7 @@ kernfs_reclaim(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+
#ifdef KERNFS_DIAGNOSTIC
printf("kernfs_reclaim(%x)\n", vp);
#endif
@@ -717,16 +707,6 @@ kernfs_vfree(ap)
}
/*
- * Kernfs vnode unsupported operation
- */
-static int
-kernfs_enotsupp()
-{
-
- return (EOPNOTSUPP);
-}
-
-/*
* Kernfs "should never get here" operation
*/
static int
@@ -735,42 +715,42 @@ kernfs_badop()
return (EIO);
}
-#define kernfs_create ((int (*) __P((struct vop_create_args *)))kernfs_enotsupp)
-#define kernfs_mknod ((int (*) __P((struct vop_mknod_args *)))kernfs_enotsupp)
+#define kernfs_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
+#define kernfs_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
#define kernfs_close ((int (*) __P((struct vop_close_args *)))nullop)
-#define kernfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))kernfs_enotsupp)
-#define kernfs_select ((int (*) __P((struct vop_select_args *)))kernfs_enotsupp)
-#define kernfs_mmap ((int (*) __P((struct vop_mmap_args *)))kernfs_enotsupp)
+#define kernfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))eopnotsupp)
+#define kernfs_select ((int (*) __P((struct vop_select_args *)))eopnotsupp)
+#define kernfs_revoke vop_revoke
+#define kernfs_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
#define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
-#define kernfs_remove ((int (*) __P((struct vop_remove_args *)))kernfs_enotsupp)
-#define kernfs_link ((int (*) __P((struct vop_link_args *)))kernfs_enotsupp)
-#define kernfs_rename ((int (*) __P((struct vop_rename_args *)))kernfs_enotsupp)
-#define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))kernfs_enotsupp)
-#define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))kernfs_enotsupp)
-#define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp)
-#define kernfs_readlink \
- ((int (*) __P((struct vop_readlink_args *)))kernfs_enotsupp)
+#define kernfs_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
+#define kernfs_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
+#define kernfs_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
+#define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
+#define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
+#define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
+#define kernfs_readlink ((int (*) __P((struct vop_readlink_args *)))eopnotsupp)
#define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
-#define kernfs_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define kernfs_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
#define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop)
-#define kernfs_strategy ((int (*) __P((struct vop_strategy_args *)))kernfs_badop)
-#define kernfs_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
-#define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp)
-#define kernfs_blkatoff \
- ((int (*) __P((struct vop_blkatoff_args *)))kernfs_enotsupp)
+#define kernfs_strategy \
+ ((int (*) __P((struct vop_strategy_args *)))kernfs_badop)
+#define kernfs_islocked \
+ ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
+#define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
+#define kernfs_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
#define kernfs_valloc ((int(*) __P(( \
struct vnode *pvp, \
int mode, \
struct ucred *cred, \
- struct vnode **vpp))) kernfs_enotsupp)
-#define kernfs_truncate \
- ((int (*) __P((struct vop_truncate_args *)))kernfs_enotsupp)
-#define kernfs_update ((int (*) __P((struct vop_update_args *)))kernfs_enotsupp)
-#define kernfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))kernfs_enotsupp)
+ struct vnode **vpp))) eopnotsupp)
+#define kernfs_truncate ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
+#define kernfs_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
+#define kernfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
-vop_t **kernfs_vnodeop_p;
+vop_t **kernfs_vnodeop_p;
static struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
{ &vop_lookup_desc, (vop_t *)kernfs_lookup }, /* lookup */
@@ -785,6 +765,7 @@ static struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
{ &vop_write_desc, (vop_t *)kernfs_write }, /* write */
{ &vop_ioctl_desc, (vop_t *)kernfs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)kernfs_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)kernfs_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)kernfs_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)kernfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)kernfs_seek }, /* seek */
diff --git a/sys/miscfs/nullfs/null.h b/sys/miscfs/nullfs/null.h
index beadb42..70a81b2 100644
--- a/sys/miscfs/nullfs/null.h
+++ b/sys/miscfs/nullfs/null.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)null.h 8.2 (Berkeley) 1/21/94
+ * @(#)null.h 8.3 (Berkeley) 8/20/94
*
* $FreeBSD$
*/
@@ -52,8 +52,7 @@ struct null_mount {
* A cache of vnode references
*/
struct null_node {
- struct null_node *null_forw; /* Hash chain */
- struct null_node *null_back;
+ LIST_ENTRY(null_node) null_hash; /* Hash list */
struct vnode *null_lowervp; /* VREFed once */
struct vnode *null_vnode; /* Back pointer */
};
diff --git a/sys/miscfs/nullfs/null_subr.c b/sys/miscfs/nullfs/null_subr.c
index a14a7e4..4418631 100644
--- a/sys/miscfs/nullfs/null_subr.c
+++ b/sys/miscfs/nullfs/null_subr.c
@@ -33,13 +33,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)null_subr.c 8.4 (Berkeley) 1/21/94
+ * @(#)null_subr.c 8.7 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -48,11 +49,8 @@
#include <sys/malloc.h>
#include <miscfs/nullfs/null.h>
-extern int nullfs_init __P((void));
-
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NNULLNODECACHE 16
-#define NULL_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NNULLNODECACHE-1))
/*
* Null layer cache:
@@ -62,51 +60,32 @@ extern int nullfs_init __P((void));
* alias is removed the lower vnode is vrele'd.
*/
-/*
- * Cache head
- */
-struct null_node_cache {
- struct null_node *ac_forw;
- struct null_node *ac_back;
-};
-
-static struct null_node_cache null_node_cache[NNULLNODECACHE];
+#define NULL_NHASH(vp) \
+ (&null_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & null_node_hash])
+LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
+u_long null_node_hash;
static int null_node_alloc __P((struct mount *mp, struct vnode *lowervp,
struct vnode **vpp));
static struct vnode *
null_node_find __P((struct mount *mp, struct vnode *lowervp));
-static struct null_node_cache *
- null_node_hash __P((struct vnode *lowervp));
/*
* Initialise cache headers
*/
int
-nullfs_init()
+nullfs_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct null_node_cache *ac;
+
#ifdef NULLFS_DIAGNOSTIC
printf("nullfs_init\n"); /* printed during system boot */
#endif
-
- for (ac = null_node_cache; ac < null_node_cache + NNULLNODECACHE; ac++)
- ac->ac_forw = ac->ac_back = (struct null_node *) ac;
+ null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
return (0);
}
/*
- * Compute hash list for given lower vnode
- */
-static struct null_node_cache *
-null_node_hash(lowervp)
-struct vnode *lowervp;
-{
-
- return (&null_node_cache[NULL_NHASH(lowervp)]);
-}
-
-/*
* Return a VREF'ed alias for lower vnode if already exists, else 0.
*/
static struct vnode *
@@ -114,7 +93,8 @@ null_node_find(mp, lowervp)
struct mount *mp;
struct vnode *lowervp;
{
- struct null_node_cache *hd;
+ struct proc *p = curproc; /* XXX */
+ struct null_node_hashhead *hd;
struct null_node *a;
struct vnode *vp;
@@ -124,9 +104,9 @@ null_node_find(mp, lowervp)
* the lower vnode. If found, the increment the null_node
* reference count (but NOT the lower vnode's VREF counter).
*/
- hd = null_node_hash(lowervp);
+ hd = NULL_NHASH(lowervp);
loop:
- for (a = hd->ac_forw; a != (struct null_node *) hd; a = a->null_forw) {
+ for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
vp = NULLTOV(a);
/*
@@ -134,7 +114,7 @@ loop:
* stuff, but we don't want to lock
* the lower node.
*/
- if (vget(vp, 0)) {
+ if (vget(vp, 0, p)) {
printf ("null_node_find: vget failed.\n");
goto loop;
};
@@ -157,7 +137,7 @@ null_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
- struct null_node_cache *hd;
+ struct null_node_hashhead *hd;
struct null_node *xp;
struct vnode *othervp, *vp;
int error;
@@ -194,8 +174,8 @@ null_node_alloc(mp, lowervp, vpp)
return 0;
};
VREF(lowervp); /* Extra VREF will be vrele'd in null_node_create */
- hd = null_node_hash(lowervp);
- insque(xp, hd);
+ hd = NULL_NHASH(lowervp);
+ LIST_INSERT_HEAD(hd, xp, null_hash);
return 0;
}
@@ -250,9 +230,8 @@ null_node_create(mp, lowervp, newvpp)
#ifdef DIAGNOSTIC
if (lowervp->v_usecount < 1) {
/* Should never happen... */
- vprint ("null_node_create: alias ",aliasvp);
- vprint ("null_node_create: lower ",lowervp);
- printf ("null_node_create: lower has 0 usecount.\n");
+ vprint ("null_node_create: alias ", aliasvp);
+ vprint ("null_node_create: lower ", lowervp);
panic ("null_node_create: lower has 0 usecount.");
};
#endif
diff --git a/sys/miscfs/nullfs/null_vfsops.c b/sys/miscfs/nullfs/null_vfsops.c
index e2aeeba..339b7c1 100644
--- a/sys/miscfs/nullfs/null_vfsops.c
+++ b/sys/miscfs/nullfs/null_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -46,7 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -55,7 +55,7 @@
#include <sys/malloc.h>
#include <miscfs/nullfs/null.h>
-extern int nullfs_init __P((void));
+extern int nullfs_init __P((struct vfsconf *));
static int nullfs_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -146,7 +146,7 @@ nullfs_mount(mp, path, data, ndp, p)
/*
* Unlock the node (either the lower or the alias)
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
/*
* Make sure the node alias worked
*/
@@ -166,7 +166,7 @@ nullfs_mount(mp, path, data, ndp, p)
if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) xmp;
- getnewfsid(mp, MOUNT_LOFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -212,12 +212,8 @@ nullfs_unmount(mp, mntflags, p)
printf("nullfs_unmount(mp = %x)\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
@@ -259,6 +255,7 @@ nullfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef NULLFS_DIAGNOSTIC
@@ -273,7 +270,7 @@ nullfs_root(mp, vpp)
*/
vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return 0;
}
diff --git a/sys/miscfs/nullfs/null_vnops.c b/sys/miscfs/nullfs/null_vnops.c
index ec279bc..c1af96f 100644
--- a/sys/miscfs/nullfs/null_vnops.c
+++ b/sys/miscfs/nullfs/null_vnops.c
@@ -33,7 +33,13 @@
* 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: null_vnops.c,v 1.11.2000.1 1996/09/17 14:32:31 peter Exp $
+ * ...and...
+ * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*
* $FreeBSD$
*/
@@ -88,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
@@ -178,7 +192,7 @@ static int null_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW,
&null_bug_bypass, 0, "");
-static int null_bypass __P((struct vop_generic_args *ap));
+int null_bypass __P((struct vop_generic_args *ap));
static int null_bwrite __P((struct vop_bwrite_args *ap));
static int null_getattr __P((struct vop_getattr_args *ap));
static int null_inactive __P((struct vop_inactive_args *ap));
@@ -211,7 +225,7 @@ static int null_strategy __P((struct vop_strategy_args *ap));
* - all mapped vnodes are of our vnode-type (NEEDSWORK:
* problems on rmdir'ing mount points and renaming?)
*/
-static int
+int
null_bypass(ap)
struct vop_generic_args /* {
struct vnodeop_desc *a_desc;
@@ -254,7 +268,8 @@ null_bypass(ap)
* 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)->v_op != null_vnodeop_p) {
+ if (i && (*this_vp_p == NULL ||
+ (*this_vp_p)->v_op != null_vnodeop_p)) {
old_vps[i] = NULL;
} else {
old_vps[i] = *this_vp_p;
@@ -317,6 +332,105 @@ null_bypass(ap)
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.
+ */
+static int
+null_lookup(ap)
+ struct vop_lookup_args /* {
+ struct vnode * a_dvp;
+ struct vnode ** a_vpp;
+ struct componentname * a_cnp;
+ } */ *ap;
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ 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;
+ unlockargs.a_p = p;
+ vop_nounlock(&unlockargs);
+ }
+ if (vp != NULL && VOP_ISLOCKED(vp)) {
+ lockargs.a_vp = vp;
+ lockargs.a_flags = LK_SHARED;
+ lockargs.a_p = p;
+ vop_nolock(&lockargs);
+ }
+ return (error);
+}
+
+/*
+ * Setattr call. Disallow write attempts if the layer is mounted read-only.
+ */
+int
+null_setattr(ap)
+ 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;
+{
+ 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.ts_sec != VNOVAL ||
+ vap->va_mtime.ts_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.
@@ -331,19 +445,90 @@ null_getattr(ap)
} */ *ap;
{
int error;
- error = null_bypass(ap);
- if (error)
+
+ if (error = null_bypass(ap))
return (error);
/* Requires that arguments be restored. */
ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
-
static int
+null_access(ap)
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
+{
+ 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;
+ }
+ }
+ 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(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ vop_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(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ vop_nounlock(ap);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
+int
null_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
/*
@@ -358,6 +543,7 @@ null_inactive(ap)
* like they do in the name lookup cache code.
* That's too much work for now.
*/
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -365,6 +551,7 @@ static int
null_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
@@ -377,14 +564,13 @@ null_reclaim(ap)
*/
/* After this assignment, this node will not be re-used. */
xp->null_lowervp = NULL;
- remque(xp);
+ LIST_REMOVE(xp, null_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele (lowervp);
return (0);
}
-
static int
null_print(ap)
struct vop_print_args /* {
@@ -396,7 +582,6 @@ null_print(ap)
return (0);
}
-
/*
* XXX - vop_strategy must be hand coded because it has no
* vnode in its arguments.
@@ -422,7 +607,6 @@ null_strategy(ap)
return (error);
}
-
/*
* XXX - like vop_strategy, vop_bwrite must be hand coded because it has no
* vnode in its arguments.
@@ -455,7 +639,12 @@ vop_t **null_vnodeop_p;
static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)null_bypass },
+ { &vop_lookup_desc, (vop_t *)null_lookup },
+ { &vop_setattr_desc, (vop_t *)null_setattr },
{ &vop_getattr_desc, (vop_t *)null_getattr },
+ { &vop_access_desc, (vop_t *)null_access },
+ { &vop_lock_desc, (vop_t *)null_lock },
+ { &vop_unlock_desc, (vop_t *)null_unlock },
{ &vop_inactive_desc, (vop_t *)null_inactive },
{ &vop_reclaim_desc, (vop_t *)null_reclaim },
{ &vop_print_desc, (vop_t *)null_print },
diff --git a/sys/miscfs/portal/portal_vfsops.c b/sys/miscfs/portal/portal_vfsops.c
index a980f65..74e1542 100644
--- a/sys/miscfs/portal/portal_vfsops.c
+++ b/sys/miscfs/portal/portal_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)portal_vfsops.c 8.6 (Berkeley) 1/21/94
+ * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -62,28 +62,18 @@
#include <sys/un.h>
#include <miscfs/portal/portal.h>
-static int portal_init __P((void));
static int portal_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
static int portal_start __P((struct mount *mp, int flags, struct proc *p));
static int portal_unmount __P((struct mount *mp, int mntflags,
struct proc *p));
static int portal_root __P((struct mount *mp, struct vnode **vpp));
-static int portal_quotactl __P((struct mount *mp, int cmd, uid_t uid,
- caddr_t arg, struct proc *p));
static int portal_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int portal_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
-static int portal_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int portal_fhtovp __P((struct mount *mp, struct fid *fhp,
- struct mbuf *nam, struct vnode **vpp,
- int *exflagsp, struct ucred **credanonp));
-static int portal_vptofh __P((struct vnode *vp, struct fid *fhp));
static int
-portal_init()
+portal_init(vfsp)
+ struct vfsconf *vfsp;
{
return (0);
@@ -150,7 +140,7 @@ portal_mount(mp, path, data, ndp, p)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) fmp;
- getnewfsid(mp, MOUNT_PORTAL);
+ vfs_getnewfsid(mp);
(void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -186,12 +176,8 @@ portal_unmount(mp, mntflags, p)
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
@@ -241,39 +227,26 @@ portal_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
-
/*
* Return locked reference to root.
*/
vp = VFSTOPORTAL(mp)->pm_root;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
static int
-portal_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
portal_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
struct proc *p;
{
- sbp->f_type = MOUNT_PORTAL;
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
@@ -283,6 +256,7 @@ portal_statfs(mp, sbp, p)
sbp->f_files = 1; /* Allow for "." */
sbp->f_ffree = 0; /* See comments above */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -290,48 +264,17 @@ portal_statfs(mp, sbp, p)
return (0);
}
-static int
-portal_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
-
- return (0);
-}
-
-static int
-portal_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-portal_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-portal_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+#define portal_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define portal_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define portal_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+#define portal_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define portal_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define portal_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
static struct vfsops portal_vfsops = {
portal_mount,
diff --git a/sys/miscfs/portal/portal_vnops.c b/sys/miscfs/portal/portal_vnops.c
index 8135a5e..19b439c 100644
--- a/sys/miscfs/portal/portal_vnops.c
+++ b/sys/miscfs/portal/portal_vnops.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94
+ * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
*
* $FreeBSD$
*/
@@ -112,17 +112,25 @@ portal_lookup(ap)
struct componentname * a_cnp;
} */ *ap;
{
- char *pname = ap->a_cnp->cn_nameptr;
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode **vpp = ap->a_vpp;
+ struct vnode *dvp = ap->a_dvp;
+ char *pname = cnp->cn_nameptr;
struct portalnode *pt;
int error;
struct vnode *fvp = 0;
char *path;
int size;
- if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
- *ap->a_vpp = ap->a_dvp;
- VREF(ap->a_dvp);
- /*VOP_LOCK(ap->a_dvp);*/
+ *vpp = NULLVP;
+
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
+ return (EROFS);
+
+ if (cnp->cn_namelen == 1 && *pname == '.') {
+ *vpp = dvp;
+ VREF(dvp);
+ /*VOP_LOCK(dvp);*/
return (0);
}
@@ -134,7 +142,7 @@ portal_lookup(ap)
MALLOC(pt, struct portalnode *, sizeof(struct portalnode),
M_TEMP, M_WAITOK);
- error = getnewvnode(VT_PORTAL, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp);
+ error = getnewvnode(VT_PORTAL, dvp->v_mount, portal_vnodeop_p, &fvp);
if (error) {
FREE(pt, M_TEMP);
goto bad;
@@ -148,22 +156,20 @@ portal_lookup(ap)
*/
for (size = 0, path = pname; *path; path++)
size++;
- ap->a_cnp->cn_consume = size - ap->a_cnp->cn_namelen;
+ cnp->cn_consume = size - cnp->cn_namelen;
pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK);
pt->pt_size = size+1;
bcopy(pname, pt->pt_arg, pt->pt_size);
pt->pt_fileid = portal_fileid++;
- *ap->a_vpp = fvp;
+ *vpp = fvp;
/*VOP_LOCK(fvp);*/
return (0);
bad:;
- if (fvp) {
+ if (fvp)
vrele(fvp);
- }
- *ap->a_vpp = NULL;
return (error);
}
@@ -444,6 +450,7 @@ portal_getattr(ap)
{
struct vnode *vp = ap->a_vp;
struct vattr *vap = ap->a_vap;
+ struct timeval tv;
bzero(vap, sizeof(*vap));
vattr_null(vap);
@@ -452,8 +459,8 @@ portal_getattr(ap)
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
vap->va_size = DEV_BSIZE;
vap->va_blocksize = DEV_BSIZE;
- microtime((struct timeval *)&vap->va_atime);
- TIMEVAL_TO_TIMESPEC((struct timeval *)&vap->va_atime, (struct timespec *)&vap->va_atime);
+ microtime(&tv);
+ TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime);
vap->va_mtime = vap->va_atime;
vap->va_ctime = vap->va_ctime;
vap->va_gen = 0;
@@ -509,9 +516,19 @@ portal_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
+ /*
+ * We don't allow exporting portal mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("portal_readdir: not hungry");
+
return (0);
}
@@ -519,9 +536,11 @@ static int
portal_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -639,6 +658,7 @@ portal_badop()
#define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp)
#define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp)
#define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp)
+#define portal_revoke vop_revoke
#define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
#define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop)
#define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp)
@@ -651,12 +671,14 @@ portal_badop()
#define portal_readlink \
((int (*) __P((struct vop_readlink_args *)))portal_enotsupp)
#define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
-#define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
+#define portal_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
#define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop)
#define portal_strategy \
((int (*) __P((struct vop_strategy_args *)))portal_badop)
-#define portal_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define portal_islocked \
+ ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
+#define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
#define portal_advlock \
((int (*) __P((struct vop_advlock_args *)))portal_enotsupp)
#define portal_blkatoff \
@@ -687,6 +709,7 @@ static struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
{ &vop_ioctl_desc, (vop_t *)portal_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)portal_select }, /* select */
{ &vop_mmap_desc, (vop_t *)portal_mmap }, /* mmap */
+ { &vop_revoke_desc, (vop_t *)portal_revoke }, /* revoke */
{ &vop_fsync_desc, (vop_t *)portal_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)portal_seek }, /* seek */
{ &vop_remove_desc, (vop_t *)portal_remove }, /* remove */
diff --git a/sys/miscfs/procfs/procfs.h b/sys/miscfs/procfs/procfs.h
index df01a39..ef0d7eb 100644
--- a/sys/miscfs/procfs/procfs.h
+++ b/sys/miscfs/procfs/procfs.h
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs.h 8.6 (Berkeley) 2/3/94
+ * @(#)procfs.h 8.9 (Berkeley) 5/14/95
*
+ * From:
* $FreeBSD$
*/
@@ -44,6 +45,7 @@
*/
typedef enum {
Proot, /* the filesystem root */
+ Pcurproc, /* symbolic link for curproc */
Pproc, /* a process-specific sub-directory */
Pfile, /* the executable file */
Pmem, /* the process's memory image */
@@ -97,9 +99,9 @@ struct pfsdent {
};
#define UIO_MX sizeof(struct pfsdent)
#define PROCFS_FILENO(pid, type) \
- (((type) == Proot) ? \
- 2 : \
- ((((pid)+1) << 3) + ((int) (type))))
+ (((type) < Pproc) ? \
+ ((type) + 2) : \
+ ((((pid)+1) << 4) + ((int) (type))))
/*
* Convert between pfsnode vnode
@@ -113,33 +115,33 @@ struct vfs_namemap {
int nm_val;
};
-extern int vfs_getuserstr __P((struct uio *, char *, int *));
-extern vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
+int vfs_getuserstr __P((struct uio *, char *, int *));
+vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int));
/* <machine/reg.h> */
struct reg;
struct fpreg;
#define PFIND(pid) ((pid) ? pfind(pid) : &proc0)
-extern int procfs_freevp __P((struct vnode *));
-extern int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
-extern struct vnode *procfs_findtextvp __P((struct proc *));
-extern int procfs_sstep __P((struct proc *));
-extern void procfs_fix_sstep __P((struct proc *));
-extern int procfs_read_regs __P((struct proc *, struct reg *));
-extern int procfs_write_regs __P((struct proc *, struct reg *));
-extern int procfs_read_fpregs __P((struct proc *, struct fpreg *));
-extern int procfs_write_fpregs __P((struct proc *, struct fpreg *));
-extern int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-extern int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_freevp __P((struct vnode *));
+int procfs_allocvp __P((struct mount *, struct vnode **, long, pfstype));
+struct vnode *procfs_findtextvp __P((struct proc *));
+int procfs_sstep __P((struct proc *));
+void procfs_fix_sstep __P((struct proc *));
+int procfs_read_regs __P((struct proc *, struct reg *));
+int procfs_write_regs __P((struct proc *, struct reg *));
+int procfs_read_fpregs __P((struct proc *, struct fpreg *));
+int procfs_write_fpregs __P((struct proc *, struct fpreg *));
+int procfs_donote __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_doregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dofpregs __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_doctl __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dostatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_domap __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
+int procfs_dotype __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-/* check to see if the process has the "items" (regs/file) */
+/* functions to check whether or not files should be displayed */
int procfs_validfile __P((struct proc *));
int procfs_validfpregs __P((struct proc *));
int procfs_validregs __P((struct proc *));
diff --git a/sys/miscfs/procfs/procfs_ctl.c b/sys/miscfs/procfs/procfs_ctl.c
index 4ddf7a7..68b93dd 100644
--- a/sys/miscfs/procfs/procfs_ctl.c
+++ b/sys/miscfs/procfs/procfs_ctl.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_ctl.c 8.3 (Berkeley) 1/21/94
+ * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
@@ -51,13 +52,13 @@
#include <sys/resourcevar.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/vm_extern.h>
-
+#include <sys/ptrace.h>
#include <miscfs/procfs/procfs.h>
+#ifndef FIX_SSTEP
+#define FIX_SSTEP(p)
+#endif
+
/*
* True iff process (p) is in trace wait state
* relative to process (curp)
@@ -67,13 +68,6 @@
(p)->p_pptr == (curp) && \
((p)->p_flag & P_TRACED))
-#ifdef notdef
-#define FIX_SSTEP(p) { \
- procfs_fix_sstep(p); \
- } \
-}
-#endif
-
#define PROCFS_CTL_ATTACH 1
#define PROCFS_CTL_DETACH 2
#define PROCFS_CTL_STEP 3
@@ -220,8 +214,10 @@ procfs_control(curp, p, op)
*/
case PROCFS_CTL_STEP:
PHOLD(p);
- procfs_sstep(p);
+ error = procfs_sstep(p);
PRELE(p);
+ if (error)
+ return (error);
break;
/*
diff --git a/sys/miscfs/procfs/procfs_fpregs.c b/sys/miscfs/procfs/procfs_fpregs.c
index a3cad5f..841cf76 100644
--- a/sys/miscfs/procfs/procfs_fpregs.c
+++ b/sys/miscfs/procfs/procfs_fpregs.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_fpregs.c 8.1 (Berkeley) 1/27/94
+ * @(#)procfs_fpregs.c 8.2 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
diff --git a/sys/miscfs/procfs/procfs_map.c b/sys/miscfs/procfs/procfs_map.c
index 27c44fa..40c40d8 100644
--- a/sys/miscfs/procfs/procfs_map.c
+++ b/sys/miscfs/procfs/procfs_map.c
@@ -59,7 +59,7 @@
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
#include <vm/vm_inherit.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_page.h>
diff --git a/sys/miscfs/procfs/procfs_mem.c b/sys/miscfs/procfs/procfs_mem.c
index 4e8fac6..06364e5 100644
--- a/sys/miscfs/procfs/procfs_mem.c
+++ b/sys/miscfs/procfs/procfs_mem.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_mem.c 8.4 (Berkeley) 1/21/94
+ * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
*
* $FreeBSD$
*/
@@ -55,7 +55,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_kern.h>
@@ -295,14 +295,11 @@ procfs_domem(curp, p, pfs, uio)
struct pfsnode *pfs;
struct uio *uio;
{
- int error;
if (uio->uio_resid == 0)
return (0);
- error = procfs_rwmem(p, uio);
-
- return (error);
+ return (procfs_rwmem(p, uio));
}
/*
@@ -320,5 +317,6 @@ struct vnode *
procfs_findtextvp(p)
struct proc *p;
{
+
return (p->p_textvp);
}
diff --git a/sys/miscfs/procfs/procfs_regs.c b/sys/miscfs/procfs/procfs_regs.c
index 9282a3a..56ef233 100644
--- a/sys/miscfs/procfs/procfs_regs.c
+++ b/sys/miscfs/procfs/procfs_regs.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_regs.c 8.3 (Berkeley) 1/27/94
+ * @(#)procfs_regs.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c
index 432918d..76974b5 100644
--- a/sys/miscfs/procfs/procfs_status.c
+++ b/sys/miscfs/procfs/procfs_status.c
@@ -34,8 +34,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94
+ * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
*
+ * From:
* $FreeBSD$
*/
@@ -142,7 +143,7 @@ procfs_dostatus(curp, p, pfs, uio)
xlen = ps - psbuf;
xlen -= uio->uio_offset;
ps = psbuf + uio->uio_offset;
- xlen = min(xlen, uio->uio_resid);
+ xlen = imin(xlen, uio->uio_resid);
if (xlen <= 0)
error = 0;
else
diff --git a/sys/miscfs/procfs/procfs_subr.c b/sys/miscfs/procfs/procfs_subr.c
index d9b3d2f..5ee78f0 100644
--- a/sys/miscfs/procfs/procfs_subr.c
+++ b/sys/miscfs/procfs/procfs_subr.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_subr.c 8.4 (Berkeley) 1/27/94
+ * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -84,18 +84,21 @@ procfs_allocvp(mp, vpp, pid, pfs_type)
long pid;
pfstype pfs_type;
{
- int error;
+ struct proc *p = curproc; /* XXX */
struct pfsnode *pfs;
+ struct vnode *vp;
struct pfsnode **pp;
+ int error;
loop:
for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) {
+ vp = PFSTOV(pfs);
if (pfs->pfs_pid == pid &&
pfs->pfs_type == pfs_type &&
- PFSTOV(pfs)->v_mount == mp) {
- if (vget(pfs->pfs_vnode, 0))
+ vp->v_mount == mp) {
+ if (vget(vp, 0, p))
goto loop;
- *vpp = pfs->pfs_vnode;
+ *vpp = vp;
return (0);
}
}
@@ -118,17 +121,18 @@ loop:
*/
MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
- error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp);
- if (error) {
+ if (error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) {
FREE(pfs, M_TEMP);
goto out;
}
+ vp = *vpp;
+
+ vp->v_data = pfs;
- (*vpp)->v_data = pfs;
pfs->pfs_next = 0;
pfs->pfs_pid = (pid_t) pid;
pfs->pfs_type = pfs_type;
- pfs->pfs_vnode = *vpp;
+ pfs->pfs_vnode = vp;
pfs->pfs_flags = 0;
pfs->pfs_lockowner = 0;
pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
@@ -138,33 +142,41 @@ loop:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
+ vp->v_type = VDIR;
+ vp->v_flag = VROOT;
+ break;
+
+ case Pcurproc: /* /proc/curproc = lr--r--r-- */
+ pfs->pfs_mode = (VREAD) |
+ (VREAD >> 3) |
+ (VREAD >> 6);
+ vp->v_type = VLNK;
break;
case Pproc:
pfs->pfs_mode = (VREAD|VEXEC) |
(VREAD|VEXEC) >> 3 |
(VREAD|VEXEC) >> 6;
+ vp->v_type = VDIR;
break;
case Pfile:
- pfs->pfs_mode = (VREAD|VWRITE);
- break;
-
case Pmem:
pfs->pfs_mode = (VREAD|VWRITE) |
(VREAD) >> 3;;
break;
case Pregs:
- pfs->pfs_mode = (VREAD|VWRITE);
- break;
-
case Pfpregs:
pfs->pfs_mode = (VREAD|VWRITE);
+ vp->v_type = VREG;
break;
case Pctl:
+ case Pnote:
+ case Pnotepg:
pfs->pfs_mode = (VWRITE);
+ vp->v_type = VREG;
break;
case Ptype:
@@ -173,14 +185,7 @@ loop:
pfs->pfs_mode = (VREAD) |
(VREAD >> 3) |
(VREAD >> 6);
- break;
-
- case Pnote:
- pfs->pfs_mode = (VWRITE);
- break;
-
- case Pnotepg:
- pfs->pfs_mode = (VWRITE);
+ vp->v_type = VREG;
break;
default:
@@ -316,8 +321,7 @@ vfs_getuserstr(uio, buf, buflenp)
return (EMSGSIZE);
xlen = uio->uio_resid;
- error = uiomove(buf, xlen, uio);
- if (error)
+ if (error = uiomove(buf, xlen, uio))
return (error);
/* allow multiple writes without seeks */
@@ -339,6 +343,7 @@ vfs_findname(nm, buf, buflen)
char *buf;
int buflen;
{
+
for (; nm->nm_name; nm++)
if (bcmp(buf, nm->nm_name, buflen+1) == 0)
return (nm);
diff --git a/sys/miscfs/procfs/procfs_vfsops.c b/sys/miscfs/procfs/procfs_vfsops.c
index 433b391..5387126 100644
--- a/sys/miscfs/procfs/procfs_vfsops.c
+++ b/sys/miscfs/procfs/procfs_vfsops.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_vfsops.c 8.4 (Berkeley) 1/21/94
+ * @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95
*
* $FreeBSD$
*/
@@ -56,24 +56,14 @@
#include <miscfs/procfs/procfs.h>
#include <vm/vm.h> /* for PAGE_SIZE */
-static int procfs_fhtovp __P((struct mount *mp, struct fid *fhp,
- struct mbuf *nam, struct vnode **vpp,
- int *exflagsp, struct ucred **credanonp));
-static int procfs_init __P((void));
+static int procfs_init __P((struct vfsconf *vfsp));
static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
-static int procfs_quotactl __P((struct mount *mp, int cmds, uid_t uid,
- caddr_t arg, struct proc *p));
static int procfs_start __P((struct mount *mp, int flags, struct proc *p));
static int procfs_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int procfs_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
static int procfs_unmount __P((struct mount *mp, int mntflags,
struct proc *p));
-static int procfs_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int procfs_vptofh __P((struct vnode *vp, struct fid *fhp));
/*
* VFS Operations.
@@ -101,7 +91,7 @@ procfs_mount(mp, path, data, ndp, p)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = 0;
- getnewfsid(mp, MOUNT_PROCFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -125,12 +115,8 @@ procfs_unmount(mp, mntflags, p)
int error;
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;
- }
error = vflush(mp, 0, flags);
if (error)
@@ -144,24 +130,10 @@ procfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
- struct pfsnode *pfs;
- struct vnode *vp;
- int error;
-
- error = procfs_allocvp(mp, &vp, (pid_t) 0, Proot);
- if (error)
- return (error);
-
- vp->v_type = VDIR;
- vp->v_flag = VROOT;
- pfs = VTOPFS(vp);
- *vpp = vp;
- return (0);
+ return (procfs_allocvp(mp, vpp, 0, Proot));
}
-/*
- */
/* ARGSUSED */
static int
procfs_start(mp, flags, p)
@@ -182,7 +154,6 @@ procfs_statfs(mp, sbp, p)
struct statfs *sbp;
struct proc *p;
{
- sbp->f_type = MOUNT_PROCFS;
sbp->f_bsize = PAGE_SIZE;
sbp->f_iosize = PAGE_SIZE;
sbp->f_blocks = 1; /* avoid divide by zero in some df's */
@@ -192,6 +163,7 @@ procfs_statfs(mp, sbp, p)
sbp->f_ffree = maxproc - nprocs; /* approx */
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -200,68 +172,25 @@ procfs_statfs(mp, sbp, p)
return (0);
}
-
-static int
-procfs_quotactl(mp, cmds, uid, arg, p)
- struct mount *mp;
- int cmds;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
static int
-procfs_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
+procfs_init(vfsp)
+ struct vfsconf *vfsp;
{
return (0);
}
-static int
-procfs_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-static int
-procfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fhp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EINVAL);
-}
-
-static int
-procfs_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return EINVAL;
-}
-
-static int
-procfs_init()
-{
-
- return (0);
-}
+#define procfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))einval)
+#define procfs_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define procfs_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+#define procfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define procfs_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define procfs_vptofh ((int (*) __P((struct vnode *, struct fid *)))einval)
static struct vfsops procfs_vfsops = {
procfs_mount,
diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c
index f497563..85be3ea 100644
--- a/sys/miscfs/procfs/procfs_vnops.c
+++ b/sys/miscfs/procfs/procfs_vnops.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
+ * Copyright (c) 1993, 1995 Jan-Simon Pendry
+ * Copyright (c) 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)procfs_vnops.c 8.6 (Berkeley) 2/7/94
+ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
*
* $FreeBSD$
*/
@@ -55,8 +55,9 @@
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/resourcevar.h>
-#include <miscfs/procfs/procfs.h>
#include <vm/vm.h> /* for PAGE_SIZE */
+#include <machine/reg.h>
+#include <miscfs/procfs/procfs.h>
static int procfs_abortop __P((struct vop_abortop_args *));
static int procfs_access __P((struct vop_access_args *));
@@ -78,29 +79,30 @@ static int procfs_setattr __P((struct vop_setattr_args *));
* process-specific sub-directories. It is
* used in procfs_lookup and procfs_readdir
*/
-static struct pfsnames {
- u_short d_namlen;
- char d_name[PROCFS_NAMELEN];
- pfstype d_pfstype;
- int (*d_valid) __P((struct proc *));
-} procent[] = {
+struct proc_target {
+ u_char pt_type;
+ u_char pt_namlen;
+ char *pt_name;
+ pfstype pt_pfstype;
+ int (*pt_valid) __P((struct proc *p));
+} proc_targets[] = {
#define N(s) sizeof(s)-1, s
- /* namlen, nam, type validp */
- { N("."), Pproc, NULL },
- { N(".."), Proot, NULL },
- { N("file"), Pfile, procfs_validfile },
- { N("mem"), Pmem, NULL },
- { N("regs"), Pregs, procfs_validregs },
- { N("fpregs"), Pfpregs, procfs_validfpregs },
- { N("ctl"), Pctl, NULL },
- { N("status"), Pstatus, NULL },
- { N("note"), Pnote, NULL },
- { N("notepg"), Pnotepg, NULL },
- { N("map"), Pmap, procfs_validmap },
- { N("etype"), Ptype, procfs_validtype },
+ /* name type validp */
+ { DT_DIR, N("."), Pproc, NULL },
+ { DT_DIR, N(".."), Proot, NULL },
+ { DT_REG, N("file"), Pfile, procfs_validfile },
+ { DT_REG, N("mem"), Pmem, NULL },
+ { DT_REG, N("regs"), Pregs, procfs_validregs },
+ { DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
+ { DT_REG, N("ctl"), Pctl, NULL },
+ { DT_REG, N("status"), Pstatus, NULL },
+ { DT_REG, N("note"), Pnote, NULL },
+ { DT_REG, N("notepg"), Pnotepg, NULL },
+ { DT_REG, N("map"), Pmap, procfs_validmap },
+ { DT_REG, N("etype"), Ptype, procfs_validtype },
#undef N
};
-#define Nprocent (sizeof(procent)/sizeof(procent[0]))
+static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
static pid_t atopid __P((const char *, u_int));
@@ -117,7 +119,12 @@ static pid_t atopid __P((const char *, u_int));
*/
static int
procfs_open(ap)
- struct vop_open_args *ap;
+ struct vop_open_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
@@ -126,11 +133,10 @@ procfs_open(ap)
if (PFIND(pfs->pfs_pid) == 0)
return (ENOENT); /* was ESRCH, jsp */
- if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
- ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)))
+ if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) ||
+ (pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))
return (EBUSY);
-
if (ap->a_mode & FWRITE)
pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
@@ -152,7 +158,12 @@ procfs_open(ap)
*/
static int
procfs_close(ap)
- struct vop_close_args *ap;
+ struct vop_close_args /* {
+ struct vnode *a_vp;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
@@ -174,14 +185,51 @@ procfs_close(ap)
*/
static int
procfs_ioctl(ap)
- struct vop_ioctl_args *ap;
+ struct vop_ioctl_args /* {
+ struct vnode *a_vp;
+ int a_command;
+ caddr_t a_data;
+ int a_fflag;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
return (ENOTTY);
}
/*
- * _inactive is called when the pfsnode
+ * do block mapping for pfsnode (vp).
+ * since we don't use the buffer cache
+ * for procfs this function should never
+ * be called. in any case, it's not clear
+ * what part of the kernel ever makes use
+ * of this function. for sanity, this is the
+ * usual no-op bmap, although returning
+ * (EIO) would be a reasonable alternative.
+ */
+int
+procfs_bmap(ap)
+ struct vop_bmap_args /* {
+ struct vnode *a_vp;
+ daddr_t a_bn;
+ struct vnode **a_vpp;
+ daddr_t *a_bnp;
+ int *a_runp;
+ } */ *ap;
+{
+
+ if (ap->a_vpp != NULL)
+ *ap->a_vpp = ap->a_vp;
+ if (ap->a_bnp != NULL)
+ *ap->a_bnp = ap->a_bn;
+ if (ap->a_runp != NULL)
+ *ap->a_runp = 0;
+ return (0);
+}
+
+/*
+ * procfs_inactive is called when the pfsnode
* is vrele'd and the reference count goes
* to zero. (vp) will be on the vnode free
* list, so to get it back vget() must be
@@ -194,16 +242,20 @@ procfs_ioctl(ap)
* chances are that the process will still be
* there and PFIND is not free.
*
- * (vp) is not locked on entry or exit.
+ * (vp) is locked on entry, but must be unlocked on exit.
*/
static int
procfs_inactive(ap)
- struct vop_inactive_args *ap;
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
- struct pfsnode *pfs = VTOPFS(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct pfsnode *pfs = VTOPFS(vp);
+ VOP_UNLOCK(vp, 0, ap->a_p);
if (PFIND(pfs->pfs_pid) == 0)
- vgone(ap->a_vp);
+ vgone(vp);
return (0);
}
@@ -217,12 +269,12 @@ procfs_inactive(ap)
*/
static int
procfs_reclaim(ap)
- struct vop_reclaim_args *ap;
+ struct vop_reclaim_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
- int error;
- error = procfs_freevp(ap->a_vp);
- return (error);
+ return (procfs_freevp(ap->a_vp));
}
/*
@@ -269,13 +321,14 @@ procfs_pathconf(ap)
*/
static int
procfs_print(ap)
- struct vop_print_args *ap;
+ struct vop_print_args /* {
+ struct vnode *a_vp;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
- printf("tag VT_PROCFS, pid %lu, mode %x, flags %lx\n",
- pfs->pfs_pid,
- pfs->pfs_mode, pfs->pfs_flags);
+ printf("tag VT_PROCFS, type %s, pid %d, mode %x, flags %x\n",
+ pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
return (0);
}
@@ -287,7 +340,10 @@ procfs_print(ap)
*/
static int
procfs_abortop(ap)
- struct vop_abortop_args *ap;
+ struct vop_abortop_args /* {
+ struct vnode *a_dvp;
+ struct componentname *a_cnp;
+ } */ *ap;
{
if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
@@ -316,7 +372,12 @@ procfs_badop()
*/
static int
procfs_getattr(ap)
- struct vop_getattr_args *ap;
+ struct vop_getattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct pfsnode *pfs = VTOPFS(ap->a_vp);
struct vattr *vap = ap->a_vap;
@@ -329,6 +390,7 @@ procfs_getattr(ap)
*/
switch (pfs->pfs_type) {
case Proot:
+ case Pcurproc:
procp = 0;
break;
@@ -353,6 +415,21 @@ procfs_getattr(ap)
vap->va_bytes = vap->va_size = 0;
/*
+ * Make all times be current TOD.
+ * It would be possible to get the process start
+ * time from the p_stat structure, but there's
+ * no "file creation" time stamp anyway, and the
+ * p_stat structure is not addressible if u. gets
+ * swapped out for that process.
+ */
+ {
+ struct timeval tv;
+ microtime(&tv);
+ TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
+ }
+ vap->va_atime = vap->va_mtime = vap->va_ctime;
+
+ /*
* If the process has exercised some setuid or setgid
* privilege, then rip away read/write permission so
* that only root can gain access.
@@ -376,21 +453,6 @@ procfs_getattr(ap)
}
/*
- * Make all times be current TOD.
- * It would be possible to get the process start
- * time from the p_stat structure, but there's
- * no "file creation" time stamp anyway, and the
- * p_stat structure is not addressible if u. gets
- * swapped out for that process.
- */
- {
- struct timeval tv;
- microtime(&tv);
- TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
- }
- vap->va_atime = vap->va_mtime = vap->va_ctime;
-
- /*
* now do the object specific fields
*
* The size could be set from struct reg, but it's hardly
@@ -402,17 +464,30 @@ procfs_getattr(ap)
switch (pfs->pfs_type) {
case Proot:
- vap->va_nlink = nprocs + 3;
+ /*
+ * Set nlink to 1 to tell fts(3) we don't actually know.
+ */
+ vap->va_nlink = 1;
+ vap->va_uid = 0;
+ vap->va_gid = 0;
+ vap->va_size = vap->va_bytes = DEV_BSIZE;
+ break;
+
+ case Pcurproc: {
+ char buf[16]; /* should be enough */
+ vap->va_nlink = 1;
vap->va_uid = 0;
vap->va_gid = 0;
- vap->va_bytes = vap->va_size = DEV_BSIZE;
+ vap->va_size = vap->va_bytes =
+ sprintf(buf, "%ld", (long)curproc->p_pid);
break;
+ }
case Pproc:
- vap->va_nlink = Nprocent;
+ vap->va_nlink = nproc_targets;
vap->va_uid = procp->p_ucred->cr_uid;
vap->va_gid = procp->p_ucred->cr_gid;
- vap->va_bytes = vap->va_size = DEV_BSIZE;
+ vap->va_size = vap->va_bytes = DEV_BSIZE;
break;
case Pfile:
@@ -436,7 +511,15 @@ procfs_getattr(ap)
case Ptype:
case Pmap:
case Pregs:
+ vap->va_bytes = vap->va_size = sizeof(struct reg);
+ vap->va_nlink = 1;
+ vap->va_uid = procp->p_ucred->cr_uid;
+ vap->va_gid = procp->p_ucred->cr_gid;
+ break;
+
case Pfpregs:
+ vap->va_bytes = vap->va_size = sizeof(struct fpreg);
+
case Pctl:
case Pstatus:
case Pnote:
@@ -455,7 +538,12 @@ procfs_getattr(ap)
static int
procfs_setattr(ap)
- struct vop_setattr_args *ap;
+ struct vop_setattr_args /* {
+ struct vnode *a_vp;
+ struct vattr *a_vap;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
/*
* just fake out attribute setting
@@ -484,7 +572,12 @@ procfs_setattr(ap)
*/
static int
procfs_access(ap)
- struct vop_access_args *ap;
+ struct vop_access_args /* {
+ struct vnode *a_vp;
+ int a_mode;
+ struct ucred *a_cred;
+ struct proc *a_p;
+ } */ *ap;
{
struct vattr *vap;
struct vattr vattr;
@@ -494,8 +587,9 @@ procfs_access(ap)
* If you're the super-user,
* you always get access.
*/
- if (ap->a_cred->cr_uid == (uid_t) 0)
+ if (ap->a_cred->cr_uid == 0)
return (0);
+
vap = &vattr;
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
if (error)
@@ -510,7 +604,7 @@ procfs_access(ap)
gid_t *gp;
int i;
- (ap->a_mode) >>= 3;
+ ap->a_mode >>= 3;
gp = ap->a_cred->cr_groups;
for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++)
if (vap->va_gid == *gp)
@@ -537,18 +631,23 @@ found:
*/
static int
procfs_lookup(ap)
- struct vop_lookup_args *ap;
+ struct vop_lookup_args /* {
+ struct vnode * a_dvp;
+ struct vnode ** a_vpp;
+ struct componentname * a_cnp;
+ } */ *ap;
{
struct componentname *cnp = ap->a_cnp;
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
+ struct proc *curp = cnp->cn_proc;
int error = 0;
+ struct proc_target *pt;
+ struct vnode *fvp;
pid_t pid;
- struct vnode *nvp;
struct pfsnode *pfs;
- struct proc *procp;
- pfstype pfs_type;
+ struct proc *p;
int i;
*vpp = NULL;
@@ -559,7 +658,7 @@ procfs_lookup(ap)
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
- /*VOP_LOCK(dvp);*/
+ /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
return (0);
}
@@ -570,72 +669,52 @@ procfs_lookup(ap)
return (EIO);
if (CNEQ(cnp, "curproc", 7))
- pid = cnp->cn_proc->p_pid;
- else
- pid = atopid(pname, cnp->cn_namelen);
- if (pid == NO_PID)
- return (ENOENT);
+ return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc));
- procp = PFIND(pid);
- if (procp == 0)
- return (ENOENT);
-
- error = procfs_allocvp(dvp->v_mount, &nvp, pid, Pproc);
- if (error)
- return (error);
+ pid = atopid(pname, cnp->cn_namelen);
+ if (pid == NO_PID)
+ break;
- nvp->v_type = VDIR;
- pfs = VTOPFS(nvp);
+ p = PFIND(pid);
+ if (p == 0)
+ break;
- *vpp = nvp;
- return (0);
+ return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
case Pproc:
- if (cnp->cn_flags & ISDOTDOT) {
- error = procfs_root(dvp->v_mount, vpp);
- return (error);
- }
-
- procp = PFIND(pfs->pfs_pid);
- if (procp == 0)
- return (ENOENT);
+ if (cnp->cn_flags & ISDOTDOT)
+ return (procfs_root(dvp->v_mount, vpp));
- for (i = 0; i < Nprocent; i++) {
- struct pfsnames *dp = &procent[i];
+ p = PFIND(pfs->pfs_pid);
+ if (p == 0)
+ break;
- if (cnp->cn_namelen == dp->d_namlen &&
- bcmp(pname, dp->d_name, dp->d_namlen) == 0 &&
- (dp->d_valid == NULL || (*dp->d_valid)(procp))) {
- pfs_type = dp->d_pfstype;
+ for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
+ if (cnp->cn_namelen == pt->pt_namlen &&
+ bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
+ (pt->pt_valid == NULL || (*pt->pt_valid)(p)))
goto found;
- }
}
- return (ENOENT);
+ break;
found:
- if (pfs_type == Pfile) {
- nvp = procfs_findtextvp(procp);
- if (nvp) {
- VREF(nvp);
- VOP_LOCK(nvp);
- } else {
- error = ENXIO;
- }
- } else {
- error = procfs_allocvp(dvp->v_mount, &nvp,
- pfs->pfs_pid, pfs_type);
- if (error)
- return (error);
-
- nvp->v_type = VREG;
- pfs = VTOPFS(nvp);
+ if (pt->pt_pfstype == Pfile) {
+ fvp = procfs_findtextvp(p);
+ /* We already checked that it exists. */
+ VREF(fvp);
+ vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curp);
+ *vpp = fvp;
+ return (0);
}
- *vpp = nvp;
- return (error);
+
+ return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
+ pt->pt_pfstype));
default:
return (ENOTDIR);
}
+
+ return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
}
/*
@@ -645,6 +724,7 @@ int
procfs_validfile(p)
struct proc *p;
{
+
return (procfs_findtextvp(p) != NULLVP);
}
@@ -662,7 +742,14 @@ procfs_validfile(p)
*/
static int
procfs_readdir(ap)
- struct vop_readdir_args *ap;
+ struct vop_readdir_args /* {
+ struct vnode *a_vp;
+ struct uio *a_uio;
+ struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
+ } */ *ap;
{
struct uio *uio = ap->a_uio;
struct pfsdent d;
@@ -672,6 +759,13 @@ procfs_readdir(ap)
int count;
int i;
+ /*
+ * We don't allow exporting procfs mounts, and currently local
+ * requests do not need cookies.
+ */
+ if (ap->a_ncookies)
+ panic("procfs_readdir: not hungry");
+
pfs = VTOPFS(ap->a_vp);
if (uio->uio_resid < UIO_MX)
@@ -693,39 +787,28 @@ procfs_readdir(ap)
*/
case Pproc: {
struct proc *p;
+ struct proc_target *pt;
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
- while (uio->uio_resid >= UIO_MX) {
- struct pfsnames *dt;
-
- if (i >= Nprocent)
- break;
-
- dt = &procent[i];
-
- /* see if we should show this one. */
- if (dt->d_valid && (*dt->d_valid)(p) == 0) {
- i++;
+ for (pt = &proc_targets[i];
+ uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
+ if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
continue;
- }
dp->d_reclen = UIO_MX;
- dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, dt->d_pfstype);
- dp->d_type = DT_REG;
- dp->d_namlen = dt->d_namlen;
- bcopy(dt->d_name, dp->d_name, sizeof(dt->d_name)-1);
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
+ dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype);
+ dp->d_namlen = pt->pt_namlen;
+ bcopy(pt->pt_name, dp->d_name, pt->pt_namlen + 1);
+ dp->d_type = pt->pt_type;
+
+ if (error = uiomove((caddr_t)dp, UIO_MX, uio))
break;
- count += UIO_MX;
- i++;
}
break;
-
}
/*
@@ -738,63 +821,61 @@ procfs_readdir(ap)
*/
case Proot: {
- int pcnt;
#ifdef PROCFS_ZOMBIE
int doingzomb = 0;
#endif
+ int pcnt = 0;
volatile struct proc *p = allproc.lh_first;
-#define PROCFS_XFILES 3 /* number of other entries, like "curproc" */
- pcnt = PROCFS_XFILES;
-
- while (p && uio->uio_resid >= UIO_MX) {
+ again:
+ for (; p && uio->uio_resid >= UIO_MX; i++, pcnt++) {
bzero((char *) dp, UIO_MX);
- dp->d_type = DT_DIR;
dp->d_reclen = UIO_MX;
switch (i) {
- case 0:
+ case 0: /* `.' */
+ case 1: /* `..' */
dp->d_fileno = PROCFS_FILENO(0, Proot);
- dp->d_namlen = sprintf(dp->d_name, ".");
- break;
-
- case 1:
- dp->d_fileno = PROCFS_FILENO(0, Proot);
- dp->d_namlen = sprintf(dp->d_name, "..");
+ dp->d_namlen = i + 1;
+ bcopy("..", dp->d_name, dp->d_namlen);
+ dp->d_name[i + 1] = '\0';
+ dp->d_type = DT_DIR;
break;
case 2:
- /* ship out entry for "curproc" */
- dp->d_fileno = PROCFS_FILENO(PID_MAX+1, Pproc);
- dp->d_namlen = sprintf(dp->d_name, "curproc");
+ dp->d_fileno = PROCFS_FILENO(0, Pcurproc);
+ dp->d_namlen = 7;
+ bcopy("curproc", dp->d_name, 8);
+ dp->d_type = DT_LNK;
break;
default:
- if (pcnt >= i) {
- dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
- dp->d_namlen = sprintf(dp->d_name, "%ld", (long) p->p_pid);
+ while (pcnt < i) {
+ pcnt++;
+ p = p->p_list.le_next;
+ if (!p)
+ goto done;
}
-
+ dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
+ dp->d_namlen = sprintf(dp->d_name, "%ld",
+ (long)p->p_pid);
+ dp->d_type = DT_REG;
p = p->p_list.le_next;
-
-#ifdef PROCFS_ZOMBIE
- if (p == 0 && doingzomb == 0) {
- doingzomb = 1;
- p = zombproc.lh_first;
- }
-#endif
-
- if (pcnt++ < i)
- continue;
-
break;
}
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
+
+ if (error = uiomove((caddr_t)dp, UIO_MX, uio))
break;
- count += UIO_MX;
- i++;
}
+ done:
+
+#ifdef PROCFS_ZOMBIE
+ if (p == 0 && doingzomb == 0) {
+ doingzomb = 1;
+ p = zombproc.lh_first;
+ goto again;
+ }
+#endif
break;
@@ -811,6 +892,25 @@ procfs_readdir(ap)
}
/*
+ * readlink reads the link of `curproc'
+ */
+int
+procfs_readlink(ap)
+ struct vop_readlink_args *ap;
+{
+ struct uio *uio = ap->a_uio;
+ char buf[16]; /* should be enough */
+ int len;
+
+ if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pcurproc))
+ return (EINVAL);
+
+ len = sprintf(buf, "%ld", (long)curproc->p_pid);
+
+ return (uiomove((caddr_t)buf, len, ap->a_uio));
+}
+
+/*
* convert decimal ascii to pid_t
*/
static pid_t
@@ -838,6 +938,7 @@ atopid(b, len)
#define procfs_write procfs_rw
#define procfs_select ((int (*) __P((struct vop_select_args *))) procfs_badop)
#define procfs_mmap ((int (*) __P((struct vop_mmap_args *))) procfs_badop)
+#define procfs_revoke vop_revoke
#define procfs_fsync ((int (*) __P((struct vop_fsync_args *))) procfs_badop)
#define procfs_seek ((int (*) __P((struct vop_seek_args *))) procfs_badop)
#define procfs_remove ((int (*) __P((struct vop_remove_args *))) procfs_badop)
@@ -849,7 +950,6 @@ atopid(b, len)
#define procfs_readlink ((int (*) __P((struct vop_readlink_args *))) procfs_badop)
#define procfs_lock ((int (*) __P((struct vop_lock_args *))) nullop)
#define procfs_unlock ((int (*) __P((struct vop_unlock_args *))) nullop)
-#define procfs_bmap ((int (*) __P((struct vop_bmap_args *))) procfs_badop)
#define procfs_strategy ((int (*) __P((struct vop_strategy_args *))) procfs_badop)
#define procfs_islocked ((int (*) __P((struct vop_islocked_args *))) nullop)
#define procfs_advlock ((int (*) __P((struct vop_advlock_args *))) procfs_badop)
@@ -859,6 +959,9 @@ atopid(b, len)
#define procfs_truncate ((int (*) __P((struct vop_truncate_args *))) procfs_badop)
#define procfs_update ((int (*) __P((struct vop_update_args *))) nullop)
+/*
+ * procfs vnode operations.
+ */
vop_t **procfs_vnodeop_p;
static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
@@ -875,6 +978,7 @@ static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
{ &vop_ioctl_desc, (vop_t *)procfs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)procfs_select }, /* select */
{ &vop_mmap_desc, (vop_t *)procfs_mmap }, /* mmap */
+ { &vop_revoke_desc, (vop_t *)procfs_revoke }, /* revoke */
{ &vop_fsync_desc, (vop_t *)procfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)procfs_seek }, /* seek */
{ &vop_remove_desc, (vop_t *)procfs_remove }, /* remove */
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index 049f41e..2e8cc04 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)spec_vnops.c 8.6 (Berkeley) 4/9/94
+ * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -79,8 +79,10 @@ static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)spec_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)spec_read }, /* read */
{ &vop_write_desc, (vop_t *)spec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
@@ -148,9 +150,10 @@ spec_open(ap)
struct proc *a_p;
} */ *ap;
{
+ struct proc *p = ap->a_p;
struct vnode *bvp, *vp = ap->a_vp;
dev_t bdev, dev = (dev_t)vp->v_rdev;
- register int maj = major(dev);
+ int maj = major(dev);
int error;
/*
@@ -171,7 +174,9 @@ spec_open(ap)
* When running in very secure mode, do not allow
* opens for writing of any disk character devices.
*/
- if (securelevel >= 2 && isdisk(dev, VCHR))
+ if (securelevel >= 2
+ && cdevsw[maj]->d_bdev
+ && cdevsw[maj]->d_bdev->d_flags == D_DISK)
return (EPERM);
/*
* When running in secure mode, do not allow opens
@@ -189,9 +194,20 @@ spec_open(ap)
return (EPERM);
}
}
- VOP_UNLOCK(vp);
- error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);
- VOP_LOCK(vp);
+#if 0
+ /*
+ * Lite2 stuff. We will almost certainly do this
+ * differently with devfs. The only use of this flag
+ * is in dead_read to make ttys return EOF instead of
+ * EIO when they are dead. Pre-lite2 FreeBSD returns
+ * EOF for all character devices.
+ */
+ if (cdevsw[maj]->d_type == D_TTY)
+ vp->v_flag |= VISTTY;
+#endif
+ VOP_UNLOCK(vp, 0, p);
+ error = (*cdevsw[maj]->d_open)(dev, ap->a_mode, S_IFCHR, p);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -204,7 +220,7 @@ spec_open(ap)
* opens for writing of any disk block devices.
*/
if (securelevel >= 2 && ap->a_cred != FSCRED &&
- (ap->a_mode & FWRITE) && isdisk(dev, VBLK))
+ (ap->a_mode & FWRITE) && bdevsw[maj]->d_flags == D_DISK)
return (EPERM);
/*
* Do not allow opens of block devices that are
@@ -213,9 +229,7 @@ spec_open(ap)
error = vfs_mountedon(vp);
if (error)
return (error);
- return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));
- default:
- break;
+ return ((*bdevsw[maj]->d_open)(dev, ap->a_mode, S_IFBLK, p));
}
return (0);
}
@@ -257,10 +271,10 @@ spec_read(ap)
switch (vp->v_type) {
case VCHR:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = (*cdevsw[major(vp->v_rdev)]->d_read)
(vp->v_rdev, uio, ap->a_ioflag);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -335,10 +349,10 @@ spec_write(ap)
switch (vp->v_type) {
case VCHR:
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
error = (*cdevsw[major(vp->v_rdev)]->d_write)
(vp->v_rdev, uio, ap->a_ioflag);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
case VBLK:
@@ -408,7 +422,7 @@ spec_ioctl(ap)
case VBLK:
if (ap->a_command == 0 && (int)ap->a_data == B_TAPE)
- if (bdevsw[major(dev)]->d_flags & B_TAPE)
+ if (bdevsw[major(dev)]->d_flags == D_TAPE)
return (0);
else
return (1);
@@ -498,6 +512,18 @@ loop:
return (0);
}
+int
+spec_inactive(ap)
+ struct vop_inactive_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
+ return (0);
+}
+
/*
* Just call the device strategy routine
*/
@@ -539,31 +565,6 @@ spec_bmap(ap)
}
/*
- * At the moment we do not do any locking.
- */
-/* ARGSUSED */
-int
-spec_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/* ARGSUSED */
-int
-spec_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (0);
-}
-
-/*
* Device close routine
*/
/* ARGSUSED */
@@ -577,6 +578,7 @@ spec_close(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
dev_t dev = vp->v_rdev;
d_close_t *devclose;
int mode, error;
@@ -631,8 +633,11 @@ spec_close(ap)
(vp->v_flag & VXLOCK) == 0)
return (0);
- if (vp->v_object)
- vnode_pager_uncache(vp);
+ if (vp->v_object) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ vnode_pager_uncache(vp, p);
+ VOP_UNLOCK(vp, 0, p);
+ }
devclose = bdevsw[major(dev)]->d_close;
mode = S_IFBLK;
diff --git a/sys/miscfs/specfs/specdev.h b/sys/miscfs/specfs/specdev.h
index 8960040..091d628 100644
--- a/sys/miscfs/specfs/specdev.h
+++ b/sys/miscfs/specfs/specdev.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)specdev.h 8.2 (Berkeley) 2/2/94
+ * @(#)specdev.h 8.6 (Berkeley) 5/21/95
* $FreeBSD$
*/
@@ -91,8 +91,10 @@ int spec_close __P((struct vop_close_args *));
#define spec_setattr ((int (*) __P((struct vop_setattr_args *)))spec_ebadf)
int spec_read __P((struct vop_read_args *));
int spec_write __P((struct vop_write_args *));
+#define spec_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
int spec_ioctl __P((struct vop_ioctl_args *));
int spec_select __P((struct vop_select_args *));
+#define spec_revoke vop_revoke
#define spec_mmap ((int (*) __P((struct vop_mmap_args *)))spec_badop)
int spec_fsync __P((struct vop_fsync_args *));
#define spec_seek ((int (*) __P((struct vop_seek_args *)))spec_badop)
@@ -105,14 +107,14 @@ int spec_fsync __P((struct vop_fsync_args *));
#define spec_readdir ((int (*) __P((struct vop_readdir_args *)))spec_badop)
#define spec_readlink ((int (*) __P((struct vop_readlink_args *)))spec_badop)
#define spec_abortop ((int (*) __P((struct vop_abortop_args *)))spec_badop)
-#define spec_inactive ((int (*) __P((struct vop_inactive_args *)))nullop)
+int spec_inactive __P((struct vop_inactive_args *));
#define spec_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop)
-int spec_lock __P((struct vop_lock_args *));
-int spec_unlock __P((struct vop_unlock_args *));
+#define spec_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define spec_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
int spec_bmap __P((struct vop_bmap_args *));
int spec_strategy __P((struct vop_strategy_args *));
int spec_print __P((struct vop_print_args *));
-#define spec_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define spec_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
int spec_pathconf __P((struct vop_pathconf_args *));
int spec_advlock __P((struct vop_advlock_args *));
int spec_getpages __P((struct vop_getpages_args *));
diff --git a/sys/miscfs/umapfs/umap.h b/sys/miscfs/umapfs/umap.h
index db1efd4..54ae097 100644
--- a/sys/miscfs/umapfs/umap.h
+++ b/sys/miscfs/umapfs/umap.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap.h 8.3 (Berkeley) 1/21/94
+ * @(#)umap.h 8.4 (Berkeley) 8/20/94
*
* $FreeBSD$
*/
@@ -67,8 +67,7 @@ struct umap_mount {
* A cache of vnode references
*/
struct umap_node {
- struct umap_node *umap_forw; /* Hash chain */
- struct umap_node *umap_back;
+ LIST_ENTRY(umap_node) umap_hash; /* Hash list */
struct vnode *umap_lowervp; /* Aliased vnode - VREFed once */
struct vnode *umap_vnode; /* Back pointer to vnode/umap_node */
};
diff --git a/sys/miscfs/umapfs/umap_subr.c b/sys/miscfs/umapfs/umap_subr.c
index 8333943..3b3629d 100644
--- a/sys/miscfs/umapfs/umap_subr.c
+++ b/sys/miscfs/umapfs/umap_subr.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -33,13 +33,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_subr.c 8.6 (Berkeley) 1/26/94
+ * @(#)umap_subr.c 8.9 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -48,11 +49,8 @@
#include <sys/malloc.h>
#include <miscfs/umapfs/umap.h>
-extern int umapfs_init __P((void));
-
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NUMAPNODECACHE 16
-#define UMAP_NHASH(vp) ((((u_long) vp)>>LOG2_SIZEVNODE) & (NUMAPNODECACHE-1))
/*
* Null layer cache:
@@ -62,52 +60,33 @@ extern int umapfs_init __P((void));
* alias is removed the target vnode is vrele'd.
*/
-/*
- * Cache head
- */
-struct umap_node_cache {
- struct umap_node *ac_forw;
- struct umap_node *ac_back;
-};
-
-static struct umap_node_cache umap_node_cache[NUMAPNODECACHE];
+#define UMAP_NHASH(vp) \
+ (&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash])
+LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
+u_long umap_node_hash;
static u_long umap_findid __P((u_long id, u_long map[][2], int nentries));
static int umap_node_alloc __P((struct mount *mp, struct vnode *lowervp,
struct vnode **vpp));
static struct vnode *
umap_node_find __P((struct mount *mp, struct vnode *targetvp));
-static struct umap_node_cache *
- umap_node_hash __P((struct vnode *targetvp));
/*
* Initialise cache headers
*/
int
-umapfs_init()
+umapfs_init(vfsp)
+ struct vfsconf *vfsp;
{
- struct umap_node_cache *ac;
+
#ifdef UMAPFS_DIAGNOSTIC
printf("umapfs_init\n"); /* printed during system boot */
#endif
-
- for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++)
- ac->ac_forw = ac->ac_back = (struct umap_node *) ac;
+ umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
return (0);
}
/*
- * Compute hash list for given target vnode
- */
-static struct umap_node_cache *
-umap_node_hash(targetvp)
- struct vnode *targetvp;
-{
-
- return (&umap_node_cache[UMAP_NHASH(targetvp)]);
-}
-
-/*
* umap_findid is called by various routines in umap_vnodeops.c to
* find a user or group id in a map.
*/
@@ -163,7 +142,8 @@ umap_node_find(mp, targetvp)
struct mount *mp;
struct vnode *targetvp;
{
- struct umap_node_cache *hd;
+ struct proc *p = curproc; /* XXX */
+ struct umap_node_hashhead *hd;
struct umap_node *a;
struct vnode *vp;
@@ -177,10 +157,9 @@ umap_node_find(mp, targetvp)
* the target vnode. If found, the increment the umap_node
* reference count (but NOT the target vnode's VREF counter).
*/
- hd = umap_node_hash(targetvp);
-
- loop:
- for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) {
+ hd = UMAP_NHASH(targetvp);
+loop:
+ for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) {
if (a->umap_lowervp == targetvp &&
a->umap_vnode->v_mount == mp) {
vp = UMAPTOV(a);
@@ -189,7 +168,7 @@ umap_node_find(mp, targetvp)
* stuff, but we don't want to lock
* the lower node.
*/
- if (vget(vp, 0)) {
+ if (vget(vp, 0, p)) {
#ifdef UMAPFS_DIAGNOSTIC
printf ("umap_node_find: vget failed.\n");
#endif
@@ -217,7 +196,7 @@ umap_node_alloc(mp, lowervp, vpp)
struct vnode *lowervp;
struct vnode **vpp;
{
- struct umap_node_cache *hd;
+ struct umap_node_hashhead *hd;
struct umap_node *xp;
struct vnode *othervp, *vp;
int error;
@@ -257,8 +236,8 @@ umap_node_alloc(mp, lowervp, vpp)
return (0);
}
VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */
- hd = umap_node_hash(lowervp);
- insque(xp, hd);
+ hd = UMAP_NHASH(lowervp);
+ LIST_INSERT_HEAD(hd, xp, umap_hash);
return (0);
}
diff --git a/sys/miscfs/umapfs/umap_vfsops.c b/sys/miscfs/umapfs/umap_vfsops.c
index 517c291..897e2ce 100644
--- a/sys/miscfs/umapfs/umap_vfsops.c
+++ b/sys/miscfs/umapfs/umap_vfsops.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94
+ * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
@@ -46,6 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/vnode.h>
@@ -54,7 +55,7 @@
#include <sys/malloc.h>
#include <miscfs/umapfs/umap.h>
-extern int umapfs_init __P((void));
+extern int umapfs_init __P((struct vfsconf *));
static int umapfs_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -187,7 +188,7 @@ umapfs_mount(mp, path, data, ndp, p)
/*
* Unlock the node (either the lower or the alias)
*/
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
/*
* Make sure the node alias worked
*/
@@ -207,7 +208,7 @@ umapfs_mount(mp, path, data, ndp, p)
if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_data = (qaddr_t) amp;
- getnewfsid(mp, MOUNT_LOFS);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
@@ -253,12 +254,8 @@ umapfs_unmount(mp, mntflags, p)
printf("umapfs_unmount(mp = %x)\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
@@ -300,6 +297,7 @@ umapfs_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp;
#ifdef UMAPFS_DIAGNOSTIC
@@ -314,7 +312,7 @@ umapfs_root(mp, vpp)
*/
vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
VREF(vp);
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
*vpp = vp;
return (0);
}
@@ -429,4 +427,3 @@ static struct vfsops umap_vfsops = {
};
VFS_SET(umap_vfsops, umap, MOUNT_UMAP, VFCF_LOOPBACK);
-
diff --git a/sys/miscfs/umapfs/umap_vnops.c b/sys/miscfs/umapfs/umap_vnops.c
index 7c14cda..17064f4 100644
--- a/sys/miscfs/umapfs/umap_vnops.c
+++ b/sys/miscfs/umapfs/umap_vnops.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)umap_vnops.c 8.3 (Berkeley) 1/5/94
+ * @(#)umap_vnops.c 8.6 (Berkeley) 5/22/95
* $FreeBSD$
*/
@@ -336,10 +336,52 @@ umap_getattr(ap)
return (0);
}
+/*
+ * 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
+umap_lock(ap)
+ struct vop_lock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+
+ vop_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
+umap_unlock(ap)
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ vop_nounlock(ap);
+ ap->a_flags &= ~LK_INTERLOCK;
+ return (null_bypass(ap));
+}
+
static int
umap_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
/*
@@ -349,6 +391,7 @@ umap_inactive(ap)
* cache and reusable.
*
*/
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -364,7 +407,7 @@ umap_reclaim(ap)
/* After this assignment, this node will not be re-used. */
xp->umap_lowervp = NULL;
- remque(xp);
+ LIST_REMOVE(xp, umap_hash);
FREE(vp->v_data, M_TEMP);
vp->v_data = NULL;
vrele(lowervp);
@@ -487,6 +530,8 @@ static struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)umap_bypass },
{ &vop_getattr_desc, (vop_t *)umap_getattr },
+ { &vop_lock_desc, (vop_t *)umap_lock },
+ { &vop_unlock_desc, (vop_t *)umap_unlock },
{ &vop_inactive_desc, (vop_t *)umap_inactive },
{ &vop_reclaim_desc, (vop_t *)umap_reclaim },
{ &vop_print_desc, (vop_t *)umap_print },
diff --git a/sys/miscfs/union/union.h b/sys/miscfs/union/union.h
index 9c740d3..c956921 100644
--- a/sys/miscfs/union/union.h
+++ b/sys/miscfs/union/union.h
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union.h 8.2 (Berkeley) 2/17/94
+ * @(#)union.h 8.9 (Berkeley) 12/10/94
* $FreeBSD$
*/
@@ -75,10 +75,14 @@ struct union_node {
struct vnode *un_uppervp; /* overlaying object */
struct vnode *un_lowervp; /* underlying object */
struct vnode *un_dirvp; /* Parent dir of uppervp */
+ struct vnode *un_pvp; /* Parent vnode */
char *un_path; /* saved component name */
int un_hash; /* saved un_path hash value */
int un_openl; /* # of opens on lowervp */
- int un_flags;
+ unsigned int un_flags;
+ struct vnode **un_dircache; /* cached union stack */
+ off_t un_uppersz; /* size of upper object */
+ off_t un_lowersz; /* size of lower object */
#ifdef DIAGNOSTIC
pid_t un_pid;
#endif
@@ -88,16 +92,23 @@ struct union_node {
#define UN_LOCKED 0x02
#define UN_ULOCK 0x04 /* Upper node is locked */
#define UN_KLOCK 0x08 /* Keep upper node locked on vput */
+#define UN_CACHED 0x10 /* In union cache */
extern int union_allocvp __P((struct vnode **, struct mount *,
struct vnode *, struct vnode *,
struct componentname *, struct vnode *,
- struct vnode *));
+ struct vnode *, int));
extern int union_freevp __P((struct vnode *));
-extern int union_copyfile __P((struct proc *, struct ucred *,
- struct vnode *, struct vnode *));
+extern int union_copyfile __P((struct vnode *, struct vnode *,
+ struct ucred *, struct proc *));
+extern int union_copyup __P((struct union_node *, int, struct ucred *,
+ struct proc *));
+extern int union_dowhiteout __P((struct union_node *, struct ucred *,
+ struct proc *));
extern int union_mkshadow __P((struct union_mount *, struct vnode *,
struct componentname *, struct vnode **));
+extern int union_mkwhiteout __P((struct union_mount *, struct vnode *,
+ struct componentname *, char *));
extern int union_vn_create __P((struct vnode **, struct union_node *,
struct proc *));
extern int union_vn_close __P((struct vnode *, int, struct ucred *,
@@ -108,6 +119,7 @@ extern void union_removed_upper __P((struct union_node *un));
extern struct vnode *union_lowervp __P((struct vnode *));
extern void union_newlower __P((struct union_node *, struct vnode *));
extern void union_newupper __P((struct union_node *, struct vnode *));
+extern void union_newsize __P((struct vnode *, off_t, off_t));
#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
diff --git a/sys/miscfs/union/union_subr.c b/sys/miscfs/union/union_subr.c
index 6549f7d..63e25e6 100644
--- a/sys/miscfs/union/union_subr.c
+++ b/sys/miscfs/union/union_subr.c
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_subr.c 8.4 (Berkeley) 2/17/94
+ * @(#)union_subr.c 8.20 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -48,6 +48,9 @@
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <vm/vm.h> /* for vnode_pager_setsize */
#include <miscfs/union/union.h>
#include <sys/proc.h>
@@ -118,31 +121,38 @@ union_updatevp(un, uppervp, lowervp)
{
int ohash = UNION_HASH(un->un_uppervp, un->un_lowervp);
int nhash = UNION_HASH(uppervp, lowervp);
+ int docache = (lowervp != NULLVP || uppervp != NULLVP);
+ int lhash, hhash, uhash;
- if (ohash != nhash) {
- /*
- * Ensure locking is ordered from lower to higher
- * to avoid deadlocks.
- */
- if (nhash < ohash) {
- int t = ohash;
- ohash = nhash;
- nhash = t;
- }
+ /*
+ * Ensure locking is ordered from lower to higher
+ * to avoid deadlocks.
+ */
+ if (nhash < ohash) {
+ lhash = nhash;
+ uhash = ohash;
+ } else {
+ lhash = ohash;
+ uhash = nhash;
+ }
- while (union_list_lock(ohash))
+ if (lhash != uhash)
+ while (union_list_lock(lhash))
continue;
- while (union_list_lock(nhash))
- continue;
+ while (union_list_lock(uhash))
+ continue;
- LIST_REMOVE(un, un_cache);
- union_list_unlock(ohash);
- } else {
- while (union_list_lock(nhash))
- continue;
+ if (ohash != nhash || !docache) {
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
}
+ if (ohash != nhash)
+ union_list_unlock(ohash);
+
if (un->un_lowervp != lowervp) {
if (un->un_lowervp) {
vrele(un->un_lowervp);
@@ -156,6 +166,7 @@ union_updatevp(un, uppervp, lowervp)
}
}
un->un_lowervp = lowervp;
+ un->un_lowersz = VNOVAL;
}
if (un->un_uppervp != uppervp) {
@@ -163,10 +174,13 @@ union_updatevp(un, uppervp, lowervp)
vrele(un->un_uppervp);
un->un_uppervp = uppervp;
+ un->un_uppersz = VNOVAL;
}
- if (ohash != nhash)
+ if (docache && (ohash != nhash)) {
LIST_INSERT_HEAD(&unhead[nhash], un, un_cache);
+ un->un_flags |= UN_CACHED;
+ }
union_list_unlock(nhash);
}
@@ -190,6 +204,47 @@ union_newupper(un, uppervp)
}
/*
+ * Keep track of size changes in the underlying vnodes.
+ * If the size changes, then callback to the vm layer
+ * giving priority to the upper layer size.
+ */
+void
+union_newsize(vp, uppersz, lowersz)
+ struct vnode *vp;
+ off_t uppersz, lowersz;
+{
+ struct union_node *un;
+ off_t sz;
+
+ /* only interested in regular files */
+ if (vp->v_type != VREG)
+ return;
+
+ un = VTOUNION(vp);
+ sz = VNOVAL;
+
+ if ((uppersz != VNOVAL) && (un->un_uppersz != uppersz)) {
+ un->un_uppersz = uppersz;
+ if (sz == VNOVAL)
+ sz = un->un_uppersz;
+ }
+
+ if ((lowersz != VNOVAL) && (un->un_lowersz != lowersz)) {
+ un->un_lowersz = lowersz;
+ if (sz == VNOVAL)
+ sz = un->un_lowersz;
+ }
+
+ if (sz != VNOVAL) {
+#ifdef UNION_DIAGNOSTIC
+ printf("union: %s size now %ld\n",
+ uppersz != VNOVAL ? "upper" : "lower", (long) sz);
+#endif
+ vnode_pager_setsize(vp, sz);
+ }
+}
+
+/*
* allocate a union_node/vnode pair. the vnode is
* referenced and locked. the new vnode is returned
* via (vpp). (mp) is the mountpoint of the union filesystem,
@@ -221,19 +276,22 @@ union_newupper(un, uppervp)
* the vnode free list.
*/
int
-union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
+union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp, docache)
struct vnode **vpp;
struct mount *mp;
- struct vnode *undvp;
+ struct vnode *undvp; /* parent union vnode */
struct vnode *dvp; /* may be null */
struct componentname *cnp; /* may be null */
struct vnode *uppervp; /* may be null */
struct vnode *lowervp; /* may be null */
+ int docache;
{
int error;
struct union_node *un = 0;
struct vnode *xlowervp = NULLVP;
- int hash = 0;
+ struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
+ int hash;
+ int vflag;
int try;
if (uppervp == NULLVP && lowervp == NULLVP)
@@ -244,8 +302,22 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
lowervp = NULLVP;
}
+ /* detect the root vnode (and aliases) */
+ vflag = 0;
+ if ((uppervp == um->um_uppervp) &&
+ ((lowervp == NULLVP) || lowervp == um->um_lowervp)) {
+ if (lowervp == NULLVP) {
+ lowervp = um->um_lowervp;
+ if (lowervp != NULLVP)
+ VREF(lowervp);
+ }
+ vflag = VROOT;
+ }
+
loop:
- for (try = 0; try < 3; try++) {
+ if (!docache) {
+ un = 0;
+ } else for (try = 0; try < 3; try++) {
switch (try) {
case 0:
if (lowervp == NULLVP)
@@ -276,7 +348,8 @@ loop:
(un->un_uppervp == uppervp ||
un->un_uppervp == NULLVP) &&
(UNIONTOV(un)->v_mount == mp)) {
- if (vget(UNIONTOV(un), 0)) {
+ if (vget(UNIONTOV(un), 0,
+ cnp ? cnp->cn_proc : NULL)) {
union_list_unlock(hash);
goto loop;
}
@@ -359,8 +432,7 @@ loop:
*/
if (lowervp != un->un_lowervp) {
union_newlower(un, lowervp);
- if (cnp && (lowervp != NULLVP) &&
- (lowervp->v_type == VREG)) {
+ if (cnp && (lowervp != NULLVP)) {
un->un_hash = cnp->cn_hash;
un->un_path = malloc(cnp->cn_namelen+1,
M_TEMP, M_WAITOK);
@@ -377,14 +449,16 @@ loop:
return (0);
}
- /*
- * otherwise lock the vp list while we call getnewvnode
- * since that can block.
- */
- hash = UNION_HASH(uppervp, lowervp);
+ if (docache) {
+ /*
+ * otherwise lock the vp list while we call getnewvnode
+ * since that can block.
+ */
+ hash = UNION_HASH(uppervp, lowervp);
- if (union_list_lock(hash))
- goto loop;
+ if (union_list_lock(hash))
+ goto loop;
+ }
error = getnewvnode(VT_UNION, mp, union_vnodeop_p, vpp);
if (error) {
@@ -403,6 +477,7 @@ loop:
MALLOC((*vpp)->v_data, void *, sizeof(struct union_node),
M_TEMP, M_WAITOK);
+ (*vpp)->v_flag |= vflag;
if (uppervp)
(*vpp)->v_type = uppervp->v_type;
else
@@ -410,7 +485,13 @@ loop:
un = VTOUNION(*vpp);
un->un_vnode = *vpp;
un->un_uppervp = uppervp;
+ un->un_uppersz = VNOVAL;
un->un_lowervp = lowervp;
+ un->un_lowersz = VNOVAL;
+ un->un_pvp = undvp;
+ if (undvp != NULLVP)
+ VREF(undvp);
+ un->un_dircache = 0;
un->un_openl = 0;
un->un_flags = UN_LOCKED;
if (un->un_uppervp)
@@ -421,7 +502,7 @@ loop:
else
un->un_pid = -1;
#endif
- if (cnp && (lowervp != NULLVP) && (lowervp->v_type == VREG)) {
+ if (cnp && (lowervp != NULLVP)) {
un->un_hash = cnp->cn_hash;
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
@@ -434,13 +515,17 @@ loop:
un->un_dirvp = 0;
}
- LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
+ if (docache) {
+ LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
+ un->un_flags |= UN_CACHED;
+ }
if (xlowervp)
vrele(xlowervp);
out:
- union_list_unlock(hash);
+ if (docache)
+ union_list_unlock(hash);
return (error);
}
@@ -451,13 +536,18 @@ union_freevp(vp)
{
struct union_node *un = VTOUNION(vp);
- LIST_REMOVE(un, un_cache);
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
- if (un->un_uppervp)
+ if (un->un_pvp != NULLVP)
+ vrele(un->un_pvp);
+ if (un->un_uppervp != NULLVP)
vrele(un->un_uppervp);
- if (un->un_lowervp)
+ if (un->un_lowervp != NULLVP)
vrele(un->un_lowervp);
- if (un->un_dirvp)
+ if (un->un_dirvp != NULLVP)
vrele(un->un_dirvp);
if (un->un_path)
free(un->un_path, M_TEMP);
@@ -474,11 +564,11 @@ union_freevp(vp)
* and (tvp) are locked on entry and exit.
*/
int
-union_copyfile(p, cred, fvp, tvp)
- struct proc *p;
- struct ucred *cred;
+union_copyfile(fvp, tvp, cred, p)
struct vnode *fvp;
struct vnode *tvp;
+ struct ucred *cred;
+ struct proc *p;
{
char *buf;
struct uio uio;
@@ -497,12 +587,12 @@ union_copyfile(p, cred, fvp, tvp)
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_offset = 0;
- VOP_UNLOCK(fvp); /* XXX */
- LEASE_CHECK(fvp, p, cred, LEASE_READ);
- VOP_LOCK(fvp); /* XXX */
- VOP_UNLOCK(tvp); /* XXX */
- LEASE_CHECK(tvp, p, cred, LEASE_WRITE);
- VOP_LOCK(tvp); /* XXX */
+ VOP_UNLOCK(fvp, 0, p); /* XXX */
+ VOP_LEASE(fvp, p, cred, LEASE_READ);
+ vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
+ VOP_UNLOCK(tvp, 0, p); /* XXX */
+ VOP_LEASE(tvp, p, cred, LEASE_WRITE);
+ vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */
buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
@@ -542,6 +632,123 @@ union_copyfile(p, cred, fvp, tvp)
}
/*
+ * (un) is assumed to be locked on entry and remains
+ * locked on exit.
+ */
+int
+union_copyup(un, docopy, cred, p)
+ struct union_node *un;
+ int docopy;
+ struct ucred *cred;
+ struct proc *p;
+{
+ int error;
+ struct vnode *lvp, *uvp;
+
+ error = union_vn_create(&uvp, un, p);
+ if (error)
+ return (error);
+
+ /* at this point, uppervp is locked */
+ union_newupper(un, uvp);
+ un->un_flags |= UN_ULOCK;
+
+ lvp = un->un_lowervp;
+
+ if (docopy) {
+ /*
+ * XX - should not ignore errors
+ * from VOP_CLOSE
+ */
+ vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = VOP_OPEN(lvp, FREAD, cred, p);
+ if (error == 0) {
+ error = union_copyfile(lvp, uvp, cred, p);
+ VOP_UNLOCK(lvp, 0, p);
+ (void) VOP_CLOSE(lvp, FREAD, cred, p);
+ }
+#ifdef UNION_DIAGNOSTIC
+ if (error == 0)
+ uprintf("union: copied up %s\n", un->un_path);
+#endif
+
+ }
+ un->un_flags &= ~UN_ULOCK;
+ VOP_UNLOCK(uvp, 0, p);
+ union_vn_close(uvp, FWRITE, cred, p);
+ vn_lock(uvp, LK_EXCLUSIVE | LK_RETRY, p);
+ un->un_flags |= UN_ULOCK;
+
+ /*
+ * Subsequent IOs will go to the top layer, so
+ * call close on the lower vnode and open on the
+ * upper vnode to ensure that the filesystem keeps
+ * its references counts right. This doesn't do
+ * the right thing with (cred) and (FREAD) though.
+ * Ignoring error returns is not right, either.
+ */
+ if (error == 0) {
+ int i;
+
+ for (i = 0; i < un->un_openl; i++) {
+ (void) VOP_CLOSE(lvp, FREAD, cred, p);
+ (void) VOP_OPEN(uvp, FREAD, cred, p);
+ }
+ un->un_openl = 0;
+ }
+
+ return (error);
+
+}
+
+static int
+union_relookup(um, dvp, vpp, cnp, cn, path, pathlen)
+ struct union_mount *um;
+ struct vnode *dvp;
+ struct vnode **vpp;
+ struct componentname *cnp;
+ struct componentname *cn;
+ char *path;
+ int pathlen;
+{
+ int error;
+
+ /*
+ * A new componentname structure must be faked up because
+ * there is no way to know where the upper level cnp came
+ * from or what it is being used for. This must duplicate
+ * some of the work done by NDINIT, some of the work done
+ * by namei, some of the work done by lookup and some of
+ * the work done by VOP_LOOKUP when given a CREATE flag.
+ * Conclusion: Horrible.
+ *
+ * The pathname buffer will be FREEed by VOP_MKDIR.
+ */
+ cn->cn_namelen = pathlen;
+ cn->cn_pnbuf = malloc(cn->cn_namelen+1, M_NAMEI, M_WAITOK);
+ bcopy(path, cn->cn_pnbuf, cn->cn_namelen);
+ cn->cn_pnbuf[cn->cn_namelen] = '\0';
+
+ cn->cn_nameiop = CREATE;
+ cn->cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
+ cn->cn_proc = cnp->cn_proc;
+ if (um->um_op == UNMNT_ABOVE)
+ cn->cn_cred = cnp->cn_cred;
+ else
+ cn->cn_cred = um->um_cred;
+ cn->cn_nameptr = cn->cn_pnbuf;
+ cn->cn_hash = cnp->cn_hash;
+ cn->cn_consume = cnp->cn_consume;
+
+ VREF(dvp);
+ error = relookup(dvp, vpp, cn);
+ if (!error)
+ vrele(dvp);
+
+ return (error);
+}
+
+/*
* Create a shadow directory in the upper layer.
* The new vnode is returned locked.
*
@@ -565,6 +772,19 @@ union_mkshadow(um, dvp, cnp, vpp)
struct proc *p = cnp->cn_proc;
struct componentname cn;
+ error = union_relookup(um, dvp, vpp, cnp, &cn,
+ cnp->cn_nameptr, cnp->cn_namelen);
+ if (error)
+ return (error);
+
+ if (*vpp) {
+ VOP_ABORTOP(dvp, &cn);
+ VOP_UNLOCK(dvp, 0, p);
+ vrele(*vpp);
+ *vpp = NULLVP;
+ return (EEXIST);
+ }
+
/*
* policy: when creating the shadow directory in the
* upper layer, create it owned by the user who did
@@ -573,55 +793,62 @@ union_mkshadow(um, dvp, cnp, vpp)
* mkdir syscall). (jsp, kb)
*/
- /*
- * A new componentname structure must be faked up because
- * there is no way to know where the upper level cnp came
- * from or what it is being used for. This must duplicate
- * some of the work done by NDINIT, some of the work done
- * by namei, some of the work done by lookup and some of
- * the work done by VOP_LOOKUP when given a CREATE flag.
- * Conclusion: Horrible.
- *
- * The pathname buffer will be FREEed by VOP_MKDIR.
- */
- cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
- bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen);
- cn.cn_pnbuf[cnp->cn_namelen] = '\0';
+ VATTR_NULL(&va);
+ va.va_type = VDIR;
+ va.va_mode = um->um_cmode;
- cn.cn_nameiop = CREATE;
- cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|SAVESTART|ISLASTCN);
- cn.cn_proc = cnp->cn_proc;
- if (um->um_op == UNMNT_ABOVE)
- cn.cn_cred = cnp->cn_cred;
- else
- cn.cn_cred = um->um_cred;
- cn.cn_nameptr = cn.cn_pnbuf;
- cn.cn_namelen = cnp->cn_namelen;
- cn.cn_hash = cnp->cn_hash;
- cn.cn_consume = cnp->cn_consume;
+ /* VOP_LEASE: dvp is locked */
+ VOP_LEASE(dvp, p, cn.cn_cred, LEASE_WRITE);
- VREF(dvp);
- error = relookup(dvp, vpp, &cn);
- if (error)
+ error = VOP_MKDIR(dvp, vpp, &cn, &va);
+ return (error);
+}
+
+/*
+ * Create a whiteout entry in the upper layer.
+ *
+ * (um) points to the union mount structure for access to the
+ * the mounting process's credentials.
+ * (dvp) is the directory in which to create the whiteout.
+ * it is locked on entry and exit.
+ * (cnp) is the componentname to be created.
+ */
+int
+union_mkwhiteout(um, dvp, cnp, path)
+ struct union_mount *um;
+ struct vnode *dvp;
+ struct componentname *cnp;
+ char *path;
+{
+ int error;
+ struct vattr va;
+ struct proc *p = cnp->cn_proc;
+ struct vnode *wvp;
+ struct componentname cn;
+
+ VOP_UNLOCK(dvp, 0, p);
+ error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
+ if (error) {
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
- vrele(dvp);
+ }
- if (*vpp) {
+ if (wvp) {
VOP_ABORTOP(dvp, &cn);
- VOP_UNLOCK(dvp);
- vrele(*vpp);
- *vpp = NULLVP;
+ vrele(dvp);
+ vrele(wvp);
return (EEXIST);
}
- VATTR_NULL(&va);
- va.va_type = VDIR;
- va.va_mode = um->um_cmode;
+ /* VOP_LEASE: dvp is locked */
+ VOP_LEASE(dvp, p, p->p_ucred, LEASE_WRITE);
+
+ error = VOP_WHITEOUT(dvp, &cn, CREATE);
+ if (error)
+ VOP_ABORTOP(dvp, &cn);
- /* LEASE_CHECK: dvp is locked */
- LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
+ vrele(dvp);
- error = VOP_MKDIR(dvp, vpp, &cn, &va);
return (error);
}
@@ -699,9 +926,8 @@ union_vn_create(vpp, un, p)
VATTR_NULL(vap);
vap->va_type = VREG;
vap->va_mode = cmode;
- LEASE_CHECK(un->un_dirvp, p, cred, LEASE_WRITE);
- error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
- if (error)
+ VOP_LEASE(un->un_dirvp, p, cred, LEASE_WRITE);
+ if (error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap))
return (error);
error = VOP_OPEN(vp, fmode, cred, p);
@@ -722,6 +948,7 @@ union_vn_close(vp, fmode, cred, p)
struct ucred *cred;
struct proc *p;
{
+
if (fmode & FWRITE)
--vp->v_writecount;
return (VOP_CLOSE(vp, fmode, cred, p));
@@ -731,24 +958,137 @@ void
union_removed_upper(un)
struct union_node *un;
{
+ struct proc *p = curproc; /* XXX */
+
+ union_newupper(un, NULLVP);
+ if (un->un_flags & UN_CACHED) {
+ un->un_flags &= ~UN_CACHED;
+ LIST_REMOVE(un, un_cache);
+ }
+
if (un->un_flags & UN_ULOCK) {
un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp);
+ VOP_UNLOCK(un->un_uppervp, 0, p);
}
-
- union_newupper(un, NULLVP);
}
+#if 0
struct vnode *
union_lowervp(vp)
struct vnode *vp;
{
struct union_node *un = VTOUNION(vp);
- if (un->un_lowervp && (vp->v_type == un->un_lowervp->v_type)) {
- if (vget(un->un_lowervp, 0))
- return (NULLVP);
+ if ((un->un_lowervp != NULLVP) &&
+ (vp->v_type == un->un_lowervp->v_type)) {
+ if (vget(un->un_lowervp, 0) == 0)
+ return (un->un_lowervp);
}
- return (un->un_lowervp);
+ return (NULLVP);
+}
+#endif
+
+/*
+ * determine whether a whiteout is needed
+ * during a remove/rmdir operation.
+ */
+int
+union_dowhiteout(un, cred, p)
+ struct union_node *un;
+ struct ucred *cred;
+ struct proc *p;
+{
+ struct vattr va;
+
+ if (un->un_lowervp != NULLVP)
+ return (1);
+
+ if (VOP_GETATTR(un->un_uppervp, &va, cred, p) == 0 &&
+ (va.va_flags & OPAQUE))
+ return (1);
+
+ return (0);
+}
+
+static void
+union_dircache_r(vp, vppp, cntp)
+ struct vnode *vp;
+ struct vnode ***vppp;
+ int *cntp;
+{
+ struct union_node *un;
+
+ if (vp->v_op != union_vnodeop_p) {
+ if (vppp) {
+ VREF(vp);
+ *(*vppp)++ = vp;
+ if (--(*cntp) == 0)
+ panic("union: dircache table too small");
+ } else {
+ (*cntp)++;
+ }
+
+ return;
+ }
+
+ un = VTOUNION(vp);
+ if (un->un_uppervp != NULLVP)
+ union_dircache_r(un->un_uppervp, vppp, cntp);
+ if (un->un_lowervp != NULLVP)
+ union_dircache_r(un->un_lowervp, vppp, cntp);
+}
+
+struct vnode *
+union_dircache(vp, p)
+ struct vnode *vp;
+ struct proc *p;
+{
+ int cnt;
+ struct vnode *nvp;
+ struct vnode **vpp;
+ struct vnode **dircache;
+ struct union_node *un;
+ int error;
+
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ dircache = VTOUNION(vp)->un_dircache;
+
+ nvp = NULLVP;
+
+ if (dircache == 0) {
+ cnt = 0;
+ union_dircache_r(vp, 0, &cnt);
+ cnt++;
+ dircache = (struct vnode **)
+ malloc(cnt * sizeof(struct vnode *),
+ M_TEMP, M_WAITOK);
+ vpp = dircache;
+ union_dircache_r(vp, &vpp, &cnt);
+ *vpp = NULLVP;
+ vpp = dircache + 1;
+ } else {
+ vpp = dircache;
+ do {
+ if (*vpp++ == VTOUNION(vp)->un_uppervp)
+ break;
+ } while (*vpp != NULLVP);
+ }
+
+ if (*vpp == NULLVP)
+ goto out;
+
+ vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, p);
+ VREF(*vpp);
+ error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, 0, *vpp, NULLVP, 0);
+ if (error)
+ goto out;
+
+ VTOUNION(vp)->un_dircache = 0;
+ un = VTOUNION(nvp);
+ un->un_dircache = dircache;
+
+out:
+ VOP_UNLOCK(vp, 0, p);
+ return (nvp);
}
diff --git a/sys/miscfs/union/union_vfsops.c b/sys/miscfs/union/union_vfsops.c
index a1a6a0d..0295961 100644
--- a/sys/miscfs/union/union_vfsops.c
+++ b/sys/miscfs/union/union_vfsops.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994 Jan-Simon Pendry.
+ * Copyright (c) 1994, 1995 The Regents of the University of California.
+ * Copyright (c) 1994, 1995 Jan-Simon Pendry.
* All rights reserved.
*
* This code is derived from software donated to Berkeley by
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_vfsops.c 8.7 (Berkeley) 3/5/94
+ * @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -56,7 +56,7 @@
#include <sys/queue.h>
#include <miscfs/union/union.h>
-extern int union_init __P((void));
+extern int union_init __P((struct vfsconf *));
extern int union_fhtovp __P((struct mount *mp, struct fid *fidp,
struct mbuf *nam, struct vnode **vpp,
@@ -92,7 +92,7 @@ union_mount(mp, path, data, ndp, p)
struct union_args args;
struct vnode *lowerrootvp = NULLVP;
struct vnode *upperrootvp = NULLVP;
- struct union_mount *um;
+ struct union_mount *um = 0;
struct ucred *cred = 0;
struct ucred *scred;
struct vattr va;
@@ -118,34 +118,6 @@ union_mount(mp, path, data, ndp, p)
}
/*
- * Take a copy of the process's credentials. This isn't
- * quite right since the euid will always be zero and we
- * want to get the "real" users credentials. So fix up
- * the uid field after taking the copy.
- */
- cred = crdup(p->p_ucred);
- cred->cr_uid = p->p_cred->p_ruid;
-
- /*
- * Ensure the *real* user has write permission on the
- * mounted-on directory. This allows the mount_union
- * command to be made setuid root so allowing anyone
- * to do union mounts onto any directory on which they
- * have write permission and which they also own.
- */
- error = VOP_GETATTR(mp->mnt_vnodecovered, &va, cred, p);
- if (error)
- goto bad;
- if ((va.va_uid != cred->cr_uid) &&
- (cred->cr_uid != 0)) {
- error = EACCES;
- goto bad;
- }
- error = VOP_ACCESS(mp->mnt_vnodecovered, VWRITE, cred, p);
- if (error)
- goto bad;
-
- /*
* Get argument
*/
error = copyin(data, (caddr_t)&args, sizeof(struct union_args));
@@ -156,18 +128,10 @@ union_mount(mp, path, data, ndp, p)
VREF(lowerrootvp);
/*
- * Find upper node. Use the real process credentials,
- * not the effective ones since this will have come
- * through a setuid process (mount_union). All this
- * messing around with permissions is entirely bogus
- * and should be removed by allowing any user straight
- * past the mount system call.
+ * Find upper node.
*/
- scred = p->p_ucred;
- p->p_ucred = cred;
NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT,
UIO_USERSPACE, args.target, p);
- p->p_ucred = scred;
error = namei(ndp);
if (error)
@@ -218,7 +182,18 @@ union_mount(mp, path, data, ndp, p)
goto bad;
}
- um->um_cred = cred;
+ /*
+ * Unless the mount is readonly, ensure that the top layer
+ * supports whiteout operations
+ */
+ if ((mp->mnt_flag & MNT_RDONLY) == 0) {
+ error = VOP_WHITEOUT(um->um_uppervp, (struct componentname *) 0, LOOKUP);
+ if (error)
+ goto bad;
+ }
+
+ um->um_cred = p->p_ucred;
+ crhold(um->um_cred);
um->um_cmode = UN_DIRMODE &~ p->p_fd->fd_cmask;
/*
@@ -246,24 +221,18 @@ union_mount(mp, path, data, ndp, p)
*/
mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
- /*
- * This is a user mount. Privilege check for unmount
- * will be done in union_unmount.
- */
- mp->mnt_flag |= MNT_USER;
-
mp->mnt_data = (qaddr_t) um;
- getnewfsid(mp, MOUNT_UNION);
+ vfs_getnewfsid(mp);
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
switch (um->um_op) {
case UNMNT_ABOVE:
- cp = "<above>";
+ cp = "<above>:";
break;
case UNMNT_BELOW:
- cp = "<below>";
+ cp = "<below>:";
break;
case UNMNT_REPLACE:
cp = "";
@@ -287,6 +256,8 @@ union_mount(mp, path, data, ndp, p)
return (0);
bad:
+ if (um)
+ free(um, M_UFSMNT);
if (cred)
crfree(cred);
if (upperrootvp)
@@ -323,40 +294,55 @@ union_unmount(mp, mntflags, p)
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
struct vnode *um_rootvp;
int error;
+ int freeing;
int flags = 0;
#ifdef UNION_DIAGNOSTIC
printf("union_unmount(mp = %x)\n", mp);
#endif
- /* only the mounter, or superuser can unmount */
- if ((p->p_cred->p_ruid != um->um_cred->cr_uid) &&
- (error = suser(p->p_ucred, &p->p_acflag)))
+ if (mntflags & MNT_FORCE)
+ flags |= FORCECLOSE;
+
+ if (error = union_root(mp, &um_rootvp))
return (error);
- if (mntflags & MNT_FORCE) {
- /* union can never be rootfs so don't check for it */
- if (!doforce)
- return (EINVAL);
- flags |= FORCECLOSE;
+ /*
+ * Keep flushing vnodes from the mount list.
+ * This is needed because of the un_pvp held
+ * reference to the parent vnode.
+ * If more vnodes have been freed on a given pass,
+ * the try again. The loop will iterate at most
+ * (d) times, where (d) is the maximum tree depth
+ * in the filesystem.
+ */
+ for (freeing = 0; vflush(mp, um_rootvp, flags) != 0;) {
+ struct vnode *vp;
+ int n;
+
+ /* count #vnodes held on mount list */
+ for (n = 0, vp = mp->mnt_vnodelist.lh_first;
+ vp != NULLVP;
+ vp = vp->v_mntvnodes.le_next)
+ n++;
+
+ /* if this is unchanged then stop */
+ if (n == freeing)
+ break;
+
+ /* otherwise try once more time */
+ freeing = n;
}
- error = union_root(mp, &um_rootvp);
- if (error)
- return (error);
+ /* At this point the root vnode should have a single reference */
if (um_rootvp->v_usecount > 1) {
vput(um_rootvp);
return (EBUSY);
}
- error = vflush(mp, um_rootvp, flags);
- if (error) {
- vput(um_rootvp);
- return (error);
- }
#ifdef UNION_DIAGNOSTIC
- vprint("alias root of lower", um_rootvp);
-#endif
+ vprint("union root", um_rootvp);
+#endif
/*
* Discard references to upper and lower target vnodes.
*/
@@ -385,16 +371,11 @@ union_root(mp, vpp)
struct mount *mp;
struct vnode **vpp;
{
+ struct proc *p = curproc; /* XXX */
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
int error;
int loselock;
-#ifdef UNION_DIAGNOSTIC
- printf("union_root(mp = %x, lvp = %x, uvp = %x)\n", mp,
- um->um_lowervp,
- um->um_uppervp);
-#endif
-
/*
* Return locked reference to root.
*/
@@ -403,7 +384,7 @@ union_root(mp, vpp)
VOP_ISLOCKED(um->um_uppervp)) {
loselock = 1;
} else {
- VOP_LOCK(um->um_uppervp);
+ vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
loselock = 0;
}
if (um->um_lowervp)
@@ -413,16 +394,17 @@ union_root(mp, vpp)
(struct vnode *) 0,
(struct componentname *) 0,
um->um_uppervp,
- um->um_lowervp);
+ um->um_lowervp,
+ 1);
if (error) {
- if (!loselock)
- VOP_UNLOCK(um->um_uppervp);
- vrele(um->um_uppervp);
+ if (loselock)
+ vrele(um->um_uppervp);
+ else
+ vput(um->um_uppervp);
if (um->um_lowervp)
vrele(um->um_lowervp);
} else {
- (*vpp)->v_flag |= VROOT;
if (loselock)
VTOUNION(*vpp)->un_flags &= ~UN_ULOCK;
}
@@ -431,18 +413,6 @@ union_root(mp, vpp)
}
int
-union_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
union_statfs(mp, sbp, p)
struct mount *mp;
struct statfs *sbp;
@@ -485,7 +455,6 @@ union_statfs(mp, sbp, p)
if (error)
return (error);
- sbp->f_type = MOUNT_UNION;
sbp->f_flags = mstat.f_flags;
sbp->f_bsize = mstat.f_bsize;
sbp->f_iosize = mstat.f_iosize;
@@ -496,18 +465,23 @@ union_statfs(mp, sbp, p)
* kind of sense. none of this makes sense though.
*/
- if (mstat.f_bsize != lbsize) {
+ if (mstat.f_bsize != lbsize)
sbp->f_blocks = sbp->f_blocks * lbsize / mstat.f_bsize;
- sbp->f_bfree = sbp->f_bfree * lbsize / mstat.f_bsize;
- sbp->f_bavail = sbp->f_bavail * lbsize / mstat.f_bsize;
- }
+
+ /*
+ * The "total" fields count total resources in all layers,
+ * the "free" fields count only those resources which are
+ * free in the upper layer (since only the upper layer
+ * is writeable).
+ */
sbp->f_blocks += mstat.f_blocks;
- sbp->f_bfree += mstat.f_bfree;
- sbp->f_bavail += mstat.f_bavail;
+ sbp->f_bfree = mstat.f_bfree;
+ sbp->f_bavail = mstat.f_bavail;
sbp->f_files += mstat.f_files;
- sbp->f_ffree += mstat.f_ffree;
+ sbp->f_ffree = mstat.f_ffree;
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
@@ -515,51 +489,21 @@ union_statfs(mp, sbp, p)
return (0);
}
-int
-union_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
-
- /*
- * XXX - Assumes no data cached at union layer.
- */
- return (0);
-}
-
-int
-union_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
-union_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
- struct mount *mp;
- struct fid *fidp;
- struct mbuf *nam;
- struct vnode **vpp;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (EOPNOTSUPP);
-}
-
-int
-union_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
-
- return (EOPNOTSUPP);
-}
+/*
+ * XXX - Assumes no data cached at union layer.
+ */
+#define union_sync ((int (*) __P((struct mount *, int, struct ucred *, \
+ struct proc *)))nullop)
+
+#define union_fhtovp ((int (*) __P((struct mount *, struct fid *, \
+ struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
+#define union_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
+ struct proc *)))eopnotsupp)
+#define union_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
+ size_t, struct proc *)))eopnotsupp)
+#define union_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
+ eopnotsupp)
+#define union_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
struct vfsops union_vfsops = {
union_mount,
diff --git a/sys/miscfs/union/union_vnops.c b/sys/miscfs/union/union_vnops.c
index 5940243..4a66dc0 100644
--- a/sys/miscfs/union/union_vnops.c
+++ b/sys/miscfs/union/union_vnops.c
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 1992, 1993, 1994 The Regents of the University of California.
- * Copyright (c) 1992, 1993, 1994 Jan-Simon Pendry.
- * All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
+ * Copyright (c) 1992, 1993, 1994, 1995
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry.
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)union_vnops.c 8.6 (Berkeley) 2/17/94
+ * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
* $FreeBSD$
*/
@@ -43,7 +43,7 @@
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/time.h>
-#include <sys/kernel.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@@ -51,16 +51,12 @@
#include <sys/malloc.h>
#include <sys/buf.h>
#include <sys/queue.h>
+#include <sys/lock.h>
#include <miscfs/union/union.h>
-/* FIXUP throws the lock on the uppervp vnode if the union_node is already
- * locked and the uppervp vnode is not. Before, this was thrown regardless
- * of the state of the union_node which resulted in locked vnodes which
- * were never unlocked (since the union would never be unlocked).
- */
-#define FIXUP(un) { \
- if (((un)->un_flags & (UN_LOCKED|UN_ULOCK)) == UN_LOCKED) { \
- union_fixup(un); \
+#define FIXUP(un, p) { \
+ if (((un)->un_flags & UN_ULOCK) == 0) { \
+ union_fixup(un, p); \
} \
}
@@ -70,7 +66,7 @@ extern int union_advlock __P((struct vop_advlock_args *ap));
extern int union_bmap __P((struct vop_bmap_args *ap));
extern int union_close __P((struct vop_close_args *ap));
extern int union_create __P((struct vop_create_args *ap));
-static void union_fixup __P((struct union_node *un));
+static void union_fixup __P((struct union_node *un, struct proc *p));
extern int union_fsync __P((struct vop_fsync_args *ap));
extern int union_getattr __P((struct vop_getattr_args *ap));
extern int union_inactive __P((struct vop_inactive_args *ap));
@@ -79,7 +75,7 @@ extern int union_islocked __P((struct vop_islocked_args *ap));
extern int union_link __P((struct vop_link_args *ap));
extern int union_lock __P((struct vop_lock_args *ap));
extern int union_lookup __P((struct vop_lookup_args *ap));
-static int union_lookup1 __P((struct vnode *udvp, struct vnode *dvp,
+static int union_lookup1 __P((struct vnode *udvp, struct vnode **dvpp,
struct vnode **vpp,
struct componentname *cnp));
extern int union_mkdir __P((struct vop_mkdir_args *ap));
@@ -100,29 +96,34 @@ extern int union_select __P((struct vop_select_args *ap));
extern int union_setattr __P((struct vop_setattr_args *ap));
extern int union_strategy __P((struct vop_strategy_args *ap));
extern int union_symlink __P((struct vop_symlink_args *ap));
-extern int union_unlock __P((struct vop_lock_args *ap));
+extern int union_unlock __P((struct vop_unlock_args *ap));
extern int union_write __P((struct vop_read_args *ap));
static void
-union_fixup(un)
+union_fixup(un, p)
struct union_node *un;
+ struct proc *p;
{
- VOP_LOCK(un->un_uppervp);
+ vn_lock(un->un_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
un->un_flags |= UN_ULOCK;
}
static int
-union_lookup1(udvp, dvp, vpp, cnp)
+union_lookup1(udvp, dvpp, vpp, cnp)
struct vnode *udvp;
- struct vnode *dvp;
+ struct vnode **dvpp;
struct vnode **vpp;
struct componentname *cnp;
{
int error;
+ struct proc *p = cnp->cn_proc;
struct vnode *tdvp;
+ struct vnode *dvp;
struct mount *mp;
+ dvp = *dvpp;
+
/*
* If stepping up the directory tree, check for going
* back across the mount point, in which case do what
@@ -130,21 +131,18 @@ union_lookup1(udvp, dvp, vpp, cnp)
* hierarchy.
*/
if (cnp->cn_flags & ISDOTDOT) {
- for (;;) {
+ while ((dvp != udvp) && (dvp->v_flag & VROOT)) {
/*
* Don't do the NOCROSSMOUNT check
* at this level. By definition,
* union fs deals with namespaces, not
* filesystems.
*/
- if ((dvp->v_flag & VROOT) == 0)
- break;
-
tdvp = dvp;
- dvp = dvp->v_mount->mnt_vnodecovered;
+ *dvpp = dvp = dvp->v_mount->mnt_vnodecovered;
vput(tdvp);
VREF(dvp);
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
}
}
@@ -158,7 +156,7 @@ union_lookup1(udvp, dvp, vpp, cnp)
* here to allow it to be unlocked again (phew) in union_lookup.
*/
if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN))
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
dvp = tdvp;
@@ -170,13 +168,11 @@ union_lookup1(udvp, dvp, vpp, cnp)
while (dvp != udvp && (dvp->v_type == VDIR) &&
(mp = dvp->v_mountedhere)) {
- if (mp->mnt_flag & MNT_MLOCK) {
- mp->mnt_flag |= MNT_MWAIT;
- (void) tsleep((caddr_t) mp, PVFS, "unlkup", 0);
+ if (vfs_busy(mp, 0, 0, p))
continue;
- }
error = VFS_ROOT(mp, &tdvp);
+ vfs_unbusy(mp, p);
if (error) {
vput(dvp);
return (error);
@@ -206,9 +202,28 @@ union_lookup(ap)
struct vnode *dvp = ap->a_dvp;
struct union_node *dun = VTOUNION(dvp);
struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
int lockparent = cnp->cn_flags & LOCKPARENT;
struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
- struct ucred *saved_cred = 0;
+ struct ucred *saved_cred;
+ int iswhiteout;
+ struct vattr va;
+
+#ifdef notyet
+ if (cnp->cn_namelen == 3 &&
+ cnp->cn_nameptr[2] == '.' &&
+ cnp->cn_nameptr[1] == '.' &&
+ cnp->cn_nameptr[0] == '.') {
+ dvp = *ap->a_vpp = LOWERVP(ap->a_dvp);
+ if (dvp == NULLVP)
+ return (ENOENT);
+ VREF(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (!lockparent || !(cnp->cn_flags & ISLASTCN))
+ VOP_UNLOCK(ap->a_dvp, 0, p);
+ return (0);
+ }
+#endif
cnp->cn_flags |= LOCKPARENT;
@@ -216,6 +231,7 @@ union_lookup(ap)
lowerdvp = dun->un_lowervp;
uppervp = NULLVP;
lowervp = NULLVP;
+ iswhiteout = 0;
/*
* do the lookup in the upper level.
@@ -223,9 +239,9 @@ union_lookup(ap)
* then assume that something special is going
* on and just return that vnode.
*/
- if (upperdvp) {
- FIXUP(dun);
- uerror = union_lookup1(um->um_uppervp, upperdvp,
+ if (upperdvp != NULLVP) {
+ FIXUP(dun, p);
+ uerror = union_lookup1(um->um_uppervp, &upperdvp,
&uppervp, cnp);
/*if (uppervp == upperdvp)
dun->un_flags |= UN_KLOCK;*/
@@ -236,6 +252,16 @@ union_lookup(ap)
cnp->cn_flags &= ~LOCKPARENT;
return (uerror);
}
+ if (uerror == ENOENT || uerror == EJUSTRETURN) {
+ if (cnp->cn_flags & ISWHITEOUT) {
+ iswhiteout = 1;
+ } else if (lowerdvp != NULLVP) {
+ lerror = VOP_GETATTR(upperdvp, &va,
+ cnp->cn_cred, cnp->cn_proc);
+ if (lerror == 0 && (va.va_flags & OPAQUE))
+ iswhiteout = 1;
+ }
+ }
} else {
uerror = ENOENT;
}
@@ -247,10 +273,10 @@ union_lookup(ap)
* back from the upper layer and return the lower vnode
* instead.
*/
- if (lowerdvp) {
+ if (lowerdvp != NULLVP && !iswhiteout) {
int nameiop;
- VOP_LOCK(lowerdvp);
+ vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, p);
/*
* Only do a LOOKUP on the bottom node, since
@@ -262,17 +288,17 @@ union_lookup(ap)
saved_cred = cnp->cn_cred;
cnp->cn_cred = um->um_cred;
}
- lerror = union_lookup1(um->um_lowervp, lowerdvp,
+ lerror = union_lookup1(um->um_lowervp, &lowerdvp,
&lowervp, cnp);
if (um->um_op == UNMNT_BELOW)
cnp->cn_cred = saved_cred;
cnp->cn_nameiop = nameiop;
if (lowervp != lowerdvp)
- VOP_UNLOCK(lowerdvp);
+ VOP_UNLOCK(lowerdvp, 0, p);
if (cnp->cn_consume != 0) {
- if (uppervp) {
+ if (uppervp != NULLVP) {
if (uppervp == upperdvp)
vrele(uppervp);
else
@@ -286,6 +312,14 @@ union_lookup(ap)
}
} else {
lerror = ENOENT;
+ if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) {
+ lowervp = LOWERVP(dun->un_pvp);
+ if (lowervp != NULLVP) {
+ VREF(lowervp);
+ vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, p);
+ lerror = 0;
+ }
+ }
}
if (!lockparent)
@@ -326,13 +360,13 @@ union_lookup(ap)
if (uerror != 0 /* && (lerror == 0) */ ) {
if (lowervp->v_type == VDIR) { /* case 2b. */
dun->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(upperdvp);
+ VOP_UNLOCK(upperdvp, 0, p);
uerror = union_mkshadow(um, upperdvp, cnp, &uppervp);
- VOP_LOCK(upperdvp);
+ vn_lock(upperdvp, LK_EXCLUSIVE | LK_RETRY, p);
dun->un_flags |= UN_ULOCK;
if (uerror) {
- if (lowervp) {
+ if (lowervp != NULLVP) {
vput(lowervp);
lowervp = NULLVP;
}
@@ -341,21 +375,21 @@ union_lookup(ap)
}
}
- if (lowervp)
- VOP_UNLOCK(lowervp);
+ if (lowervp != NULLVP)
+ VOP_UNLOCK(lowervp, 0, p);
error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
- uppervp, lowervp);
+ uppervp, lowervp, 1);
if (error) {
- if (uppervp)
+ if (uppervp != NULLVP)
vput(uppervp);
- if (lowervp)
+ if (lowervp != NULLVP)
vrele(lowervp);
} else {
if (*ap->a_vpp != dvp)
if (!lockparent || !(cnp->cn_flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
return (error);
@@ -372,28 +406,26 @@ union_create(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
+ struct mount *mp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
+ mp = ap->a_dvp->v_mount;
vput(ap->a_dvp);
- error = VOP_CREATE(dvp, &vp, ap->a_cnp, ap->a_vap);
+ error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
if (error)
return (error);
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, cnp, vp,
+ NULLVP, 1);
if (error)
vput(vp);
return (error);
@@ -404,6 +436,25 @@ union_create(ap)
}
int
+union_whiteout(ap)
+ struct vop_whiteout_args /* {
+ struct vnode *a_dvp;
+ struct componentname *a_cnp;
+ int a_flags;
+ } */ *ap;
+{
+ struct union_node *un = VTOUNION(ap->a_dvp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+
+ if (un->un_uppervp == NULLVP)
+ return (EOPNOTSUPP);
+
+ FIXUP(un, p);
+ return (VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags));
+}
+
+int
union_mknod(ap)
struct vop_mknod_args /* {
struct vnode *a_dvp;
@@ -414,29 +465,27 @@ union_mknod(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
+ struct mount *mp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
+ mp = ap->a_dvp->v_mount;
vput(ap->a_dvp);
- error = VOP_MKNOD(dvp, &vp, ap->a_cnp, ap->a_vap);
+ error = VOP_MKNOD(dvp, &vp, cnp, ap->a_vap);
if (error)
return (error);
- if (vp) {
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ if (vp != NULLVP) {
+ error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
+ cnp, vp, NULLVP, 1);
if (error)
vput(vp);
}
@@ -476,77 +525,7 @@ union_open(ap)
*/
tvp = un->un_lowervp;
if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
- struct vnode *vp;
- int i;
-
- /*
- * Open the named file in the upper layer. Note that
- * the file may have come into existence *since* the
- * lookup was done, since the upper layer may really
- * be a loopback mount of some other filesystem...
- * so open the file with exclusive create and barf if
- * it already exists.
- * XXX - perhaps should re-lookup the node (once more
- * with feeling) and simply open that. Who knows.
- */
- error = union_vn_create(&vp, un, p);
- if (error)
- return (error);
-
- /* at this point, uppervp is locked */
- union_newupper(un, vp);
- un->un_flags |= UN_ULOCK;
-
- /*
- * Now, if the file is being opened with truncation,
- * then the (new) upper vnode is ready to fly,
- * otherwise the data from the lower vnode must be
- * copied to the upper layer first. This only works
- * for regular files (check is made above).
- */
- if ((mode & O_TRUNC) == 0) {
- /*
- * XXX - should not ignore errors
- * from VOP_CLOSE
- */
- VOP_LOCK(tvp);
- error = VOP_OPEN(tvp, FREAD, cred, p);
- if (error == 0) {
- error = union_copyfile(p, cred,
- tvp, un->un_uppervp);
- VOP_UNLOCK(tvp);
- (void) VOP_CLOSE(tvp, FREAD, cred, p);
- } else {
- VOP_UNLOCK(tvp);
- }
-
-#ifdef UNION_DIAGNOSTIC
- if (!error)
- uprintf("union: copied up %s\n",
- un->un_path);
-#endif
- }
-
- un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp);
- union_vn_close(un->un_uppervp, FWRITE, cred, p);
- VOP_LOCK(un->un_uppervp);
- un->un_flags |= UN_ULOCK;
-
- /*
- * Subsequent IOs will go to the top layer, so
- * call close on the lower vnode and open on the
- * upper vnode to ensure that the filesystem keeps
- * its references counts right. This doesn't do
- * the right thing with (cred) and (FREAD) though.
- * Ignoring error returns is not righ, either.
- */
- for (i = 0; i < un->un_openl; i++) {
- (void) VOP_CLOSE(tvp, FREAD, cred, p);
- (void) VOP_OPEN(un->un_uppervp, FREAD, cred, p);
- }
- un->un_openl = 0;
-
+ error = union_copyup(un, (mode&O_TRUNC) == 0, cred, p);
if (error == 0)
error = VOP_OPEN(un->un_uppervp, mode, cred, p);
return (error);
@@ -556,14 +535,14 @@ union_open(ap)
* Just open the lower vnode
*/
un->un_openl++;
- VOP_LOCK(tvp);
+ vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_OPEN(tvp, mode, cred, p);
- VOP_UNLOCK(tvp);
+ VOP_UNLOCK(tvp, 0, p);
return (error);
}
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_OPEN(tvp, mode, cred, p);
@@ -582,9 +561,7 @@ union_close(ap)
struct union_node *un = VTOUNION(ap->a_vp);
struct vnode *vp;
- if (un->un_uppervp) {
- vp = un->un_uppervp;
- } else {
+ if ((vp = un->un_uppervp) == NULLVP) {
#ifdef UNION_DIAGNOSTIC
if (un->un_openl <= 0)
panic("union: un_openl cnt");
@@ -593,7 +570,8 @@ union_close(ap)
vp = un->un_lowervp;
}
- return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));
+ ap->a_vp = vp;
+ return (VCALL(vp, VOFFSET(vop_close), ap));
}
/*
@@ -615,27 +593,29 @@ union_access(ap)
} */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
int error = EACCES;
struct vnode *vp;
- vp = un->un_uppervp;
- if (vp) {
- FIXUP(un);
- return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p));
+ if ((vp = un->un_uppervp) != NULLVP) {
+ FIXUP(un, p);
+ ap->a_vp = vp;
+ return (VCALL(vp, VOFFSET(vop_access), ap));
}
- vp = un->un_lowervp;
- if (vp) {
- VOP_LOCK(vp);
- error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p);
+ if ((vp = un->un_lowervp) != NULLVP) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_access), ap);
if (error == 0) {
struct union_mount *um = MOUNTTOUNIONMOUNT(vp->v_mount);
- if (um->um_op == UNMNT_BELOW)
- error = VOP_ACCESS(vp, ap->a_mode,
- um->um_cred, ap->a_p);
+ if (um->um_op == UNMNT_BELOW) {
+ ap->a_cred = um->um_cred;
+ error = VCALL(vp, VOFFSET(vop_access), ap);
+ }
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (error)
return (error);
}
@@ -644,7 +624,8 @@ union_access(ap)
}
/*
- * We handle getattr only to change the fsid.
+ * We handle getattr only to change the fsid and
+ * track object sizes
*/
int
union_getattr(ap)
@@ -658,6 +639,7 @@ union_getattr(ap)
int error;
struct union_node *un = VTOUNION(ap->a_vp);
struct vnode *vp = un->un_uppervp;
+ struct proc *p = ap->a_p;
struct vattr *vap;
struct vattr va;
@@ -675,10 +657,21 @@ union_getattr(ap)
vp = un->un_uppervp;
if (vp != NULLVP) {
- FIXUP(un);
+ /*
+ * It's not clear whether VOP_GETATTR is to be
+ * called with the vnode locked or not. stat() calls
+ * it with (vp) locked, and fstat calls it with
+ * (vp) unlocked.
+ * In the mean time, compensate here by checking
+ * the union_node's lock flag.
+ */
+ if (un->un_flags & UN_LOCKED)
+ FIXUP(un, p);
+
error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
if (error)
return (error);
+ union_newsize(ap->a_vp, vap->va_size, VNOVAL);
}
if (vp == NULLVP) {
@@ -691,17 +684,16 @@ union_getattr(ap)
}
if (vp != NULLVP) {
- VOP_LOCK(vp);
error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
- VOP_UNLOCK(vp);
if (error)
return (error);
+ union_newsize(ap->a_vp, VNOVAL, vap->va_size);
}
if ((vap != ap->a_vap) && (vap->va_type == VDIR))
ap->a_vap->va_nlink += vap->va_nlink;
- vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
+ ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
return (0);
}
@@ -715,6 +707,7 @@ union_setattr(ap)
} */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
int error;
/*
@@ -724,21 +717,11 @@ union_setattr(ap)
*/
if ((un->un_uppervp == NULLVP) &&
/* assert(un->un_lowervp != NULLVP) */
- (un->un_lowervp->v_type == VREG) &&
- (ap->a_vap->va_size == 0)) {
- struct vnode *vp;
-
- error = union_vn_create(&vp, un, ap->a_p);
+ (un->un_lowervp->v_type == VREG)) {
+ error = union_copyup(un, (ap->a_vap->va_size != 0),
+ ap->a_cred, ap->a_p);
if (error)
return (error);
-
- /* at this point, uppervp is locked */
- union_newupper(un, vp);
-
- VOP_UNLOCK(vp);
- union_vn_close(un->un_uppervp, FWRITE, ap->a_cred, ap->a_p);
- VOP_LOCK(vp);
- un->un_flags |= UN_ULOCK;
}
/*
@@ -746,9 +729,11 @@ union_setattr(ap)
* otherwise return read-only filesystem error.
*/
if (un->un_uppervp != NULLVP) {
- FIXUP(un);
+ FIXUP(un, p);
error = VOP_SETATTR(un->un_uppervp, ap->a_vap,
ap->a_cred, ap->a_p);
+ if ((error == 0) && (ap->a_vap->va_size != VNOVAL))
+ union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL);
} else {
error = EROFS;
}
@@ -766,16 +751,36 @@ union_read(ap)
} */ *ap;
{
int error;
+ struct proc *p = ap->a_uio->uio_procp;
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
+ FIXUP(VTOUNION(ap->a_vp), p);
error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
+
+ /*
+ * XXX
+ * perhaps the size of the underlying object has changed under
+ * our feet. take advantage of the offset information present
+ * in the uio structure.
+ */
+ if (error == 0) {
+ struct union_node *un = VTOUNION(ap->a_vp);
+ off_t cur = ap->a_uio->uio_offset;
+
+ if (vp == un->un_uppervp) {
+ if (cur > un->un_uppersz)
+ union_newsize(ap->a_vp, cur, VNOVAL);
+ } else {
+ if (cur > un->un_lowersz)
+ union_newsize(ap->a_vp, VNOVAL, cur);
+ }
+ }
return (error);
}
@@ -790,21 +795,47 @@ union_write(ap)
} */ *ap;
{
int error;
- struct vnode *vp = OTHERVP(ap->a_vp);
- int dolock = (vp == LOWERVP(ap->a_vp));
+ struct vnode *vp;
+ struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_uio->uio_procp;
- if (dolock)
- VOP_LOCK(vp);
- else
- FIXUP(VTOUNION(ap->a_vp));
+ vp = UPPERVP(ap->a_vp);
+ if (vp == NULLVP)
+ panic("union: missing upper layer in write");
+
+ FIXUP(un, p);
error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
- if (dolock)
- VOP_UNLOCK(vp);
+
+ /*
+ * the size of the underlying object may be changed by the
+ * write.
+ */
+ if (error == 0) {
+ off_t cur = ap->a_uio->uio_offset;
+
+ if (cur > un->un_uppersz)
+ union_newsize(ap->a_vp, cur, VNOVAL);
+ }
return (error);
}
int
+union_lease(ap)
+ struct vop_lease_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ struct ucred *a_cred;
+ int a_flag;
+ } */ *ap;
+{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
+
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_lease), ap));
+}
+
+int
union_ioctl(ap)
struct vop_ioctl_args /* {
struct vnode *a_vp;
@@ -815,9 +846,10 @@ union_ioctl(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_IOCTL(OTHERVP(ap->a_vp), ap->a_command, ap->a_data,
- ap->a_fflag, ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_ioctl), ap));
}
int
@@ -830,9 +862,28 @@ union_select(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_SELECT(OTHERVP(ap->a_vp), ap->a_which, ap->a_fflags,
- ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_select), ap));
+}
+
+int
+union_revoke(ap)
+ struct vop_revoke_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+
+ if (UPPERVP(vp))
+ VOP_REVOKE(UPPERVP(vp), ap->a_flags);
+ if (LOWERVP(vp))
+ VOP_REVOKE(LOWERVP(vp), ap->a_flags);
+ vgone(vp);
+ return (0);
}
int
@@ -844,9 +895,10 @@ union_mmap(ap)
struct proc *a_p;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_MMAP(OTHERVP(ap->a_vp), ap->a_fflags,
- ap->a_cred, ap->a_p));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_mmap), ap));
}
int
@@ -859,19 +911,19 @@ union_fsync(ap)
} */ *ap;
{
int error = 0;
+ struct proc *p = ap->a_p;
struct vnode *targetvp = OTHERVP(ap->a_vp);
- if (targetvp) {
+ if (targetvp != NULLVP) {
int dolock = (targetvp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(targetvp);
+ vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_FSYNC(targetvp, ap->a_cred,
- ap->a_waitfor, ap->a_p);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
if (dolock)
- VOP_UNLOCK(targetvp);
+ VOP_UNLOCK(targetvp, 0, p);
}
return (error);
@@ -886,8 +938,10 @@ union_seek(ap)
struct ucred *a_cred;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_SEEK(OTHERVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_seek), ap));
}
int
@@ -901,34 +955,37 @@ union_remove(ap)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dun->un_uppervp && un->un_uppervp) {
+ if (dun->un_uppervp == NULLVP)
+ panic("union remove: null upper vnode");
+
+ if (un->un_uppervp != NULLVP) {
struct vnode *dvp = dun->un_uppervp;
struct vnode *vp = un->un_uppervp;
- FIXUP(dun);
+ FIXUP(dun, p);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- FIXUP(un);
+ FIXUP(un, p);
VREF(vp);
un->un_flags |= UN_KLOCK;
vput(ap->a_vp);
- error = VOP_REMOVE(dvp, vp, ap->a_cnp);
+ if (union_dowhiteout(un, cnp->cn_cred, cnp->cn_proc))
+ cnp->cn_flags |= DOWHITEOUT;
+ error = VOP_REMOVE(dvp, vp, cnp);
if (!error)
union_removed_upper(un);
-
- /*
- * XXX: should create a whiteout here
- */
} else {
- /*
- * XXX: should create a whiteout here
- */
+ FIXUP(dun, p);
+ error = union_mkwhiteout(
+ MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
+ dun->un_uppervp, ap->a_cnp, un->un_path);
vput(ap->a_dvp);
vput(ap->a_vp);
- error = EROFS;
}
return (error);
@@ -942,34 +999,51 @@ union_link(ap)
struct componentname *a_cnp;
} */ *ap;
{
- int error;
- struct union_node *dun = VTOUNION(ap->a_vp);
- struct union_node *un = VTOUNION(ap->a_tdvp);
-
- if (dun->un_uppervp && un->un_uppervp) {
- struct vnode *dvp = dun->un_uppervp;
- struct vnode *vp = un->un_uppervp;
+ int error = 0;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
+ struct union_node *un;
+ struct vnode *vp;
+ struct vnode *tdvp;
- FIXUP(dun);
- VREF(dvp);
- dun->un_flags |= UN_KLOCK;
- vput(ap->a_vp);
- FIXUP(un);
- VREF(vp);
- vrele(ap->a_tdvp);
+ un = VTOUNION(ap->a_tdvp);
- error = VOP_LINK(dvp, vp, ap->a_cnp);
+ if (ap->a_tdvp->v_op != ap->a_vp->v_op) {
+ vp = ap->a_vp;
} else {
- /*
- * XXX: need to copy to upper layer
- * and do the link there.
- */
- vput(ap->a_vp);
- vrele(ap->a_tdvp);
+ struct union_node *tun = VTOUNION(ap->a_vp);
+ if (tun->un_uppervp == NULLVP) {
+ vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (un->un_uppervp == tun->un_dirvp) {
+ un->un_flags &= ~UN_ULOCK;
+ VOP_UNLOCK(un->un_uppervp, 0, p);
+ }
+ error = union_copyup(tun, 1, cnp->cn_cred, p);
+ if (un->un_uppervp == tun->un_dirvp) {
+ vn_lock(un->un_uppervp,
+ LK_EXCLUSIVE | LK_RETRY, p);
+ un->un_flags |= UN_ULOCK;
+ }
+ VOP_UNLOCK(ap->a_vp, 0, p);
+ }
+ vp = tun->un_uppervp;
+ }
+
+ tdvp = un->un_uppervp;
+ if (tdvp == NULLVP)
error = EROFS;
+
+ if (error) {
+ vput(ap->a_tdvp);
+ return (error);
}
- return (error);
+ FIXUP(un, p);
+ VREF(tdvp);
+ un->un_flags |= UN_KLOCK;
+ vput(ap->a_tdvp);
+
+ return (VOP_LINK(vp, tdvp, cnp));
}
int
@@ -993,11 +1067,16 @@ union_rename(ap)
if (fdvp->v_op == union_vnodeop_p) { /* always true */
struct union_node *un = VTOUNION(fdvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /*
+ * this should never happen in normal
+ * operation but might if there was
+ * a problem creating the top-level shadow
+ * directory.
+ */
+ error = EXDEV;
goto bad;
}
- FIXUP(un);
fdvp = un->un_uppervp;
VREF(fdvp);
vrele(ap->a_fdvp);
@@ -1006,11 +1085,14 @@ union_rename(ap)
if (fvp->v_op == union_vnodeop_p) { /* always true */
struct union_node *un = VTOUNION(fvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /* XXX: should do a copyup */
+ error = EXDEV;
goto bad;
}
- FIXUP(un);
+ if (un->un_lowervp != NULLVP)
+ ap->a_fcnp->cn_flags |= DOWHITEOUT;
+
fvp = un->un_uppervp;
VREF(fvp);
vrele(ap->a_fvp);
@@ -1019,7 +1101,13 @@ union_rename(ap)
if (tdvp->v_op == union_vnodeop_p) {
struct union_node *un = VTOUNION(tdvp);
if (un->un_uppervp == NULLVP) {
- error = EROFS;
+ /*
+ * this should never happen in normal
+ * operation but might if there was
+ * a problem creating the top-level shadow
+ * directory.
+ */
+ error = EXDEV;
goto bad;
}
@@ -1029,16 +1117,14 @@ union_rename(ap)
vput(ap->a_tdvp);
}
- if (tvp && tvp->v_op == union_vnodeop_p) {
+ if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) {
struct union_node *un = VTOUNION(tvp);
- if (un->un_uppervp == NULLVP) {
- error = EROFS;
- goto bad;
- }
tvp = un->un_uppervp;
- VREF(tvp);
- un->un_flags |= UN_KLOCK;
+ if (tvp != NULLVP) {
+ VREF(tvp);
+ un->un_flags |= UN_KLOCK;
+ }
vput(ap->a_tvp);
}
@@ -1048,7 +1134,7 @@ bad:
vrele(fdvp);
vrele(fvp);
vput(tdvp);
- if (tvp)
+ if (tvp != NULLVP)
vput(tvp);
return (error);
@@ -1065,27 +1151,26 @@ union_mkdir(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
- vput(ap->a_dvp);
- error = VOP_MKDIR(dvp, &vp, ap->a_cnp, ap->a_vap);
- if (error)
+ VOP_UNLOCK(ap->a_dvp, 0, p);
+ error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap);
+ if (error) {
+ vrele(ap->a_dvp);
return (error);
+ }
- error = union_allocvp(
- ap->a_vpp,
- ap->a_dvp->v_mount,
- ap->a_dvp,
- NULLVP,
- ap->a_cnp,
- vp,
- NULLVP);
+ error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp,
+ NULLVP, cnp, vp, NULLVP, 1);
+ vrele(ap->a_dvp);
if (error)
vput(vp);
return (error);
@@ -1106,34 +1191,37 @@ union_rmdir(ap)
int error;
struct union_node *dun = VTOUNION(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_vp);
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dun->un_uppervp && un->un_uppervp) {
+ if (dun->un_uppervp == NULLVP)
+ panic("union rmdir: null upper vnode");
+
+ if (un->un_uppervp != NULLVP) {
struct vnode *dvp = dun->un_uppervp;
struct vnode *vp = un->un_uppervp;
- FIXUP(dun);
+ FIXUP(dun, p);
VREF(dvp);
dun->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- FIXUP(un);
+ FIXUP(un, p);
VREF(vp);
un->un_flags |= UN_KLOCK;
vput(ap->a_vp);
+ if (union_dowhiteout(un, cnp->cn_cred, cnp->cn_proc))
+ cnp->cn_flags |= DOWHITEOUT;
error = VOP_RMDIR(dvp, vp, ap->a_cnp);
if (!error)
union_removed_upper(un);
-
- /*
- * XXX: should create a whiteout here
- */
} else {
- /*
- * XXX: should create a whiteout here
- */
+ FIXUP(dun, p);
+ error = union_mkwhiteout(
+ MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
+ dun->un_uppervp, ap->a_cnp, un->un_path);
vput(ap->a_dvp);
vput(ap->a_vp);
- error = EROFS;
}
return (error);
@@ -1151,17 +1239,18 @@ union_symlink(ap)
{
struct union_node *un = VTOUNION(ap->a_dvp);
struct vnode *dvp = un->un_uppervp;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
- if (dvp) {
+ if (dvp != NULLVP) {
int error;
struct vnode *vp;
- FIXUP(un);
+ FIXUP(un, p);
VREF(dvp);
un->un_flags |= UN_KLOCK;
vput(ap->a_dvp);
- error = VOP_SYMLINK(dvp, &vp, ap->a_cnp,
- ap->a_vap, ap->a_target);
+ error = VOP_SYMLINK(dvp, &vp, cnp, ap->a_vap, ap->a_target);
*ap->a_vpp = NULLVP;
return (error);
}
@@ -1183,17 +1272,21 @@ union_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
+ int *a_eofflag;
+ u_long *a_cookies;
+ int a_ncookies;
} */ *ap;
{
- int error = 0;
struct union_node *un = VTOUNION(ap->a_vp);
+ struct vnode *uvp = un->un_uppervp;
+ struct proc *p = ap->a_uio->uio_procp;
- if (un->un_uppervp) {
- FIXUP(un);
- error = VOP_READDIR(un->un_uppervp, ap->a_uio, ap->a_cred, NULL, NULL, NULL);
- }
+ if (uvp == NULLVP)
+ return (0);
- return (error);
+ FIXUP(un, p);
+ ap->a_vp = uvp;
+ return (VCALL(uvp, VOFFSET(vop_readdir), ap));
}
int
@@ -1205,16 +1298,19 @@ union_readlink(ap)
} */ *ap;
{
int error;
+ struct uio *uio = ap->a_uio;
+ struct proc *p = uio->uio_procp;
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_READLINK(vp, ap->a_uio, ap->a_cred);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_readlink), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1227,6 +1323,8 @@ union_abortop(ap)
} */ *ap;
{
int error;
+ struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
struct vnode *vp = OTHERVP(ap->a_dvp);
struct union_node *un = VTOUNION(ap->a_dvp);
int islocked = un->un_flags & UN_LOCKED;
@@ -1234,13 +1332,14 @@ union_abortop(ap)
if (islocked) {
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_dvp));
+ FIXUP(VTOUNION(ap->a_dvp), p);
}
- error = VOP_ABORTOP(vp, ap->a_cnp);
+ ap->a_dvp = vp;
+ error = VCALL(vp, VOFFSET(vop_abortop), ap);
if (islocked && dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1249,8 +1348,13 @@ int
union_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
+ struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
+ struct union_node *un = VTOUNION(vp);
+ struct vnode **vpp;
/*
* Do nothing (and _don't_ bypass).
@@ -1265,12 +1369,17 @@ union_inactive(ap)
* That's too much work for now.
*/
-#ifdef UNION_DIAGNOSTIC
- struct union_node *un = VTOUNION(ap->a_vp);
+ if (un->un_dircache != 0) {
+ for (vpp = un->un_dircache; *vpp != NULLVP; vpp++)
+ vrele(*vpp);
+ free(un->un_dircache, M_TEMP);
+ un->un_dircache = 0;
+ }
- if (un->un_flags & UN_LOCKED)
- panic("union: inactivating locked node");
-#endif
+ VOP_UNLOCK(vp, 0, p);
+
+ if ((un->un_flags & UN_CACHED) == 0)
+ vgone(vp);
return (0);
}
@@ -1292,24 +1401,39 @@ union_lock(ap)
struct vop_lock_args *ap;
{
struct vnode *vp = ap->a_vp;
+ struct proc *p = ap->a_p;
+ int flags = ap->a_flags;
struct union_node *un;
+ int error;
-start:
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t)vp, PINOD, "unnlk1", 0);
- }
+ vop_nolock(ap);
+ /*
+ * Need to do real lockmgr-style locking here.
+ * in the mean time, draining won't work quite right,
+ * which could lead to a few race conditions.
+ * the following test was here, but is not quite right, we
+ * still need to take the lock:
+ if ((flags & LK_TYPE_MASK) == LK_DRAIN)
+ return (0);
+ */
+ flags &= ~LK_INTERLOCK;
+start:
un = VTOUNION(vp);
- if (un->un_uppervp) {
- if ((un->un_flags & UN_ULOCK) == 0) {
+ if (un->un_uppervp != NULLVP) {
+ if (((un->un_flags & UN_ULOCK) == 0) &&
+ (vp->v_usecount != 0)) {
+ error = vn_lock(un->un_uppervp, flags, p);
+ if (error)
+ return (error);
un->un_flags |= UN_ULOCK;
- VOP_LOCK(un->un_uppervp);
}
#ifdef DIAGNOSTIC
- if (un->un_flags & UN_KLOCK)
- panic("union: dangling upper lock");
+ if (un->un_flags & UN_KLOCK) {
+ vprint("union: dangling klock", vp);
+ panic("union: dangling upper lock (%lx)", vp);
+ }
#endif
}
@@ -1320,7 +1444,7 @@ start:
panic("union: locking against myself");
#endif
un->un_flags |= UN_WANT;
- (void) tsleep((caddr_t) &un->un_flags, PINOD, "unnlk2", 0);
+ tsleep((caddr_t)&un->un_flags, PINOD, "unionlk2", 0);
goto start;
}
@@ -1335,11 +1459,27 @@ start:
return (0);
}
+/*
+ * When operations want to vput() a union node yet retain a lock on
+ * the upper vnode (say, to do some further operations like link(),
+ * mkdir(), ...), they set UN_KLOCK on the union node, then call
+ * vput() which calls VOP_UNLOCK() and comes here. union_unlock()
+ * unlocks the union node (leaving the upper vnode alone), clears the
+ * KLOCK flag, and then returns to vput(). The caller then does whatever
+ * is left to do with the upper vnode, and ensures that it gets unlocked.
+ *
+ * If UN_KLOCK isn't set, then the upper vnode is unlocked here.
+ */
int
union_unlock(ap)
- struct vop_lock_args *ap;
+ struct vop_unlock_args /* {
+ struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
+ } */ *ap;
{
struct union_node *un = VTOUNION(ap->a_vp);
+ struct proc *p = ap->a_p;
#ifdef DIAGNOSTIC
if ((un->un_flags & UN_LOCKED) == 0)
@@ -1352,7 +1492,7 @@ union_unlock(ap)
un->un_flags &= ~UN_LOCKED;
if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK)
- VOP_UNLOCK(un->un_uppervp);
+ VOP_UNLOCK(un->un_uppervp, 0, p);
un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
@@ -1364,6 +1504,7 @@ union_unlock(ap)
#ifdef DIAGNOSTIC
un->un_pid = 0;
#endif
+ vop_nounlock(ap);
return (0);
}
@@ -1380,16 +1521,18 @@ union_bmap(ap)
} */ *ap;
{
int error;
+ struct proc *p = curproc; /* XXX */
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_BMAP(vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp, ap->a_runb);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_bmap), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1404,6 +1547,11 @@ union_print(ap)
printf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n",
vp, UPPERVP(vp), LOWERVP(vp));
+ if (UPPERVP(vp) != NULLVP)
+ vprint("union: upper", UPPERVP(vp));
+ if (LOWERVP(vp) != NULLVP)
+ vprint("union: lower", LOWERVP(vp));
+
return (0);
}
@@ -1426,16 +1574,18 @@ union_pathconf(ap)
} */ *ap;
{
int error;
+ struct proc *p = curproc; /* XXX */
struct vnode *vp = OTHERVP(ap->a_vp);
int dolock = (vp == LOWERVP(ap->a_vp));
if (dolock)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
else
- FIXUP(VTOUNION(ap->a_vp));
- error = VOP_PATHCONF(vp, ap->a_name, ap->a_retval);
+ FIXUP(VTOUNION(ap->a_vp), p);
+ ap->a_vp = vp;
+ error = VCALL(vp, VOFFSET(vop_pathconf), ap);
if (dolock)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
return (error);
}
@@ -1450,9 +1600,10 @@ union_advlock(ap)
int a_flags;
} */ *ap;
{
+ register struct vnode *ovp = OTHERVP(ap->a_vp);
- return (VOP_ADVLOCK(OTHERVP(ap->a_vp), ap->a_id, ap->a_op,
- ap->a_fl, ap->a_flags));
+ ap->a_vp = ovp;
+ return (VCALL(ovp, VOFFSET(vop_advlock), ap));
}
@@ -1496,6 +1647,7 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
{ &vop_lookup_desc, (vop_t *)union_lookup }, /* lookup */
{ &vop_create_desc, (vop_t *)union_create }, /* create */
+ { &vop_whiteout_desc, (vop_t *)union_whiteout }, /* whiteout */
{ &vop_mknod_desc, (vop_t *)union_mknod }, /* mknod */
{ &vop_open_desc, (vop_t *)union_open }, /* open */
{ &vop_close_desc, (vop_t *)union_close }, /* close */
@@ -1504,8 +1656,10 @@ struct vnodeopv_entry_desc union_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)union_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)union_read }, /* read */
{ &vop_write_desc, (vop_t *)union_write }, /* write */
+ { &vop_lease_desc, (vop_t *)union_lease }, /* lease */
{ &vop_ioctl_desc, (vop_t *)union_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)union_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)union_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)union_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)union_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)union_seek }, /* seek */
diff --git a/sys/msdosfs/msdosfs_denode.c b/sys/msdosfs/msdosfs_denode.c
index de4bf5e..a891ddc 100644
--- a/sys/msdosfs/msdosfs_denode.c
+++ b/sys/msdosfs/msdosfs_denode.c
@@ -124,7 +124,7 @@ msdosfs_hashget(dev, dirclust, diroff)
(void) tsleep((caddr_t)dep, PINOD, "msdhgt", 0);
break;
}
- if (!vget(DETOV(dep), 1))
+ if (!vget(DETOV(dep), LK_EXCLUSIVE | LK_INTERLOCK, curproc))
return dep;
break;
}
@@ -259,7 +259,7 @@ deget(pmp, dirclust, diroffset, direntptr, depp)
* can't be accessed until we've read it in and have done what we
* need to it.
*/
- VOP_LOCK(nvp);
+ vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY, curproc);
msdosfs_hashins(ldep);
/*
@@ -716,7 +716,7 @@ msdosfs_inactive(ap)
printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n",
dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
#endif
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
error = detrunc(dep, (u_long) 0, 0, NOCRED, NULL);
dep->de_flag |= DE_UPDATE;
@@ -726,7 +726,7 @@ msdosfs_inactive(ap)
TIMEVAL_TO_TIMESPEC(&time, &ts);
deupdat(dep, &ts, 0);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curproc);
dep->de_flag = 0;
/*
diff --git a/sys/msdosfs/msdosfs_lookup.c b/sys/msdosfs/msdosfs_lookup.c
index 60236b8..6617f9e 100644
--- a/sys/msdosfs/msdosfs_lookup.c
+++ b/sys/msdosfs/msdosfs_lookup.c
@@ -54,6 +54,7 @@
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <msdosfs/bpb.h>
#include <msdosfs/direntry.h>
@@ -156,14 +157,14 @@ msdosfs_lookup(ap)
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, curproc);
+ error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE | LK_INTERLOCK, curproc);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
}
if (!error) {
@@ -183,9 +184,9 @@ msdosfs_lookup(ap)
}
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
}
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (error)
return error;
vdp = pdp;
@@ -345,7 +346,7 @@ notfound:;
/* dp->de_flag |= DE_UPDATE; never update dos directories */
cnp->cn_flags |= SAVENAME;
if (!lockparent)/* leave searched dir locked? */
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
return EJUSTRETURN;
}
/*
@@ -398,7 +399,7 @@ foundroot:;
}
*vpp = DETOV(tdp);
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
if (bp)
brelse(bp);
return 0;
@@ -428,7 +429,7 @@ foundroot:;
*vpp = DETOV(tdp);
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, curproc);
if (bp)
brelse(bp);
return 0;
@@ -439,16 +440,16 @@ foundroot:;
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
error = deget(pmp, cluster, diroff, dep, &tdp);
if (error) {
- VOP_LOCK(pdp);
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc);
if (bp)
brelse(bp);
return error;
}
if (lockparent && (flags & ISLASTCN)
- && (error = VOP_LOCK(pdp))) {
+ && (error = vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, curproc))) {
vput(DETOV(tdp));
return error;
}
@@ -464,7 +465,7 @@ foundroot:;
return error;
}
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, curproc);
*vpp = DETOV(tdp);
}
if (bp)
diff --git a/sys/msdosfs/msdosfs_vfsops.c b/sys/msdosfs/msdosfs_vfsops.c
index 5669c63..d0c8cdb 100644
--- a/sys/msdosfs/msdosfs_vfsops.c
+++ b/sys/msdosfs/msdosfs_vfsops.c
@@ -130,10 +130,10 @@ msdosfs_mount(mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp))
+ if (vfs_busy(mp, LK_NOWAIT, 0, p))
return EBUSY;
error = vflush(mp, NULLVP, flags);
- vfs_unbusy(mp);
+ vfs_unbusy(mp, p);
}
if (!error && (mp->mnt_flag & MNT_RELOAD))
/* not yet implemented */
@@ -707,7 +707,7 @@ loop:
if ((dep->de_flag & (DE_MODIFIED | DE_UPDATE)) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL)
continue;
- if (vget(vp, 1)) /* not there anymore? */
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) /* not there anymore? */
goto loop;
error = VOP_FSYNC(vp, cred, waitfor, p);
if (error)
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c
index bc4e12e..0f4deae 100644
--- a/sys/msdosfs/msdosfs_vnops.c
+++ b/sys/msdosfs/msdosfs_vnops.c
@@ -1172,17 +1172,17 @@ msdosfs_rename(ap)
*/
if (newparent == 0) {
/* tddep and fddep point to the same denode here */
- VOP_LOCK(ap->a_fvp); /* ap->a_fdvp is already locked */
+ vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc); /* ap->a_fdvp is already locked */
error = readep(fddep->de_pmp, fdep->de_dirclust,
fdep->de_diroffset, &bp, &ep);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
bcopy(toname, ep->deName, 11);
error = bwrite(bp);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
bcopy(toname, fdep->de_Name, 11); /* update denode */
@@ -1204,7 +1204,7 @@ msdosfs_rename(ap)
* will also insure that the directory entry on disk has a
* filesize of zero.
*/
- VOP_LOCK(ap->a_fvp);
+ vn_lock(ap->a_fvp, LK_EXCLUSIVE | LK_RETRY, curproc);
bcopy(toname, fdep->de_Name, 11); /* update denode */
if (fdep->de_Attributes & ATTR_DIRECTORY) {
dirsize = fdep->de_FileSize;
@@ -1216,22 +1216,22 @@ msdosfs_rename(ap)
}
if (error) {
/* should put back filename */
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
- VOP_LOCK(ap->a_fdvp);
+ vn_lock(ap->a_fdvp, LK_EXCLUSIVE | LK_RETRY, curproc);
error = readep(fddep->de_pmp, fddep->de_fndclust,
fddep->de_fndoffset, &bp, &ep);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
goto bad;
}
ep->deName[0] = SLOT_DELETED;
error = bwrite(bp);
if (error) {
- VOP_UNLOCK(ap->a_fvp);
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
goto bad;
}
if (!sourceisadirectory) {
@@ -1239,7 +1239,7 @@ msdosfs_rename(ap)
fdep->de_diroffset = tddep->de_fndoffset;
reinsert(fdep);
}
- VOP_UNLOCK(ap->a_fdvp);
+ VOP_UNLOCK(ap->a_fdvp, 0, curproc);
}
/* fdep is still locked here */
@@ -1259,19 +1259,19 @@ msdosfs_rename(ap)
NOCRED, &bp);
if (error) {
/* should really panic here, fs is corrupt */
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
goto bad;
}
dotdotp = (struct direntry *) bp->b_data + 1;
putushort(dotdotp->deStartCluster, tddep->de_StartCluster);
error = bwrite(bp);
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
if (error) {
/* should really panic here, fs is corrupt */
goto bad;
}
} else
- VOP_UNLOCK(ap->a_fvp);
+ VOP_UNLOCK(ap->a_fvp, 0, curproc);
bad: ;
vrele(DETOV(fdep));
vrele(DETOV(fddep));
diff --git a/sys/msdosfs/msdosfsmount.h b/sys/msdosfs/msdosfsmount.h
index 7b0a22e..77c6add 100644
--- a/sys/msdosfs/msdosfsmount.h
+++ b/sys/msdosfs/msdosfsmount.h
@@ -169,3 +169,15 @@ struct msdosfsmount {
(((size) + (pmp)->pm_bpcluster - 1) >> (pmp)->pm_cnshift)
int msdosfs_init __P((void));
+
+/*
+ * Arguments to mount MSDOS filesystems.
+ */
+struct msdosfs_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 */
+};
+
diff --git a/sys/nfs/nfs.h b/sys/nfs/nfs.h
index db41859..73a018c 100644
--- a/sys/nfs/nfs.h
+++ b/sys/nfs/nfs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,19 +33,19 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $FreeBSD$
*/
#ifndef _NFS_NFS_H_
#define _NFS_NFS_H_
-#include <nfs/rpcv2.h>
-
/*
* Tunable constants for nfs
*/
+#ifdef KERNEL
+
#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
@@ -69,7 +69,7 @@
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
+#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
@@ -89,30 +89,9 @@
/*
* XXX
- * sys/buf.h should be edited to change B_APPENDWRITE --> B_NEEDCOMMIT, but
- * until then...
- * Same goes for sys/malloc.h, which needs M_NFSDIROFF,
- * M_NFSRVDESC and M_NFSBIGFH added.
- * The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
- * exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
-#ifndef B_NEEDCOMMIT
-#define B_NEEDCOMMIT B_APPENDWRITE
-#endif
-#ifndef M_NFSRVDESC
-#define M_NFSRVDESC M_TEMP
-#endif
-#ifndef M_NFSDIROFF
-#define M_NFSDIROFF M_TEMP
-#endif
-#ifndef M_NFSBIGFH
-#define M_NFSBIGFH M_TEMP
-#endif
-#ifndef VA_EXCLUSIVE
-#define VA_EXCLUSIVE 0
-#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
@@ -120,20 +99,6 @@
#endif
/*
- * These ifdefs try to handle the differences between the various 4.4BSD-Lite
- * based vfs interfaces.
- * btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
- * differentiate between NetBSD-1.0 and NetBSD-current, so..
- * I also don't know about BSDi's 2.0 release.
- */
-#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPLEASE 1
-#endif
-#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPREVOKE 1
-#endif
-
-/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
@@ -164,13 +129,114 @@
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
+#endif /* KERNEL */
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
+/*
+ * Arguments to mount NFS
+ */
+#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
+struct nfs_args {
+ int version; /* args structure version number */
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
*/
struct nfsd_args {
int sock; /* Socket to serve */
- caddr_t name; /* Client address for connection based sockets */
+ caddr_t name; /* Client addr for connection based sockets */
int namelen; /* Length of name */
};
@@ -200,6 +266,10 @@ struct nfsd_cargs {
};
/*
+ * XXX to allow amd to include nfs.h without nfsproto.h
+ */
+#ifdef NFS_NPROCS
+/*
* Stats structure
*/
struct nfsstats {
@@ -237,6 +307,7 @@ struct nfsstats {
int srvnqnfs_getleases;
int srvvop_writes;
};
+#endif
/*
* Flags for nfssvc() system call.
@@ -267,7 +338,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
-#if defined(KERNEL) || defined(_KERNEL)
+#ifdef KERNEL
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@@ -482,6 +553,8 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
+
+int nfs_init __P((struct vfsconf *vfsp));
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
@@ -516,14 +589,12 @@ int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
u_long nfs_hash __P((nfsfh_t *,int));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
-void nfsrv_cleancache __P((void));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
-int nfs_init __P((void));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
+void nfsrv_cleancache __P((void));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *nmp));
+void nfs_disconnect __P((struct nfsmount *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
@@ -531,7 +602,6 @@ int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_writebp __P((struct buf *,int));
@@ -594,8 +664,8 @@ int nfsrv_symlink __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
-
-
+void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void nfsrv_slpderef __P((struct nfssvc_sock *slp));
#endif /* KERNEL */
#endif
diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c
index d67a3c0..0f636b0 100644
--- a/sys/nfs/nfs_bio.c
+++ b/sys/nfs/nfs_bio.c
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_bio.c 8.5 (Berkeley) 1/4/94
+ * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
@@ -66,19 +67,6 @@ extern int nfs_numasync;
extern struct nfsstats nfsstats;
/*
- * Ifdefs for FreeBSD-current's merged VM/buffer cache. It is unfortunate
- * that this isn't done inside getblk() and brelse() so these calls
- * wouldn't need to be here.
- */
-#ifdef B_VMIO
-#define vnode_pager_uncache(vp)
-#else
-#define vfs_busy_pages(bp, f)
-#define vfs_unbusy_pages(bp)
-#define vfs_dirty_pages(bp)
-#endif
-
-/*
* Vnode op for read using bio
* Any similarity to readip() is purely coincidental
*/
@@ -195,7 +183,7 @@ nfs_bioread(vp, uio, ioflag, cred)
case VDIR:
break;
default:
- printf(" NQNFSNONCACHE: type %x unexpected\n",
+ printf(" NQNFSNONCACHE: type %x unexpected\n",
vp->v_type);
};
}
@@ -225,9 +213,8 @@ nfs_bioread(vp, uio, ioflag, cred)
vfs_unbusy_pages(rabp);
brelse(rabp);
}
- } else {
+ } else
brelse(rabp);
- }
}
}
}
@@ -270,6 +257,7 @@ again:
if (not_readin && n > 0) {
if (on < bp->b_validoff || (on + n) > bp->b_validend) {
bp->b_flags |= B_NOCACHE;
+ bp->b_flags |= B_INVAFTERWRITE;
if (bp->b_dirtyend > 0) {
if ((bp->b_flags & B_DELWRI) == 0)
panic("nfsbioread");
@@ -475,10 +463,6 @@ nfs_write(ap)
*/
biosize = vp->v_mount->mnt_stat.f_iosize;
do {
-
- /*
- * XXX make sure we aren't cached in the VM page cache
- */
/*
* Check for a valid write lease.
*/
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
index 1feadd6..5f83bf5 100644
--- a/sys/nfs/nfs_common.c
+++ b/sys/nfs/nfs_common.c
@@ -100,6 +100,7 @@ enum vtype nv3tov_type[8]= {
VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
};
+int nfs_mount_type;
int nfs_ticks;
struct nfs_reqq nfs_reqq;
@@ -1093,7 +1094,8 @@ nfsm_strtmbuf(mb, bpos, cp, siz)
* Called once to initialize data structures...
*/
int
-nfs_init()
+nfs_init(vfsp)
+ struct vfsconf *vfsp;
{
register int i;
@@ -1116,6 +1118,7 @@ nfs_init()
printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
printf("Try unionizing the nu_nickname and nu_flag fields\n");
}
+ nfs_mount_type = vfsp->vfc_typenum;
nfsrtt.pos = 0;
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
@@ -1170,10 +1173,10 @@ nfs_init()
* of the system can call us, if we are loadable.
*/
#ifndef NFS_NOSERVER
- lease_check = nfs_lease_check;
+ lease_check_hook = nqnfs_vop_lease_check;
#endif
lease_updatetime = nfs_lease_updatetime;
- vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */
+ vfsp->vfc_refcount++; /* make us non-unloadable */
#ifdef VFS_LKM
sysent[SYS_nfssvc].sy_narg = 2;
sysent[SYS_nfssvc].sy_call = nfssvc;
@@ -1212,7 +1215,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
register struct vattr *vap;
register struct nfs_fattr *fp;
register struct nfsnode *np;
- register struct nfsnodehashhead *nhpp;
register long t1;
caddr_t cp2;
int error = 0, rdev;
@@ -1222,6 +1224,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
struct timespec mtime;
struct vnode *nvp;
int v3 = NFS_ISV3(vp);
+ struct proc *p = curproc;
md = *mdp;
t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
@@ -1284,7 +1287,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* then release it here.
*/
if (vtyp != VREG && VOP_ISLOCKED(vp))
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
vp->v_type = vtyp;
if (vp->v_type == VFIFO) {
vp->v_op = fifo_nfsv2nodeop_p;
@@ -1295,8 +1298,11 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
if (nvp) {
/*
* Discard unneeded vnode, but save its nfsnode.
+ * Since the nfsnode does not have a lock, its
+ * vnode lock has to be carried over.
*/
- LIST_REMOVE(np, n_hash);
+ nvp->v_vnlock = vp->v_vnlock;
+ vp->v_vnlock = NULL;
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = spec_vnodeop_p;
@@ -1306,8 +1312,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* Reinitialize aliased node.
*/
np->n_vnode = nvp;
- nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
- LIST_INSERT_HEAD(nhpp, np, n_hash);
*vpp = vp = nvp;
}
}
@@ -1714,13 +1718,14 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int *rdonlyp;
int kerbflag;
{
+ struct proc *p = curproc; /* XXX */
register struct mount *mp;
register int i;
struct ucred *credanon;
int error, exflags;
*vpp = (struct vnode *)0;
- mp = getvfs(&fhp->fh_fsid);
+ mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
@@ -1751,7 +1756,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_object_create(*vpp);
if (!lockflag)
- VOP_UNLOCK(*vpp);
+ VOP_UNLOCK(*vpp, 0, p);
return (0);
}
@@ -1947,3 +1952,4 @@ nfsrv_object_create(struct vnode *vp) {
return vfs_object_create(vp, curproc, curproc?curproc->p_ucred:NULL, 1);
}
#endif /* NFS_NOSERVER */
+
diff --git a/sys/nfs/nfs_common.h b/sys/nfs/nfs_common.h
index ac1a159..cd37c59 100644
--- a/sys/nfs/nfs_common.h
+++ b/sys/nfs/nfs_common.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
+ * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
diff --git a/sys/nfs/nfs_node.c b/sys/nfs/nfs_node.c
index 2ddb4a6..8403f55 100644
--- a/sys/nfs/nfs_node.c
+++ b/sys/nfs/nfs_node.c
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_node.c 8.2 (Berkeley) 12/30/93
+ * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
* $FreeBSD$
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
@@ -108,7 +109,8 @@ nfs_nget(mntp, fhp, fhsize, npp)
int fhsize;
struct nfsnode **npp;
{
- register struct nfsnode *np;
+ struct proc *p = curproc; /* XXX */
+ struct nfsnode *np;
struct nfsnodehashhead *nhpp;
register struct vnode *vp;
struct vnode *nvp;
@@ -121,7 +123,7 @@ loop:
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
continue;
vp = NFSTOV(np);
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
*npp = np;
return(0);
@@ -178,7 +180,7 @@ loop:
/*
* Lock the new nfsnode.
*/
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (0);
}
@@ -187,6 +189,7 @@ int
nfs_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
register struct nfsnode *np;
@@ -213,6 +216,7 @@ nfs_inactive(ap)
}
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
NQNFSNONCACHE | NQNFSWRITE);
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -265,6 +269,7 @@ nfs_reclaim(ap)
return (0);
}
+#if 0
/*
* Lock an nfsnode
*/
@@ -355,6 +360,7 @@ nfs_islocked(ap)
{
return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
}
+#endif
/*
* Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
diff --git a/sys/nfs/nfs_nqlease.c b/sys/nfs/nfs_nqlease.c
index 2fa8360..1740b82 100644
--- a/sys/nfs/nfs_nqlease.c
+++ b/sys/nfs/nfs_nqlease.c
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_nqlease.c 8.3 (Berkeley) 1/4/94
+ * @(#)nfs_nqlease.c 8.9 (Berkeley) 5/20/95
* $FreeBSD$
*/
+
/*
* References:
* Cary G. Gray and David R. Cheriton, "Leases: An Efficient Fault-Tolerant
@@ -84,11 +85,8 @@ struct vop_lease_args;
static int nqsrv_cmpnam __P((struct nfssvc_sock *,struct mbuf *,
struct nqhost *));
-extern void nqnfs_lease_check __P((struct vnode *vp, struct proc *p,
- struct ucred *cred, int flag));
extern void nqnfs_lease_updatetime __P((int deltat));
static int nqnfs_vacated __P((struct vnode *vp, struct ucred *cred));
-extern int nqnfs_vop_lease_check __P((struct vop_lease_args *ap));
static void nqsrv_addhost __P((struct nqhost *lph, struct nfssvc_sock *slp,
struct mbuf *nam));
static void nqsrv_instimeq __P((struct nqlease *lp, u_long duration));
@@ -136,6 +134,7 @@ extern nfstype nfsv3_type[9];
extern struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
extern int nfsd_waiting;
extern struct nfsstats nfsstats;
+extern int nfs_mount_type;
#define TRUE 1
#define FALSE 0
@@ -349,7 +348,6 @@ nqnfs_lease_check(vp, p, cred, flag)
#endif /* NFS_NOSERVER */
-#ifdef HAS_VOPLEASE
int
nqnfs_vop_lease_check(ap)
struct vop_lease_args /* {
@@ -367,7 +365,6 @@ nqnfs_vop_lease_check(ap)
NQLOCALSLP, ap->a_p, (struct mbuf *)0, &cache, &frev, ap->a_cred);
return (0);
}
-#endif
/*
* Add a host to an nqhost structure for a lease.
@@ -1090,7 +1087,7 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, p)
vp = NFSTOV(np);
vpid = vp->v_id;
if (np->n_expiry < time.tv_sec) {
- if (vget(vp, 1) == 0) {
+ if (vget(vp, LK_EXCLUSIVE, p) == 0) {
nmp->nm_inprog = vp;
if (vpid == vp->v_id) {
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
@@ -1115,7 +1112,7 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, p)
} else if ((np->n_expiry - NQ_RENEWAL) < time.tv_sec) {
if ((np->n_flag & (NQNFSWRITE | NQNFSNONCACHE))
== NQNFSWRITE && vp->v_dirtyblkhd.lh_first &&
- vget(vp, 1) == 0) {
+ vget(vp, LK_EXCLUSIVE, p) == 0) {
nmp->nm_inprog = vp;
if (vpid == vp->v_id &&
nqnfs_getlease(vp, ND_WRITE, cred, p)==0)
@@ -1179,9 +1176,10 @@ void
nqnfs_lease_updatetime(deltat)
register int deltat;
{
- register struct nqlease *lp;
- register struct nfsnode *np;
- struct mount *mp;
+ struct proc *p = curproc; /* XXX */
+ struct nqlease *lp;
+ struct nfsnode *np;
+ struct mount *mp, *nxtmp;
struct nfsmount *nmp;
int s;
@@ -1197,13 +1195,13 @@ nqnfs_lease_updatetime(deltat)
* Search the mount list for all nqnfs mounts and do their timer
* queues.
*/
- for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
- mp = mp->mnt_list.cqe_next) {
-#ifdef __NetBSD__
- if (!strcmp(&mp->mnt_stat.f_fstypename[0], MOUNT_NFS)) {
-#else
- if (mp->mnt_stat.f_fsid.val[1] == MOUNT_NFS) {
-#endif
+ simple_lock(&mountlist_slock);
+ for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nxtmp) {
+ if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+ nxtmp = mp->mnt_list.cqe_next;
+ continue;
+ }
+ if (mp->mnt_stat.f_type == nfs_mount_type) {
nmp = VFSTONFS(mp);
if (nmp->nm_flag & NFSMNT_NQNFS) {
for (np = nmp->nm_timerhead.cqh_first;
@@ -1213,7 +1211,11 @@ nqnfs_lease_updatetime(deltat)
}
}
}
+ simple_lock(&mountlist_slock);
+ nxtmp = mp->mnt_list.cqe_next;
+ vfs_unbusy(mp, p);
}
+ simple_unlock(&mountlist_slock);
}
/*
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c
index 3946778..28a705a 100644
--- a/sys/nfs/nfs_serv.c
+++ b/sys/nfs/nfs_serv.c
@@ -1723,7 +1723,7 @@ nfsrv_remove(nfsd, slp, procp, mrq)
}
out:
if (!error) {
- vnode_pager_uncache(vp);
+ vnode_pager_uncache(vp, procp);
nqsrv_getl(nd.ni_dvp, ND_WRITE);
nqsrv_getl(vp, ND_WRITE);
@@ -1900,7 +1900,7 @@ out:
nqsrv_getl(tdvp, ND_WRITE);
if (tvp) {
nqsrv_getl(tvp, ND_WRITE);
- (void) vnode_pager_uncache(tvp);
+ (void) vnode_pager_uncache(tvp, procp);
}
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
@@ -2027,11 +2027,7 @@ out:
if (!error) {
nqsrv_getl(vp, ND_WRITE);
nqsrv_getl(xp, ND_WRITE);
-#if defined(__NetBSD__) || defined(__FreeBSD__)
- error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
-#else
error = VOP_LINK(vp, nd.ni_dvp, &nd.ni_cnd);
-#endif
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
@@ -2479,7 +2475,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
int v3 = (nfsd->nd_flag & ND_NFSV3);
u_quad_t frev, off, toff, verf;
- u_int *cookies = NULL, *cookiep;
+ u_long *cookies = NULL, *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
@@ -2520,7 +2516,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
nfsm_srvpostop_attr(getret, &at);
return (0);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
#ifdef __NetBSD__
ncookies = siz / (5 * NFSX_UNSIGNED); /*7 for V3, but it's an est. so*/
@@ -2538,16 +2534,12 @@ again:
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
eofflag = 0;
- VOP_LOCK(vp);
-#ifndef __NetBSD__
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, procp);
if (cookies) {
free((caddr_t)cookies, M_TEMP);
cookies = NULL;
}
error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
-#else
- error = VOP_READDIR(vp, &io, cred, &eofflag, cookies, ncookies);
-#endif
off = (off_t)io.uio_offset;
if (!cookies && !error)
error = NFSERR_PERM;
@@ -2556,7 +2548,7 @@ again:
if (!error)
error = getret;
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
if (error) {
vrele(vp);
free((caddr_t)rbuf, M_TEMP);
@@ -2751,7 +2743,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
u_quad_t frev, off, toff, verf;
- u_int *cookies = NULL, *cookiep;
+ u_long *cookies = NULL, *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
@@ -2787,7 +2779,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
nfsm_srvpostop_attr(getret, &at);
return (0);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
#ifdef __NetBSD__
ncookies = siz / (7 * NFSX_UNSIGNED);
@@ -2805,19 +2797,15 @@ again:
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
eofflag = 0;
- VOP_LOCK(vp);
-#ifndef __NetBSD__
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, procp);
if (cookies) {
free((caddr_t)cookies, M_TEMP);
cookies = NULL;
}
error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
-#else
- error = VOP_READDIR(vp, &io, cred, &eofflag, cookies, ncookies);
-#endif
off = (u_quad_t)io.uio_offset;
getret = VOP_GETATTR(vp, &at, cred, procp);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
if (!cookies && !error)
error = NFSERR_PERM;
if (!error)
diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c
index addd59f..ed16333 100644
--- a/sys/nfs/nfs_socket.c
+++ b/sys/nfs/nfs_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1991, 1993
+ * Copyright (c) 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
+ * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
* $FreeBSD$
*/
@@ -1925,6 +1925,9 @@ nfs_getreq(nd, nfsd, has_header)
struct mbuf *mrep, *md;
register struct nfsuid *nuidp;
struct timeval tvin, tvout;
+#if 0 /* until encrypted keys are implemented */
+ NFSKERBKEYSCHED_T keys; /* stores key schedule */
+#endif
mrep = nd->nd_mrep;
md = nd->nd_md;
diff --git a/sys/nfs/nfs_srvcache.c b/sys/nfs/nfs_srvcache.c
index 835ec06..efff221 100644
--- a/sys/nfs/nfs_srvcache.c
+++ b/sys/nfs/nfs_srvcache.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_srvcache.c 8.1 (Berkeley) 6/10/93
+ * @(#)nfs_srvcache.c 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c
index 1feadd6..5f83bf5 100644
--- a/sys/nfs/nfs_subs.c
+++ b/sys/nfs/nfs_subs.c
@@ -100,6 +100,7 @@ enum vtype nv3tov_type[8]= {
VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
};
+int nfs_mount_type;
int nfs_ticks;
struct nfs_reqq nfs_reqq;
@@ -1093,7 +1094,8 @@ nfsm_strtmbuf(mb, bpos, cp, siz)
* Called once to initialize data structures...
*/
int
-nfs_init()
+nfs_init(vfsp)
+ struct vfsconf *vfsp;
{
register int i;
@@ -1116,6 +1118,7 @@ nfs_init()
printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
printf("Try unionizing the nu_nickname and nu_flag fields\n");
}
+ nfs_mount_type = vfsp->vfc_typenum;
nfsrtt.pos = 0;
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
@@ -1170,10 +1173,10 @@ nfs_init()
* of the system can call us, if we are loadable.
*/
#ifndef NFS_NOSERVER
- lease_check = nfs_lease_check;
+ lease_check_hook = nqnfs_vop_lease_check;
#endif
lease_updatetime = nfs_lease_updatetime;
- vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */
+ vfsp->vfc_refcount++; /* make us non-unloadable */
#ifdef VFS_LKM
sysent[SYS_nfssvc].sy_narg = 2;
sysent[SYS_nfssvc].sy_call = nfssvc;
@@ -1212,7 +1215,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
register struct vattr *vap;
register struct nfs_fattr *fp;
register struct nfsnode *np;
- register struct nfsnodehashhead *nhpp;
register long t1;
caddr_t cp2;
int error = 0, rdev;
@@ -1222,6 +1224,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
struct timespec mtime;
struct vnode *nvp;
int v3 = NFS_ISV3(vp);
+ struct proc *p = curproc;
md = *mdp;
t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
@@ -1284,7 +1287,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* then release it here.
*/
if (vtyp != VREG && VOP_ISLOCKED(vp))
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
vp->v_type = vtyp;
if (vp->v_type == VFIFO) {
vp->v_op = fifo_nfsv2nodeop_p;
@@ -1295,8 +1298,11 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
if (nvp) {
/*
* Discard unneeded vnode, but save its nfsnode.
+ * Since the nfsnode does not have a lock, its
+ * vnode lock has to be carried over.
*/
- LIST_REMOVE(np, n_hash);
+ nvp->v_vnlock = vp->v_vnlock;
+ vp->v_vnlock = NULL;
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = spec_vnodeop_p;
@@ -1306,8 +1312,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* Reinitialize aliased node.
*/
np->n_vnode = nvp;
- nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
- LIST_INSERT_HEAD(nhpp, np, n_hash);
*vpp = vp = nvp;
}
}
@@ -1714,13 +1718,14 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int *rdonlyp;
int kerbflag;
{
+ struct proc *p = curproc; /* XXX */
register struct mount *mp;
register int i;
struct ucred *credanon;
int error, exflags;
*vpp = (struct vnode *)0;
- mp = getvfs(&fhp->fh_fsid);
+ mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
@@ -1751,7 +1756,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_object_create(*vpp);
if (!lockflag)
- VOP_UNLOCK(*vpp);
+ VOP_UNLOCK(*vpp, 0, p);
return (0);
}
@@ -1947,3 +1952,4 @@ nfsrv_object_create(struct vnode *vp) {
return vfs_object_create(vp, curproc, curproc?curproc->p_ucred:NULL, 1);
}
#endif /* NFS_NOSERVER */
+
diff --git a/sys/nfs/nfs_syscalls.c b/sys/nfs/nfs_syscalls.c
index 734fe79..24d4bd6 100644
--- a/sys/nfs/nfs_syscalls.c
+++ b/sys/nfs/nfs_syscalls.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
+ * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
* $FreeBSD$
*/
@@ -97,7 +97,6 @@ static int nfssvc_iod __P((struct proc *));
static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
-
#ifndef NFS_NOSERVER
int nfsd_waiting = 0;
static struct nfsdrt nfsdrt;
@@ -1051,6 +1050,7 @@ nfsmout:
}
#ifndef NFS_NOSERVER
+
/*
* Derefence a server socket structure. If it has no more references and
* is no longer valid, you can throw it away.
diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c
index 937c2d5..06457f1 100644
--- a/sys/nfs/nfs_vfsops.c
+++ b/sys/nfs/nfs_vfsops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94
+ * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -121,7 +121,7 @@ static struct vfsops nfs_vfsops = {
nfs_vget,
nfs_fhtovp,
nfs_vptofh,
- nfs_init,
+ nfs_init
};
VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
@@ -152,8 +152,10 @@ SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
void nfsargs_ntoh __P((struct nfs_args *));
-static struct mount *nfs_mountdiskless __P((char *, char *, int,
- struct sockaddr_in *, struct nfs_args *, register struct vnode **));
+static int nfs_mountdiskless __P((char *, char *, int,
+ struct sockaddr_in *, struct nfs_args *,
+ struct proc *, struct vnode **,
+ struct mount **));
static int nfs_iosize(nmp)
struct nfsmount* nmp;
@@ -329,8 +331,8 @@ nfs_fsinfo(nmp, vp, cred, p)
int
nfs_mountroot()
{
- register struct mount *mp;
- register struct nfs_diskless *nd = &nfs_diskless;
+ struct mount *mp, *swap_mp;
+ struct nfs_diskless *nd = &nfs_diskless;
struct socket *so;
struct vnode *vp;
struct proc *p = curproc; /* XXX */
@@ -406,6 +408,7 @@ nfs_mountroot()
panic("nfs_mountroot: RTM_ADD: %d", error);
}
+ swap_mp = NULL;
if (nd->swap_nblks) {
/* Convert to DEV_BSIZE instead of Kilobyte */
@@ -426,8 +429,10 @@ nfs_mountroot()
(l >> 24) & 0xff, (l >> 16) & 0xff,
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam);
printf("NFS SWAP: %s\n",buf);
- (void) nfs_mountdiskless(buf, "/swap", 0,
- &nd->swap_saddr, &nd->swap_args, &vp);
+ if (error = nfs_mountdiskless(buf, "/swap", 0,
+ &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp))
+ return (error);
+ vfs_unbusy(swap_mp, p);
VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size =
nd->swap_nblks * DEV_BSIZE ;
@@ -455,16 +460,22 @@ nfs_mountroot()
(l >> 24) & 0xff, (l >> 16) & 0xff,
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
printf("NFS ROOT: %s\n",buf);
- mp = nfs_mountdiskless(buf, "/", MNT_RDONLY,
- &nd->root_saddr, &nd->root_args, &vp);
+ if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
+ &nd->root_saddr, &nd->root_args, p, &vp, &mp)) {
+ if (swap_mp) {
+ mp->mnt_vfc->vfc_refcount--;
+ free(swap_mp, M_MOUNT);
+ }
+ return (error);
+ }
- if (vfs_lock(mp))
- panic("nfs_mountroot: vfs_lock");
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
mp->mnt_flag |= MNT_ROOTFS;
mp->mnt_vnodecovered = NULLVP;
- vfs_unlock(mp);
rootvp = vp;
+ vfs_unbusy(mp, p);
/*
* This is not really an nfs issue, but it is much easier to
@@ -483,39 +494,65 @@ nfs_mountroot()
/*
* Internal version of mount system call for diskless setup.
*/
-static struct mount *
-nfs_mountdiskless(path, which, mountflag, sin, args, vpp)
+static int
+nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp)
char *path;
char *which;
int mountflag;
struct sockaddr_in *sin;
struct nfs_args *args;
- register struct vnode **vpp;
+ struct proc *p;
+ struct vnode **vpp;
+ struct mount **mpp;
{
- register struct mount *mp;
- register struct mbuf *m;
- register int error;
-
- mp = (struct mount *)malloc((u_long)sizeof(struct mount),
- M_MOUNT, M_NOWAIT);
- if (mp == NULL)
- panic("nfs_mountroot: %s mount malloc", which);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = &nfs_vfsops;
- mp->mnt_flag = mountflag;
+ struct mount *mp;
+ struct mbuf *m;
+ int error;
- MGET(m, MT_SONAME, M_DONTWAIT);
- if (m == NULL)
- panic("nfs_mountroot: %s mount mbuf", which);
+ if (error = vfs_rootmountalloc("nfs", path, &mp)) {
+ printf("nfs_mountroot: NFS not configured");
+ return (error);
+ }
+ mp->mnt_flag = mountflag;
+ MGET(m, MT_SONAME, M_WAITOK);
bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len);
m->m_len = sin->sin_len;
- error = mountnfs(args, mp, m, which, path, vpp);
- if (error)
- panic("nfs_mountroot: mount %s on %s: %d", path, which, error);
-
- return (mp);
+ if (error = mountnfs(args, mp, m, which, path, vpp)) {
+ printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
+ free(mp, M_MOUNT);
+ return (error);
+ }
+ (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
+ *mpp = mp;
+ return (0);
}
+#ifdef COMPAT_PRELITE2
+/*
+ * Old arguments to mount NFS
+ */
+struct onfs_args {
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+#endif
/*
* VFS Operations.
@@ -546,6 +583,39 @@ nfs_mount(mp, path, data, ndp, p)
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
+ if (args.version != NFS_ARGSVERSION) {
+#ifdef COMPAT_PRELITE2
+ /*
+ * If the argument version is unknown, then assume the
+ * caller is a pre-lite2 4.4BSD client and convert its
+ * arguments.
+ */
+ struct onfs_args oargs;
+ error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
+ if (error)
+ return (error);
+ args.version = NFS_ARGSVERSION;
+ args.addr = oargs.addr;
+ args.addrlen = oargs.addrlen;
+ args.sotype = oargs.sotype;
+ args.proto = oargs.proto;
+ args.fh = oargs.fh;
+ args.fhsize = oargs.fhsize;
+ args.flags = oargs.flags;
+ args.wsize = oargs.wsize;
+ args.rsize = oargs.rsize;
+ args.readdirsize = oargs.readdirsize;
+ args.timeo = oargs.timeo;
+ args.retrans = oargs.retrans;
+ args.maxgrouplist = oargs.maxgrouplist;
+ args.readahead = oargs.readahead;
+ args.leaseterm = oargs.leaseterm;
+ args.deadthresh = oargs.deadthresh;
+ args.hostname = oargs.hostname;
+#else /* COMPAT_PRELITE2 */
+ return (EPROGMISMATCH);
+#endif /* COMPAT_PRELITE2 */
+ }
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
if (error)
return (error);
@@ -595,7 +665,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
- getnewfsid(mp, MOUNT_NFS);
+ vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
nmp->nm_flag = argp->flags;
if (nmp->nm_flag & NFSMNT_NQNFS)
@@ -619,15 +689,6 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
nmp->nm_inprog = NULLVP;
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
-#ifdef __NetBSD__
-#ifdef COMPAT_09
- mp->mnt_stat.f_type = 2;
-#else
- mp->mnt_stat.f_type = 0;
-#endif
-#else
- mp->mnt_stat.f_type = MOUNT_NFS;
-#endif
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
@@ -741,7 +802,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
/*
* Lose the lock but keep the ref.
*/
- VOP_UNLOCK(*vpp);
+ VOP_UNLOCK(*vpp, 0, curproc);
return (0);
bad:
@@ -765,11 +826,8 @@ nfs_unmount(mp, mntflags, p)
struct vnode *vp;
int error, flags = 0;
- if (mntflags & MNT_FORCE) {
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
nmp = VFSTONFS(mp);
/*
* Goes something like this..
@@ -846,7 +904,7 @@ nfs_root(mp, vpp)
if (error)
return (error);
vp = NFSTOV(np);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curproc);
if (vp->v_type == VNON)
vp->v_type = VDIR;
vp->v_flag = VROOT;
@@ -885,7 +943,7 @@ loop:
goto loop;
if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL)
continue;
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
error = VOP_FSYNC(vp, cred, waitfor, p);
if (error)
@@ -969,4 +1027,3 @@ nfs_quotactl(mp, cmd, uid, arg, p)
return (EOPNOTSUPP);
}
-
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
index b8ff396..905bb22 100644
--- a/sys/nfs/nfs_vnops.c
+++ b/sys/nfs/nfs_vnops.c
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_vnops.c 8.5 (Berkeley) 2/13/94
+ * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
* $FreeBSD$
*/
+
/*
* vnode op calls for Sun NFS version 2 and 3
*/
@@ -151,14 +152,10 @@ static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)nfs_read }, /* read */
{ &vop_write_desc, (vop_t *)nfs_write }, /* write */
-#ifdef HAS_VOPLEASE
{ &vop_lease_desc, (vop_t *)nfs_lease_check }, /* lease */
-#endif
{ &vop_ioctl_desc, (vop_t *)nfs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)nfs_select }, /* select */
-#ifdef HAS_VOPREVOKE
{ &vop_revoke_desc, (vop_t *)nfs_revoke }, /* revoke */
-#endif
{ &vop_mmap_desc, (vop_t *)nfs_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)nfs_seek }, /* seek */
@@ -212,14 +209,10 @@ static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)nfsspec_read }, /* read */
{ &vop_write_desc, (vop_t *)nfsspec_write }, /* write */
-#ifdef HAS_VOPLEASE
{ &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
-#endif
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
-#ifdef HAS_VOPREVOKE
{ &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
-#endif
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
@@ -270,14 +263,10 @@ static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)nfsfifo_read }, /* read */
{ &vop_write_desc, (vop_t *)nfsfifo_write }, /* write */
-#ifdef HAS_VOPLEASE
{ &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
-#endif
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
-#ifdef HAS_VOPREVOKE
{ &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
-#endif
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
@@ -469,7 +458,7 @@ nfs_open(ap)
if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
ap->a_p, 1)) == EINTR)
return (error);
- (void) vnode_pager_uncache(vp);
+ (void) vnode_pager_uncache(vp, ap->a_p);
np->n_brev = np->n_lrev;
}
}
@@ -588,7 +577,7 @@ nfs_getattr(ap)
int error = 0;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
int v3 = NFS_ISV3(vp);
-
+
/*
* Update local times for special files.
*/
@@ -634,7 +623,7 @@ nfs_setattr(ap)
/*
* Disallow write attempts if the filesystem is mounted read-only.
*/
- if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
+ 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))
@@ -645,6 +634,8 @@ nfs_setattr(ap)
return (EISDIR);
case VCHR:
case VBLK:
+ case VSOCK:
+ case VFIFO:
if (vap->va_mtime.tv_sec == VNOVAL &&
vap->va_atime.tv_sec == VNOVAL &&
vap->va_mode == (u_short)VNOVAL &&
@@ -660,20 +651,22 @@ nfs_setattr(ap)
*/
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
- if (vap->va_size == 0)
+ if (np->n_flag & NMODIFIED) {
+ if (vap->va_size == 0)
error = nfs_vinvalbuf(vp, 0,
ap->a_cred, ap->a_p, 1);
- else
+ else
error = nfs_vinvalbuf(vp, V_SAVE,
ap->a_cred, ap->a_p, 1);
- if (error)
+ if (error)
return (error);
+ }
tsize = np->n_size;
np->n_size = np->n_vattr.va_size = vap->va_size;
vnode_pager_setsize(vp, (u_long)np->n_size);
};
} else if ((vap->va_mtime.tv_sec != VNOVAL ||
- vap->va_atime.tv_sec != VNOVAL) &&
+ vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) &&
vp->v_type == VREG &&
(error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
ap->a_p, 1)) == EINTR)
@@ -826,6 +819,7 @@ nfs_lookup(ap)
struct nfsnode *np;
int lockparent, wantparent, error = 0, attrflag, fhsize;
int v3 = NFS_ISV3(dvp);
+ struct proc *p = cnp->cn_proc;
if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
@@ -851,18 +845,18 @@ nfs_lookup(ap)
VREF(newvp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(dvp);
- error = vget(newvp, 1);
+ VOP_UNLOCK(dvp, 0, p);
+ error = vget(newvp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(dvp);
+ error = vn_lock(dvp, LK_EXCLUSIVE, p);
} else {
- error = vget(newvp, 1);
+ error = vget(newvp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
if (!error) {
if (vpid == newvp->v_id) {
- if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)
+ if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p)
&& vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
nfsstats.lookupcache_hits++;
if (cnp->cn_nameiop != LOOKUP &&
@@ -874,9 +868,9 @@ nfs_lookup(ap)
}
vput(newvp);
if (lockparent && dvp != newvp && (flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
- error = VOP_LOCK(dvp);
+ error = vn_lock(dvp, LK_EXCLUSIVE, p);
if (error)
return (error);
*vpp = NULLVP;
@@ -920,20 +914,20 @@ nfs_lookup(ap)
m_freem(mrep);
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
return (0);
}
if (flags & ISDOTDOT) {
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
if (error) {
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE + LK_RETRY, p);
return (error);
}
newvp = NFSTOV(np);
if (lockparent && (flags & ISLASTCN) &&
- (error = VOP_LOCK(dvp))) {
+ (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
vput(newvp);
return (error);
}
@@ -946,7 +940,7 @@ nfs_lookup(ap)
return (error);
}
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
newvp = NFSTOV(np);
}
if (v3) {
@@ -969,7 +963,7 @@ nfs_lookup(ap)
if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
(flags & ISLASTCN) && error == ENOENT) {
if (!lockparent)
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
if (dvp->v_mount->mnt_flag & MNT_RDONLY)
error = EROFS;
else
@@ -2110,7 +2104,7 @@ nfs_readdirrpc(vp, uiop, cred)
}
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
more_dirs = fxdr_unsigned(int, *tl);
-
+
/* loop thru the dir entries, doctoring them to 4bsd form */
while (more_dirs && bigenough) {
if (v3) {
@@ -2923,6 +2917,9 @@ loop:
}
}
if (vp->v_dirtyblkhd.lh_first && commit) {
+#ifndef DIAGNOSTIC
+ vprint("nfs_fsync: dirty", vp);
+#endif
goto loop;
}
}
@@ -3131,7 +3128,7 @@ nfs_writebp(bp, force)
* an actual write will have to be scheduled via. VOP_STRATEGY().
* If B_WRITEINPROG is already set, then push it with a write anyhow.
*/
- if (oldflags & (B_NEEDCOMMIT | B_WRITEINPROG) == B_NEEDCOMMIT) {
+ if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
bp->b_flags |= B_WRITEINPROG;
retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
@@ -3205,7 +3202,7 @@ nfsspec_access(ap)
if (cred->cr_uid == 0)
return (0);
vap = &vattr;
- error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p);
+ error = VOP_GETATTR(vp, vap, cred, ap->a_p);
if (error)
return (error);
/*
diff --git a/sys/nfs/nfsdiskless.h b/sys/nfs/nfsdiskless.h
index 117548b..4777818 100644
--- a/sys/nfs/nfsdiskless.h
+++ b/sys/nfs/nfsdiskless.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsdiskless.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfsdiskless.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSDISKLESS_H_
#define _NFS_NFSDISKLESS_H_
@@ -46,8 +47,8 @@
* vnodes plus do a partial ifconfig(8) and route(8) so that the critical net
* interface can communicate with the server.
* The primary bootstrap is expected to fill in the appropriate fields before
- * starting the kernel. Whether or not the swap area is nfs mounted is determined
- * by the value in swdevt[0]. (equal to NODEV --> swap over nfs)
+ * starting the kernel. Whether or not the swap area is nfs mounted is
+ * determined by the value in swdevt[0]. (equal to NODEV --> swap over nfs)
* Currently only works for AF_INET protocols.
* NB: All fields are stored in net byte order to avoid hassles with
* client/server byte ordering differences.
diff --git a/sys/nfs/nfsm_subs.h b/sys/nfs/nfsm_subs.h
index ac1a159..cd37c59 100644
--- a/sys/nfs/nfsm_subs.h
+++ b/sys/nfs/nfsm_subs.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
+ * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
diff --git a/sys/nfs/nfsmount.h b/sys/nfs/nfsmount.h
index ea48bca..1545ada 100644
--- a/sys/nfs/nfsmount.h
+++ b/sys/nfs/nfsmount.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsmount.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfsmount.h 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSMOUNT_H_
#define _NFS_NFSMOUNT_H_
diff --git a/sys/nfs/nfsnode.h b/sys/nfs/nfsnode.h
index 4408fe2..e52a3dd 100644
--- a/sys/nfs/nfsnode.h
+++ b/sys/nfs/nfsnode.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsnode.h 8.4 (Berkeley) 2/13/94
+ * @(#)nfsnode.h 8.9 (Berkeley) 5/14/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSNODE_H_
#define _NFS_NFSNODE_H_
@@ -161,26 +162,16 @@ extern vop_t **spec_nfsv2nodeop_p;
* Prototypes for NFS vnode operations
*/
int nfs_write __P((struct vop_write_args *));
-#ifdef HAS_VOPLEASE
#define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
-#define nqnfs_vop_lease_check lease_check
-#else
-#ifdef __FreeBSD__
-#define nqnfs_lease_check nfs_lease_check
-#else
-#define nqnfs_lease_check lease_check
-#endif
-#endif
-#ifdef HAS_VOPREVOKE
+int nqnfs_vop_lease_check __P((struct vop_lease_args *));
#define nfs_revoke vop_revoke
-#endif
#define nfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
int nfs_abortop __P((struct vop_abortop_args *));
int nfs_inactive __P((struct vop_inactive_args *));
int nfs_reclaim __P((struct vop_reclaim_args *));
-int nfs_lock __P((struct vop_lock_args *));
-int nfs_unlock __P((struct vop_unlock_args *));
-int nfs_islocked __P((struct vop_islocked_args *));
+#define nfs_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define nfs_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
+#define nfs_islocked ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
#define nfs_reallocblks \
((int (*) __P((struct vop_reallocblks_args *)))eopnotsupp)
@@ -190,11 +181,7 @@ int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
void nfs_invaldir __P((struct vnode *));
-#ifdef __FreeBSD__
#define nqnfs_lease_updatetime nfs_lease_updatetime
-#else
-#define nqnfs_lease_updatetime lease_updatetime
-#endif
#endif /* KERNEL */
diff --git a/sys/nfs/nfsrtt.h b/sys/nfs/nfsrtt.h
index 291427f..a67b6c9 100644
--- a/sys/nfs/nfsrtt.h
+++ b/sys/nfs/nfsrtt.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsrtt.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfsrtt.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSRTT_H_
#define _NFS_NFSRTT_H_
diff --git a/sys/nfs/nfsrvcache.h b/sys/nfs/nfsrvcache.h
index 38c9657..2cfa694 100644
--- a/sys/nfs/nfsrvcache.h
+++ b/sys/nfs/nfsrvcache.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsrvcache.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfsrvcache.h 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSRVCACHE_H_
#define _NFS_NFSRVCACHE_H_
diff --git a/sys/nfs/nqnfs.h b/sys/nfs/nqnfs.h
index af55a23..91942b2 100644
--- a/sys/nfs/nqnfs.h
+++ b/sys/nfs/nqnfs.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nqnfs.h 8.1 (Berkeley) 6/10/93
+ * @(#)nqnfs.h 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NQNFS_H_
#define _NFS_NQNFS_H_
diff --git a/sys/nfs/rpcv2.h b/sys/nfs/rpcv2.h
index 418c80d..afe7972 100644
--- a/sys/nfs/rpcv2.h
+++ b/sys/nfs/rpcv2.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)rpcv2.h 8.1 (Berkeley) 6/10/93
+ * @(#)rpcv2.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_RPCV2_H_
#define _NFS_RPCV2_H_
diff --git a/sys/nfs/xdr_subs.h b/sys/nfs/xdr_subs.h
index 46016f2..cbaec88 100644
--- a/sys/nfs/xdr_subs.h
+++ b/sys/nfs/xdr_subs.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)xdr_subs.h 8.1 (Berkeley) 6/10/93
+ * @(#)xdr_subs.h 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_XDR_SUBS_H_
#define _NFS_XDR_SUBS_H_
diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h
index db41859..73a018c 100644
--- a/sys/nfsclient/nfs.h
+++ b/sys/nfsclient/nfs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,19 +33,19 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $FreeBSD$
*/
#ifndef _NFS_NFS_H_
#define _NFS_NFS_H_
-#include <nfs/rpcv2.h>
-
/*
* Tunable constants for nfs
*/
+#ifdef KERNEL
+
#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
@@ -69,7 +69,7 @@
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
+#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
@@ -89,30 +89,9 @@
/*
* XXX
- * sys/buf.h should be edited to change B_APPENDWRITE --> B_NEEDCOMMIT, but
- * until then...
- * Same goes for sys/malloc.h, which needs M_NFSDIROFF,
- * M_NFSRVDESC and M_NFSBIGFH added.
- * The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
- * exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
-#ifndef B_NEEDCOMMIT
-#define B_NEEDCOMMIT B_APPENDWRITE
-#endif
-#ifndef M_NFSRVDESC
-#define M_NFSRVDESC M_TEMP
-#endif
-#ifndef M_NFSDIROFF
-#define M_NFSDIROFF M_TEMP
-#endif
-#ifndef M_NFSBIGFH
-#define M_NFSBIGFH M_TEMP
-#endif
-#ifndef VA_EXCLUSIVE
-#define VA_EXCLUSIVE 0
-#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
@@ -120,20 +99,6 @@
#endif
/*
- * These ifdefs try to handle the differences between the various 4.4BSD-Lite
- * based vfs interfaces.
- * btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
- * differentiate between NetBSD-1.0 and NetBSD-current, so..
- * I also don't know about BSDi's 2.0 release.
- */
-#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPLEASE 1
-#endif
-#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPREVOKE 1
-#endif
-
-/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
@@ -164,13 +129,114 @@
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
+#endif /* KERNEL */
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
+/*
+ * Arguments to mount NFS
+ */
+#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
+struct nfs_args {
+ int version; /* args structure version number */
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
*/
struct nfsd_args {
int sock; /* Socket to serve */
- caddr_t name; /* Client address for connection based sockets */
+ caddr_t name; /* Client addr for connection based sockets */
int namelen; /* Length of name */
};
@@ -200,6 +266,10 @@ struct nfsd_cargs {
};
/*
+ * XXX to allow amd to include nfs.h without nfsproto.h
+ */
+#ifdef NFS_NPROCS
+/*
* Stats structure
*/
struct nfsstats {
@@ -237,6 +307,7 @@ struct nfsstats {
int srvnqnfs_getleases;
int srvvop_writes;
};
+#endif
/*
* Flags for nfssvc() system call.
@@ -267,7 +338,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
-#if defined(KERNEL) || defined(_KERNEL)
+#ifdef KERNEL
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@@ -482,6 +553,8 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
+
+int nfs_init __P((struct vfsconf *vfsp));
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
@@ -516,14 +589,12 @@ int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
u_long nfs_hash __P((nfsfh_t *,int));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
-void nfsrv_cleancache __P((void));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
-int nfs_init __P((void));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
+void nfsrv_cleancache __P((void));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *nmp));
+void nfs_disconnect __P((struct nfsmount *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
@@ -531,7 +602,6 @@ int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_writebp __P((struct buf *,int));
@@ -594,8 +664,8 @@ int nfsrv_symlink __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
-
-
+void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void nfsrv_slpderef __P((struct nfssvc_sock *slp));
#endif /* KERNEL */
#endif
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index d67a3c0..0f636b0 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_bio.c 8.5 (Berkeley) 1/4/94
+ * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/resourcevar.h>
@@ -66,19 +67,6 @@ extern int nfs_numasync;
extern struct nfsstats nfsstats;
/*
- * Ifdefs for FreeBSD-current's merged VM/buffer cache. It is unfortunate
- * that this isn't done inside getblk() and brelse() so these calls
- * wouldn't need to be here.
- */
-#ifdef B_VMIO
-#define vnode_pager_uncache(vp)
-#else
-#define vfs_busy_pages(bp, f)
-#define vfs_unbusy_pages(bp)
-#define vfs_dirty_pages(bp)
-#endif
-
-/*
* Vnode op for read using bio
* Any similarity to readip() is purely coincidental
*/
@@ -195,7 +183,7 @@ nfs_bioread(vp, uio, ioflag, cred)
case VDIR:
break;
default:
- printf(" NQNFSNONCACHE: type %x unexpected\n",
+ printf(" NQNFSNONCACHE: type %x unexpected\n",
vp->v_type);
};
}
@@ -225,9 +213,8 @@ nfs_bioread(vp, uio, ioflag, cred)
vfs_unbusy_pages(rabp);
brelse(rabp);
}
- } else {
+ } else
brelse(rabp);
- }
}
}
}
@@ -270,6 +257,7 @@ again:
if (not_readin && n > 0) {
if (on < bp->b_validoff || (on + n) > bp->b_validend) {
bp->b_flags |= B_NOCACHE;
+ bp->b_flags |= B_INVAFTERWRITE;
if (bp->b_dirtyend > 0) {
if ((bp->b_flags & B_DELWRI) == 0)
panic("nfsbioread");
@@ -475,10 +463,6 @@ nfs_write(ap)
*/
biosize = vp->v_mount->mnt_stat.f_iosize;
do {
-
- /*
- * XXX make sure we aren't cached in the VM page cache
- */
/*
* Check for a valid write lease.
*/
diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c
index 734fe79..24d4bd6 100644
--- a/sys/nfsclient/nfs_nfsiod.c
+++ b/sys/nfsclient/nfs_nfsiod.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
+ * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
* $FreeBSD$
*/
@@ -97,7 +97,6 @@ static int nfssvc_iod __P((struct proc *));
static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
-
#ifndef NFS_NOSERVER
int nfsd_waiting = 0;
static struct nfsdrt nfsdrt;
@@ -1051,6 +1050,7 @@ nfsmout:
}
#ifndef NFS_NOSERVER
+
/*
* Derefence a server socket structure. If it has no more references and
* is no longer valid, you can throw it away.
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
index 2ddb4a6..8403f55 100644
--- a/sys/nfsclient/nfs_node.c
+++ b/sys/nfsclient/nfs_node.c
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_node.c 8.2 (Berkeley) 12/30/93
+ * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95
* $FreeBSD$
*/
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
@@ -108,7 +109,8 @@ nfs_nget(mntp, fhp, fhsize, npp)
int fhsize;
struct nfsnode **npp;
{
- register struct nfsnode *np;
+ struct proc *p = curproc; /* XXX */
+ struct nfsnode *np;
struct nfsnodehashhead *nhpp;
register struct vnode *vp;
struct vnode *nvp;
@@ -121,7 +123,7 @@ loop:
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
continue;
vp = NFSTOV(np);
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
*npp = np;
return(0);
@@ -178,7 +180,7 @@ loop:
/*
* Lock the new nfsnode.
*/
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return (0);
}
@@ -187,6 +189,7 @@ int
nfs_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
register struct nfsnode *np;
@@ -213,6 +216,7 @@ nfs_inactive(ap)
}
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
NQNFSNONCACHE | NQNFSWRITE);
+ VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
return (0);
}
@@ -265,6 +269,7 @@ nfs_reclaim(ap)
return (0);
}
+#if 0
/*
* Lock an nfsnode
*/
@@ -355,6 +360,7 @@ nfs_islocked(ap)
{
return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
}
+#endif
/*
* Nfs abort op, called after namei() when a CREATE/DELETE isn't actually
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index addd59f..ed16333 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1991, 1993
+ * Copyright (c) 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
+ * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
* $FreeBSD$
*/
@@ -1925,6 +1925,9 @@ nfs_getreq(nd, nfsd, has_header)
struct mbuf *mrep, *md;
register struct nfsuid *nuidp;
struct timeval tvin, tvout;
+#if 0 /* until encrypted keys are implemented */
+ NFSKERBKEYSCHED_T keys; /* stores key schedule */
+#endif
mrep = nd->nd_mrep;
md = nd->nd_md;
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index 1feadd6..5f83bf5 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -100,6 +100,7 @@ enum vtype nv3tov_type[8]= {
VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
};
+int nfs_mount_type;
int nfs_ticks;
struct nfs_reqq nfs_reqq;
@@ -1093,7 +1094,8 @@ nfsm_strtmbuf(mb, bpos, cp, siz)
* Called once to initialize data structures...
*/
int
-nfs_init()
+nfs_init(vfsp)
+ struct vfsconf *vfsp;
{
register int i;
@@ -1116,6 +1118,7 @@ nfs_init()
printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
printf("Try unionizing the nu_nickname and nu_flag fields\n");
}
+ nfs_mount_type = vfsp->vfc_typenum;
nfsrtt.pos = 0;
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
@@ -1170,10 +1173,10 @@ nfs_init()
* of the system can call us, if we are loadable.
*/
#ifndef NFS_NOSERVER
- lease_check = nfs_lease_check;
+ lease_check_hook = nqnfs_vop_lease_check;
#endif
lease_updatetime = nfs_lease_updatetime;
- vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */
+ vfsp->vfc_refcount++; /* make us non-unloadable */
#ifdef VFS_LKM
sysent[SYS_nfssvc].sy_narg = 2;
sysent[SYS_nfssvc].sy_call = nfssvc;
@@ -1212,7 +1215,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
register struct vattr *vap;
register struct nfs_fattr *fp;
register struct nfsnode *np;
- register struct nfsnodehashhead *nhpp;
register long t1;
caddr_t cp2;
int error = 0, rdev;
@@ -1222,6 +1224,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
struct timespec mtime;
struct vnode *nvp;
int v3 = NFS_ISV3(vp);
+ struct proc *p = curproc;
md = *mdp;
t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
@@ -1284,7 +1287,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* then release it here.
*/
if (vtyp != VREG && VOP_ISLOCKED(vp))
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
vp->v_type = vtyp;
if (vp->v_type == VFIFO) {
vp->v_op = fifo_nfsv2nodeop_p;
@@ -1295,8 +1298,11 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
if (nvp) {
/*
* Discard unneeded vnode, but save its nfsnode.
+ * Since the nfsnode does not have a lock, its
+ * vnode lock has to be carried over.
*/
- LIST_REMOVE(np, n_hash);
+ nvp->v_vnlock = vp->v_vnlock;
+ vp->v_vnlock = NULL;
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = spec_vnodeop_p;
@@ -1306,8 +1312,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* Reinitialize aliased node.
*/
np->n_vnode = nvp;
- nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
- LIST_INSERT_HEAD(nhpp, np, n_hash);
*vpp = vp = nvp;
}
}
@@ -1714,13 +1718,14 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int *rdonlyp;
int kerbflag;
{
+ struct proc *p = curproc; /* XXX */
register struct mount *mp;
register int i;
struct ucred *credanon;
int error, exflags;
*vpp = (struct vnode *)0;
- mp = getvfs(&fhp->fh_fsid);
+ mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
@@ -1751,7 +1756,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_object_create(*vpp);
if (!lockflag)
- VOP_UNLOCK(*vpp);
+ VOP_UNLOCK(*vpp, 0, p);
return (0);
}
@@ -1947,3 +1952,4 @@ nfsrv_object_create(struct vnode *vp) {
return vfs_object_create(vp, curproc, curproc?curproc->p_ucred:NULL, 1);
}
#endif /* NFS_NOSERVER */
+
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 937c2d5..06457f1 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94
+ * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -121,7 +121,7 @@ static struct vfsops nfs_vfsops = {
nfs_vget,
nfs_fhtovp,
nfs_vptofh,
- nfs_init,
+ nfs_init
};
VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
@@ -152,8 +152,10 @@ SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
void nfsargs_ntoh __P((struct nfs_args *));
-static struct mount *nfs_mountdiskless __P((char *, char *, int,
- struct sockaddr_in *, struct nfs_args *, register struct vnode **));
+static int nfs_mountdiskless __P((char *, char *, int,
+ struct sockaddr_in *, struct nfs_args *,
+ struct proc *, struct vnode **,
+ struct mount **));
static int nfs_iosize(nmp)
struct nfsmount* nmp;
@@ -329,8 +331,8 @@ nfs_fsinfo(nmp, vp, cred, p)
int
nfs_mountroot()
{
- register struct mount *mp;
- register struct nfs_diskless *nd = &nfs_diskless;
+ struct mount *mp, *swap_mp;
+ struct nfs_diskless *nd = &nfs_diskless;
struct socket *so;
struct vnode *vp;
struct proc *p = curproc; /* XXX */
@@ -406,6 +408,7 @@ nfs_mountroot()
panic("nfs_mountroot: RTM_ADD: %d", error);
}
+ swap_mp = NULL;
if (nd->swap_nblks) {
/* Convert to DEV_BSIZE instead of Kilobyte */
@@ -426,8 +429,10 @@ nfs_mountroot()
(l >> 24) & 0xff, (l >> 16) & 0xff,
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam);
printf("NFS SWAP: %s\n",buf);
- (void) nfs_mountdiskless(buf, "/swap", 0,
- &nd->swap_saddr, &nd->swap_args, &vp);
+ if (error = nfs_mountdiskless(buf, "/swap", 0,
+ &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp))
+ return (error);
+ vfs_unbusy(swap_mp, p);
VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size =
nd->swap_nblks * DEV_BSIZE ;
@@ -455,16 +460,22 @@ nfs_mountroot()
(l >> 24) & 0xff, (l >> 16) & 0xff,
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
printf("NFS ROOT: %s\n",buf);
- mp = nfs_mountdiskless(buf, "/", MNT_RDONLY,
- &nd->root_saddr, &nd->root_args, &vp);
+ if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
+ &nd->root_saddr, &nd->root_args, p, &vp, &mp)) {
+ if (swap_mp) {
+ mp->mnt_vfc->vfc_refcount--;
+ free(swap_mp, M_MOUNT);
+ }
+ return (error);
+ }
- if (vfs_lock(mp))
- panic("nfs_mountroot: vfs_lock");
+ simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
+ simple_unlock(&mountlist_slock);
mp->mnt_flag |= MNT_ROOTFS;
mp->mnt_vnodecovered = NULLVP;
- vfs_unlock(mp);
rootvp = vp;
+ vfs_unbusy(mp, p);
/*
* This is not really an nfs issue, but it is much easier to
@@ -483,39 +494,65 @@ nfs_mountroot()
/*
* Internal version of mount system call for diskless setup.
*/
-static struct mount *
-nfs_mountdiskless(path, which, mountflag, sin, args, vpp)
+static int
+nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp)
char *path;
char *which;
int mountflag;
struct sockaddr_in *sin;
struct nfs_args *args;
- register struct vnode **vpp;
+ struct proc *p;
+ struct vnode **vpp;
+ struct mount **mpp;
{
- register struct mount *mp;
- register struct mbuf *m;
- register int error;
-
- mp = (struct mount *)malloc((u_long)sizeof(struct mount),
- M_MOUNT, M_NOWAIT);
- if (mp == NULL)
- panic("nfs_mountroot: %s mount malloc", which);
- bzero((char *)mp, (u_long)sizeof(struct mount));
- mp->mnt_op = &nfs_vfsops;
- mp->mnt_flag = mountflag;
+ struct mount *mp;
+ struct mbuf *m;
+ int error;
- MGET(m, MT_SONAME, M_DONTWAIT);
- if (m == NULL)
- panic("nfs_mountroot: %s mount mbuf", which);
+ if (error = vfs_rootmountalloc("nfs", path, &mp)) {
+ printf("nfs_mountroot: NFS not configured");
+ return (error);
+ }
+ mp->mnt_flag = mountflag;
+ MGET(m, MT_SONAME, M_WAITOK);
bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len);
m->m_len = sin->sin_len;
- error = mountnfs(args, mp, m, which, path, vpp);
- if (error)
- panic("nfs_mountroot: mount %s on %s: %d", path, which, error);
-
- return (mp);
+ if (error = mountnfs(args, mp, m, which, path, vpp)) {
+ printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
+ mp->mnt_vfc->vfc_refcount--;
+ vfs_unbusy(mp, p);
+ free(mp, M_MOUNT);
+ return (error);
+ }
+ (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
+ *mpp = mp;
+ return (0);
}
+#ifdef COMPAT_PRELITE2
+/*
+ * Old arguments to mount NFS
+ */
+struct onfs_args {
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+#endif
/*
* VFS Operations.
@@ -546,6 +583,39 @@ nfs_mount(mp, path, data, ndp, p)
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
+ if (args.version != NFS_ARGSVERSION) {
+#ifdef COMPAT_PRELITE2
+ /*
+ * If the argument version is unknown, then assume the
+ * caller is a pre-lite2 4.4BSD client and convert its
+ * arguments.
+ */
+ struct onfs_args oargs;
+ error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
+ if (error)
+ return (error);
+ args.version = NFS_ARGSVERSION;
+ args.addr = oargs.addr;
+ args.addrlen = oargs.addrlen;
+ args.sotype = oargs.sotype;
+ args.proto = oargs.proto;
+ args.fh = oargs.fh;
+ args.fhsize = oargs.fhsize;
+ args.flags = oargs.flags;
+ args.wsize = oargs.wsize;
+ args.rsize = oargs.rsize;
+ args.readdirsize = oargs.readdirsize;
+ args.timeo = oargs.timeo;
+ args.retrans = oargs.retrans;
+ args.maxgrouplist = oargs.maxgrouplist;
+ args.readahead = oargs.readahead;
+ args.leaseterm = oargs.leaseterm;
+ args.deadthresh = oargs.deadthresh;
+ args.hostname = oargs.hostname;
+#else /* COMPAT_PRELITE2 */
+ return (EPROGMISMATCH);
+#endif /* COMPAT_PRELITE2 */
+ }
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
if (error)
return (error);
@@ -595,7 +665,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
- getnewfsid(mp, MOUNT_NFS);
+ vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
nmp->nm_flag = argp->flags;
if (nmp->nm_flag & NFSMNT_NQNFS)
@@ -619,15 +689,6 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
nmp->nm_inprog = NULLVP;
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
-#ifdef __NetBSD__
-#ifdef COMPAT_09
- mp->mnt_stat.f_type = 2;
-#else
- mp->mnt_stat.f_type = 0;
-#endif
-#else
- mp->mnt_stat.f_type = MOUNT_NFS;
-#endif
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
@@ -741,7 +802,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
/*
* Lose the lock but keep the ref.
*/
- VOP_UNLOCK(*vpp);
+ VOP_UNLOCK(*vpp, 0, curproc);
return (0);
bad:
@@ -765,11 +826,8 @@ nfs_unmount(mp, mntflags, p)
struct vnode *vp;
int error, flags = 0;
- if (mntflags & MNT_FORCE) {
- if (!doforce)
- return (EINVAL);
+ if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
- }
nmp = VFSTONFS(mp);
/*
* Goes something like this..
@@ -846,7 +904,7 @@ nfs_root(mp, vpp)
if (error)
return (error);
vp = NFSTOV(np);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, curproc);
if (vp->v_type == VNON)
vp->v_type = VDIR;
vp->v_flag = VROOT;
@@ -885,7 +943,7 @@ loop:
goto loop;
if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL)
continue;
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto loop;
error = VOP_FSYNC(vp, cred, waitfor, p);
if (error)
@@ -969,4 +1027,3 @@ nfs_quotactl(mp, cmd, uid, arg, p)
return (EOPNOTSUPP);
}
-
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index b8ff396..905bb22 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_vnops.c 8.5 (Berkeley) 2/13/94
+ * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
* $FreeBSD$
*/
+
/*
* vnode op calls for Sun NFS version 2 and 3
*/
@@ -151,14 +152,10 @@ static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)nfs_read }, /* read */
{ &vop_write_desc, (vop_t *)nfs_write }, /* write */
-#ifdef HAS_VOPLEASE
{ &vop_lease_desc, (vop_t *)nfs_lease_check }, /* lease */
-#endif
{ &vop_ioctl_desc, (vop_t *)nfs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)nfs_select }, /* select */
-#ifdef HAS_VOPREVOKE
{ &vop_revoke_desc, (vop_t *)nfs_revoke }, /* revoke */
-#endif
{ &vop_mmap_desc, (vop_t *)nfs_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)nfs_seek }, /* seek */
@@ -212,14 +209,10 @@ static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)nfsspec_read }, /* read */
{ &vop_write_desc, (vop_t *)nfsspec_write }, /* write */
-#ifdef HAS_VOPLEASE
{ &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
-#endif
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
-#ifdef HAS_VOPREVOKE
{ &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
-#endif
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
@@ -270,14 +263,10 @@ static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)nfsfifo_read }, /* read */
{ &vop_write_desc, (vop_t *)nfsfifo_write }, /* write */
-#ifdef HAS_VOPLEASE
{ &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
-#endif
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
-#ifdef HAS_VOPREVOKE
{ &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
-#endif
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
@@ -469,7 +458,7 @@ nfs_open(ap)
if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
ap->a_p, 1)) == EINTR)
return (error);
- (void) vnode_pager_uncache(vp);
+ (void) vnode_pager_uncache(vp, ap->a_p);
np->n_brev = np->n_lrev;
}
}
@@ -588,7 +577,7 @@ nfs_getattr(ap)
int error = 0;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
int v3 = NFS_ISV3(vp);
-
+
/*
* Update local times for special files.
*/
@@ -634,7 +623,7 @@ nfs_setattr(ap)
/*
* Disallow write attempts if the filesystem is mounted read-only.
*/
- if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
+ 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))
@@ -645,6 +634,8 @@ nfs_setattr(ap)
return (EISDIR);
case VCHR:
case VBLK:
+ case VSOCK:
+ case VFIFO:
if (vap->va_mtime.tv_sec == VNOVAL &&
vap->va_atime.tv_sec == VNOVAL &&
vap->va_mode == (u_short)VNOVAL &&
@@ -660,20 +651,22 @@ nfs_setattr(ap)
*/
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
- if (vap->va_size == 0)
+ if (np->n_flag & NMODIFIED) {
+ if (vap->va_size == 0)
error = nfs_vinvalbuf(vp, 0,
ap->a_cred, ap->a_p, 1);
- else
+ else
error = nfs_vinvalbuf(vp, V_SAVE,
ap->a_cred, ap->a_p, 1);
- if (error)
+ if (error)
return (error);
+ }
tsize = np->n_size;
np->n_size = np->n_vattr.va_size = vap->va_size;
vnode_pager_setsize(vp, (u_long)np->n_size);
};
} else if ((vap->va_mtime.tv_sec != VNOVAL ||
- vap->va_atime.tv_sec != VNOVAL) &&
+ vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) &&
vp->v_type == VREG &&
(error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
ap->a_p, 1)) == EINTR)
@@ -826,6 +819,7 @@ nfs_lookup(ap)
struct nfsnode *np;
int lockparent, wantparent, error = 0, attrflag, fhsize;
int v3 = NFS_ISV3(dvp);
+ struct proc *p = cnp->cn_proc;
if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
@@ -851,18 +845,18 @@ nfs_lookup(ap)
VREF(newvp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(dvp);
- error = vget(newvp, 1);
+ VOP_UNLOCK(dvp, 0, p);
+ error = vget(newvp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(dvp);
+ error = vn_lock(dvp, LK_EXCLUSIVE, p);
} else {
- error = vget(newvp, 1);
+ error = vget(newvp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
if (!error) {
if (vpid == newvp->v_id) {
- if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)
+ if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p)
&& vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
nfsstats.lookupcache_hits++;
if (cnp->cn_nameiop != LOOKUP &&
@@ -874,9 +868,9 @@ nfs_lookup(ap)
}
vput(newvp);
if (lockparent && dvp != newvp && (flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
}
- error = VOP_LOCK(dvp);
+ error = vn_lock(dvp, LK_EXCLUSIVE, p);
if (error)
return (error);
*vpp = NULLVP;
@@ -920,20 +914,20 @@ nfs_lookup(ap)
m_freem(mrep);
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
return (0);
}
if (flags & ISDOTDOT) {
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
if (error) {
- VOP_LOCK(dvp);
+ vn_lock(dvp, LK_EXCLUSIVE + LK_RETRY, p);
return (error);
}
newvp = NFSTOV(np);
if (lockparent && (flags & ISLASTCN) &&
- (error = VOP_LOCK(dvp))) {
+ (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
vput(newvp);
return (error);
}
@@ -946,7 +940,7 @@ nfs_lookup(ap)
return (error);
}
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
newvp = NFSTOV(np);
}
if (v3) {
@@ -969,7 +963,7 @@ nfs_lookup(ap)
if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
(flags & ISLASTCN) && error == ENOENT) {
if (!lockparent)
- VOP_UNLOCK(dvp);
+ VOP_UNLOCK(dvp, 0, p);
if (dvp->v_mount->mnt_flag & MNT_RDONLY)
error = EROFS;
else
@@ -2110,7 +2104,7 @@ nfs_readdirrpc(vp, uiop, cred)
}
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
more_dirs = fxdr_unsigned(int, *tl);
-
+
/* loop thru the dir entries, doctoring them to 4bsd form */
while (more_dirs && bigenough) {
if (v3) {
@@ -2923,6 +2917,9 @@ loop:
}
}
if (vp->v_dirtyblkhd.lh_first && commit) {
+#ifndef DIAGNOSTIC
+ vprint("nfs_fsync: dirty", vp);
+#endif
goto loop;
}
}
@@ -3131,7 +3128,7 @@ nfs_writebp(bp, force)
* an actual write will have to be scheduled via. VOP_STRATEGY().
* If B_WRITEINPROG is already set, then push it with a write anyhow.
*/
- if (oldflags & (B_NEEDCOMMIT | B_WRITEINPROG) == B_NEEDCOMMIT) {
+ if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
bp->b_flags |= B_WRITEINPROG;
retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
@@ -3205,7 +3202,7 @@ nfsspec_access(ap)
if (cred->cr_uid == 0)
return (0);
vap = &vattr;
- error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p);
+ error = VOP_GETATTR(vp, vap, cred, ap->a_p);
if (error)
return (error);
/*
diff --git a/sys/nfsclient/nfsargs.h b/sys/nfsclient/nfsargs.h
index db41859..73a018c 100644
--- a/sys/nfsclient/nfsargs.h
+++ b/sys/nfsclient/nfsargs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,19 +33,19 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $FreeBSD$
*/
#ifndef _NFS_NFS_H_
#define _NFS_NFS_H_
-#include <nfs/rpcv2.h>
-
/*
* Tunable constants for nfs
*/
+#ifdef KERNEL
+
#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
@@ -69,7 +69,7 @@
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
+#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
@@ -89,30 +89,9 @@
/*
* XXX
- * sys/buf.h should be edited to change B_APPENDWRITE --> B_NEEDCOMMIT, but
- * until then...
- * Same goes for sys/malloc.h, which needs M_NFSDIROFF,
- * M_NFSRVDESC and M_NFSBIGFH added.
- * The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
- * exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
-#ifndef B_NEEDCOMMIT
-#define B_NEEDCOMMIT B_APPENDWRITE
-#endif
-#ifndef M_NFSRVDESC
-#define M_NFSRVDESC M_TEMP
-#endif
-#ifndef M_NFSDIROFF
-#define M_NFSDIROFF M_TEMP
-#endif
-#ifndef M_NFSBIGFH
-#define M_NFSBIGFH M_TEMP
-#endif
-#ifndef VA_EXCLUSIVE
-#define VA_EXCLUSIVE 0
-#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
@@ -120,20 +99,6 @@
#endif
/*
- * These ifdefs try to handle the differences between the various 4.4BSD-Lite
- * based vfs interfaces.
- * btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
- * differentiate between NetBSD-1.0 and NetBSD-current, so..
- * I also don't know about BSDi's 2.0 release.
- */
-#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPLEASE 1
-#endif
-#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPREVOKE 1
-#endif
-
-/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
@@ -164,13 +129,114 @@
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
+#endif /* KERNEL */
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
+/*
+ * Arguments to mount NFS
+ */
+#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
+struct nfs_args {
+ int version; /* args structure version number */
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
*/
struct nfsd_args {
int sock; /* Socket to serve */
- caddr_t name; /* Client address for connection based sockets */
+ caddr_t name; /* Client addr for connection based sockets */
int namelen; /* Length of name */
};
@@ -200,6 +266,10 @@ struct nfsd_cargs {
};
/*
+ * XXX to allow amd to include nfs.h without nfsproto.h
+ */
+#ifdef NFS_NPROCS
+/*
* Stats structure
*/
struct nfsstats {
@@ -237,6 +307,7 @@ struct nfsstats {
int srvnqnfs_getleases;
int srvvop_writes;
};
+#endif
/*
* Flags for nfssvc() system call.
@@ -267,7 +338,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
-#if defined(KERNEL) || defined(_KERNEL)
+#ifdef KERNEL
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@@ -482,6 +553,8 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
+
+int nfs_init __P((struct vfsconf *vfsp));
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
@@ -516,14 +589,12 @@ int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
u_long nfs_hash __P((nfsfh_t *,int));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
-void nfsrv_cleancache __P((void));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
-int nfs_init __P((void));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
+void nfsrv_cleancache __P((void));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *nmp));
+void nfs_disconnect __P((struct nfsmount *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
@@ -531,7 +602,6 @@ int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_writebp __P((struct buf *,int));
@@ -594,8 +664,8 @@ int nfsrv_symlink __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
-
-
+void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void nfsrv_slpderef __P((struct nfssvc_sock *slp));
#endif /* KERNEL */
#endif
diff --git a/sys/nfsclient/nfsdiskless.h b/sys/nfsclient/nfsdiskless.h
index 117548b..4777818 100644
--- a/sys/nfsclient/nfsdiskless.h
+++ b/sys/nfsclient/nfsdiskless.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsdiskless.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfsdiskless.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSDISKLESS_H_
#define _NFS_NFSDISKLESS_H_
@@ -46,8 +47,8 @@
* vnodes plus do a partial ifconfig(8) and route(8) so that the critical net
* interface can communicate with the server.
* The primary bootstrap is expected to fill in the appropriate fields before
- * starting the kernel. Whether or not the swap area is nfs mounted is determined
- * by the value in swdevt[0]. (equal to NODEV --> swap over nfs)
+ * starting the kernel. Whether or not the swap area is nfs mounted is
+ * determined by the value in swdevt[0]. (equal to NODEV --> swap over nfs)
* Currently only works for AF_INET protocols.
* NB: All fields are stored in net byte order to avoid hassles with
* client/server byte ordering differences.
diff --git a/sys/nfsclient/nfsm_subs.h b/sys/nfsclient/nfsm_subs.h
index ac1a159..cd37c59 100644
--- a/sys/nfsclient/nfsm_subs.h
+++ b/sys/nfsclient/nfsm_subs.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
+ * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
diff --git a/sys/nfsclient/nfsmount.h b/sys/nfsclient/nfsmount.h
index ea48bca..1545ada 100644
--- a/sys/nfsclient/nfsmount.h
+++ b/sys/nfsclient/nfsmount.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsmount.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfsmount.h 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSMOUNT_H_
#define _NFS_NFSMOUNT_H_
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 4408fe2..e52a3dd 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsnode.h 8.4 (Berkeley) 2/13/94
+ * @(#)nfsnode.h 8.9 (Berkeley) 5/14/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSNODE_H_
#define _NFS_NFSNODE_H_
@@ -161,26 +162,16 @@ extern vop_t **spec_nfsv2nodeop_p;
* Prototypes for NFS vnode operations
*/
int nfs_write __P((struct vop_write_args *));
-#ifdef HAS_VOPLEASE
#define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
-#define nqnfs_vop_lease_check lease_check
-#else
-#ifdef __FreeBSD__
-#define nqnfs_lease_check nfs_lease_check
-#else
-#define nqnfs_lease_check lease_check
-#endif
-#endif
-#ifdef HAS_VOPREVOKE
+int nqnfs_vop_lease_check __P((struct vop_lease_args *));
#define nfs_revoke vop_revoke
-#endif
#define nfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
int nfs_abortop __P((struct vop_abortop_args *));
int nfs_inactive __P((struct vop_inactive_args *));
int nfs_reclaim __P((struct vop_reclaim_args *));
-int nfs_lock __P((struct vop_lock_args *));
-int nfs_unlock __P((struct vop_unlock_args *));
-int nfs_islocked __P((struct vop_islocked_args *));
+#define nfs_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define nfs_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
+#define nfs_islocked ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
#define nfs_reallocblks \
((int (*) __P((struct vop_reallocblks_args *)))eopnotsupp)
@@ -190,11 +181,7 @@ int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
void nfs_invaldir __P((struct vnode *));
-#ifdef __FreeBSD__
#define nqnfs_lease_updatetime nfs_lease_updatetime
-#else
-#define nqnfs_lease_updatetime lease_updatetime
-#endif
#endif /* KERNEL */
diff --git a/sys/nfsclient/nfsstats.h b/sys/nfsclient/nfsstats.h
index db41859..73a018c 100644
--- a/sys/nfsclient/nfsstats.h
+++ b/sys/nfsclient/nfsstats.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,19 +33,19 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $FreeBSD$
*/
#ifndef _NFS_NFS_H_
#define _NFS_NFS_H_
-#include <nfs/rpcv2.h>
-
/*
* Tunable constants for nfs
*/
+#ifdef KERNEL
+
#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
@@ -69,7 +69,7 @@
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
+#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
@@ -89,30 +89,9 @@
/*
* XXX
- * sys/buf.h should be edited to change B_APPENDWRITE --> B_NEEDCOMMIT, but
- * until then...
- * Same goes for sys/malloc.h, which needs M_NFSDIROFF,
- * M_NFSRVDESC and M_NFSBIGFH added.
- * The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
- * exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
-#ifndef B_NEEDCOMMIT
-#define B_NEEDCOMMIT B_APPENDWRITE
-#endif
-#ifndef M_NFSRVDESC
-#define M_NFSRVDESC M_TEMP
-#endif
-#ifndef M_NFSDIROFF
-#define M_NFSDIROFF M_TEMP
-#endif
-#ifndef M_NFSBIGFH
-#define M_NFSBIGFH M_TEMP
-#endif
-#ifndef VA_EXCLUSIVE
-#define VA_EXCLUSIVE 0
-#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
@@ -120,20 +99,6 @@
#endif
/*
- * These ifdefs try to handle the differences between the various 4.4BSD-Lite
- * based vfs interfaces.
- * btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
- * differentiate between NetBSD-1.0 and NetBSD-current, so..
- * I also don't know about BSDi's 2.0 release.
- */
-#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPLEASE 1
-#endif
-#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPREVOKE 1
-#endif
-
-/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
@@ -164,13 +129,114 @@
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
+#endif /* KERNEL */
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
+/*
+ * Arguments to mount NFS
+ */
+#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
+struct nfs_args {
+ int version; /* args structure version number */
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
*/
struct nfsd_args {
int sock; /* Socket to serve */
- caddr_t name; /* Client address for connection based sockets */
+ caddr_t name; /* Client addr for connection based sockets */
int namelen; /* Length of name */
};
@@ -200,6 +266,10 @@ struct nfsd_cargs {
};
/*
+ * XXX to allow amd to include nfs.h without nfsproto.h
+ */
+#ifdef NFS_NPROCS
+/*
* Stats structure
*/
struct nfsstats {
@@ -237,6 +307,7 @@ struct nfsstats {
int srvnqnfs_getleases;
int srvvop_writes;
};
+#endif
/*
* Flags for nfssvc() system call.
@@ -267,7 +338,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
-#if defined(KERNEL) || defined(_KERNEL)
+#ifdef KERNEL
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@@ -482,6 +553,8 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
+
+int nfs_init __P((struct vfsconf *vfsp));
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
@@ -516,14 +589,12 @@ int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
u_long nfs_hash __P((nfsfh_t *,int));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
-void nfsrv_cleancache __P((void));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
-int nfs_init __P((void));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
+void nfsrv_cleancache __P((void));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *nmp));
+void nfs_disconnect __P((struct nfsmount *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
@@ -531,7 +602,6 @@ int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_writebp __P((struct buf *,int));
@@ -594,8 +664,8 @@ int nfsrv_symlink __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
-
-
+void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void nfsrv_slpderef __P((struct nfssvc_sock *slp));
#endif /* KERNEL */
#endif
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index db41859..73a018c 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/nfs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,19 +33,19 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $FreeBSD$
*/
#ifndef _NFS_NFS_H_
#define _NFS_NFS_H_
-#include <nfs/rpcv2.h>
-
/*
* Tunable constants for nfs
*/
+#ifdef KERNEL
+
#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
@@ -69,7 +69,7 @@
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
+#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
@@ -89,30 +89,9 @@
/*
* XXX
- * sys/buf.h should be edited to change B_APPENDWRITE --> B_NEEDCOMMIT, but
- * until then...
- * Same goes for sys/malloc.h, which needs M_NFSDIROFF,
- * M_NFSRVDESC and M_NFSBIGFH added.
- * The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
- * exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
-#ifndef B_NEEDCOMMIT
-#define B_NEEDCOMMIT B_APPENDWRITE
-#endif
-#ifndef M_NFSRVDESC
-#define M_NFSRVDESC M_TEMP
-#endif
-#ifndef M_NFSDIROFF
-#define M_NFSDIROFF M_TEMP
-#endif
-#ifndef M_NFSBIGFH
-#define M_NFSBIGFH M_TEMP
-#endif
-#ifndef VA_EXCLUSIVE
-#define VA_EXCLUSIVE 0
-#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
@@ -120,20 +99,6 @@
#endif
/*
- * These ifdefs try to handle the differences between the various 4.4BSD-Lite
- * based vfs interfaces.
- * btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
- * differentiate between NetBSD-1.0 and NetBSD-current, so..
- * I also don't know about BSDi's 2.0 release.
- */
-#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPLEASE 1
-#endif
-#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPREVOKE 1
-#endif
-
-/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
@@ -164,13 +129,114 @@
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
+#endif /* KERNEL */
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
+/*
+ * Arguments to mount NFS
+ */
+#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
+struct nfs_args {
+ int version; /* args structure version number */
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
*/
struct nfsd_args {
int sock; /* Socket to serve */
- caddr_t name; /* Client address for connection based sockets */
+ caddr_t name; /* Client addr for connection based sockets */
int namelen; /* Length of name */
};
@@ -200,6 +266,10 @@ struct nfsd_cargs {
};
/*
+ * XXX to allow amd to include nfs.h without nfsproto.h
+ */
+#ifdef NFS_NPROCS
+/*
* Stats structure
*/
struct nfsstats {
@@ -237,6 +307,7 @@ struct nfsstats {
int srvnqnfs_getleases;
int srvvop_writes;
};
+#endif
/*
* Flags for nfssvc() system call.
@@ -267,7 +338,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
-#if defined(KERNEL) || defined(_KERNEL)
+#ifdef KERNEL
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@@ -482,6 +553,8 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
+
+int nfs_init __P((struct vfsconf *vfsp));
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
@@ -516,14 +589,12 @@ int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
u_long nfs_hash __P((nfsfh_t *,int));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
-void nfsrv_cleancache __P((void));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
-int nfs_init __P((void));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
+void nfsrv_cleancache __P((void));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *nmp));
+void nfs_disconnect __P((struct nfsmount *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
@@ -531,7 +602,6 @@ int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_writebp __P((struct buf *,int));
@@ -594,8 +664,8 @@ int nfsrv_symlink __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
-
-
+void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void nfsrv_slpderef __P((struct nfssvc_sock *slp));
#endif /* KERNEL */
#endif
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 3946778..28a705a 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -1723,7 +1723,7 @@ nfsrv_remove(nfsd, slp, procp, mrq)
}
out:
if (!error) {
- vnode_pager_uncache(vp);
+ vnode_pager_uncache(vp, procp);
nqsrv_getl(nd.ni_dvp, ND_WRITE);
nqsrv_getl(vp, ND_WRITE);
@@ -1900,7 +1900,7 @@ out:
nqsrv_getl(tdvp, ND_WRITE);
if (tvp) {
nqsrv_getl(tvp, ND_WRITE);
- (void) vnode_pager_uncache(tvp);
+ (void) vnode_pager_uncache(tvp, procp);
}
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
@@ -2027,11 +2027,7 @@ out:
if (!error) {
nqsrv_getl(vp, ND_WRITE);
nqsrv_getl(xp, ND_WRITE);
-#if defined(__NetBSD__) || defined(__FreeBSD__)
- error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
-#else
error = VOP_LINK(vp, nd.ni_dvp, &nd.ni_cnd);
-#endif
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)
@@ -2479,7 +2475,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
int v3 = (nfsd->nd_flag & ND_NFSV3);
u_quad_t frev, off, toff, verf;
- u_int *cookies = NULL, *cookiep;
+ u_long *cookies = NULL, *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
@@ -2520,7 +2516,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
nfsm_srvpostop_attr(getret, &at);
return (0);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
#ifdef __NetBSD__
ncookies = siz / (5 * NFSX_UNSIGNED); /*7 for V3, but it's an est. so*/
@@ -2538,16 +2534,12 @@ again:
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
eofflag = 0;
- VOP_LOCK(vp);
-#ifndef __NetBSD__
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, procp);
if (cookies) {
free((caddr_t)cookies, M_TEMP);
cookies = NULL;
}
error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
-#else
- error = VOP_READDIR(vp, &io, cred, &eofflag, cookies, ncookies);
-#endif
off = (off_t)io.uio_offset;
if (!cookies && !error)
error = NFSERR_PERM;
@@ -2556,7 +2548,7 @@ again:
if (!error)
error = getret;
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
if (error) {
vrele(vp);
free((caddr_t)rbuf, M_TEMP);
@@ -2751,7 +2743,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
u_quad_t frev, off, toff, verf;
- u_int *cookies = NULL, *cookiep;
+ u_long *cookies = NULL, *cookiep;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
@@ -2787,7 +2779,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
nfsm_srvpostop_attr(getret, &at);
return (0);
}
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
#ifdef __NetBSD__
ncookies = siz / (7 * NFSX_UNSIGNED);
@@ -2805,19 +2797,15 @@ again:
io.uio_rw = UIO_READ;
io.uio_procp = (struct proc *)0;
eofflag = 0;
- VOP_LOCK(vp);
-#ifndef __NetBSD__
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, procp);
if (cookies) {
free((caddr_t)cookies, M_TEMP);
cookies = NULL;
}
error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
-#else
- error = VOP_READDIR(vp, &io, cred, &eofflag, cookies, ncookies);
-#endif
off = (u_quad_t)io.uio_offset;
getret = VOP_GETATTR(vp, &at, cred, procp);
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, procp);
if (!cookies && !error)
error = NFSERR_PERM;
if (!error)
diff --git a/sys/nfsserver/nfs_srvcache.c b/sys/nfsserver/nfs_srvcache.c
index 835ec06..efff221 100644
--- a/sys/nfsserver/nfs_srvcache.c
+++ b/sys/nfsserver/nfs_srvcache.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_srvcache.c 8.1 (Berkeley) 6/10/93
+ * @(#)nfs_srvcache.c 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
diff --git a/sys/nfsserver/nfs_srvsock.c b/sys/nfsserver/nfs_srvsock.c
index addd59f..ed16333 100644
--- a/sys/nfsserver/nfs_srvsock.c
+++ b/sys/nfsserver/nfs_srvsock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1991, 1993
+ * Copyright (c) 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
+ * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
* $FreeBSD$
*/
@@ -1925,6 +1925,9 @@ nfs_getreq(nd, nfsd, has_header)
struct mbuf *mrep, *md;
register struct nfsuid *nuidp;
struct timeval tvin, tvout;
+#if 0 /* until encrypted keys are implemented */
+ NFSKERBKEYSCHED_T keys; /* stores key schedule */
+#endif
mrep = nd->nd_mrep;
md = nd->nd_md;
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 1feadd6..5f83bf5 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -100,6 +100,7 @@ enum vtype nv3tov_type[8]= {
VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
};
+int nfs_mount_type;
int nfs_ticks;
struct nfs_reqq nfs_reqq;
@@ -1093,7 +1094,8 @@ nfsm_strtmbuf(mb, bpos, cp, siz)
* Called once to initialize data structures...
*/
int
-nfs_init()
+nfs_init(vfsp)
+ struct vfsconf *vfsp;
{
register int i;
@@ -1116,6 +1118,7 @@ nfs_init()
printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
printf("Try unionizing the nu_nickname and nu_flag fields\n");
}
+ nfs_mount_type = vfsp->vfc_typenum;
nfsrtt.pos = 0;
rpc_vers = txdr_unsigned(RPC_VER2);
rpc_call = txdr_unsigned(RPC_CALL);
@@ -1170,10 +1173,10 @@ nfs_init()
* of the system can call us, if we are loadable.
*/
#ifndef NFS_NOSERVER
- lease_check = nfs_lease_check;
+ lease_check_hook = nqnfs_vop_lease_check;
#endif
lease_updatetime = nfs_lease_updatetime;
- vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */
+ vfsp->vfc_refcount++; /* make us non-unloadable */
#ifdef VFS_LKM
sysent[SYS_nfssvc].sy_narg = 2;
sysent[SYS_nfssvc].sy_call = nfssvc;
@@ -1212,7 +1215,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
register struct vattr *vap;
register struct nfs_fattr *fp;
register struct nfsnode *np;
- register struct nfsnodehashhead *nhpp;
register long t1;
caddr_t cp2;
int error = 0, rdev;
@@ -1222,6 +1224,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
struct timespec mtime;
struct vnode *nvp;
int v3 = NFS_ISV3(vp);
+ struct proc *p = curproc;
md = *mdp;
t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
@@ -1284,7 +1287,7 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* then release it here.
*/
if (vtyp != VREG && VOP_ISLOCKED(vp))
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
vp->v_type = vtyp;
if (vp->v_type == VFIFO) {
vp->v_op = fifo_nfsv2nodeop_p;
@@ -1295,8 +1298,11 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
if (nvp) {
/*
* Discard unneeded vnode, but save its nfsnode.
+ * Since the nfsnode does not have a lock, its
+ * vnode lock has to be carried over.
*/
- LIST_REMOVE(np, n_hash);
+ nvp->v_vnlock = vp->v_vnlock;
+ vp->v_vnlock = NULL;
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = spec_vnodeop_p;
@@ -1306,8 +1312,6 @@ nfs_loadattrcache(vpp, mdp, dposp, vaper)
* Reinitialize aliased node.
*/
np->n_vnode = nvp;
- nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize));
- LIST_INSERT_HEAD(nhpp, np, n_hash);
*vpp = vp = nvp;
}
}
@@ -1714,13 +1718,14 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
int *rdonlyp;
int kerbflag;
{
+ struct proc *p = curproc; /* XXX */
register struct mount *mp;
register int i;
struct ucred *credanon;
int error, exflags;
*vpp = (struct vnode *)0;
- mp = getvfs(&fhp->fh_fsid);
+ mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
@@ -1751,7 +1756,7 @@ nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag)
nfsrv_object_create(*vpp);
if (!lockflag)
- VOP_UNLOCK(*vpp);
+ VOP_UNLOCK(*vpp, 0, p);
return (0);
}
@@ -1947,3 +1952,4 @@ nfsrv_object_create(struct vnode *vp) {
return vfs_object_create(vp, curproc, curproc?curproc->p_ucred:NULL, 1);
}
#endif /* NFS_NOSERVER */
+
diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c
index 734fe79..24d4bd6 100644
--- a/sys/nfsserver/nfs_syscalls.c
+++ b/sys/nfsserver/nfs_syscalls.c
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
+ * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
* $FreeBSD$
*/
@@ -97,7 +97,6 @@ static int nfssvc_iod __P((struct proc *));
static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
-
#ifndef NFS_NOSERVER
int nfsd_waiting = 0;
static struct nfsdrt nfsdrt;
@@ -1051,6 +1050,7 @@ nfsmout:
}
#ifndef NFS_NOSERVER
+
/*
* Derefence a server socket structure. If it has no more references and
* is no longer valid, you can throw it away.
diff --git a/sys/nfsserver/nfsm_subs.h b/sys/nfsserver/nfsm_subs.h
index ac1a159..cd37c59 100644
--- a/sys/nfsserver/nfsm_subs.h
+++ b/sys/nfsserver/nfsm_subs.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
+ * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
diff --git a/sys/nfsserver/nfsrvcache.h b/sys/nfsserver/nfsrvcache.h
index 38c9657..2cfa694 100644
--- a/sys/nfsserver/nfsrvcache.h
+++ b/sys/nfsserver/nfsrvcache.h
@@ -33,10 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfsrvcache.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfsrvcache.h 8.3 (Berkeley) 3/30/95
* $FreeBSD$
*/
+
#ifndef _NFS_NFSRVCACHE_H_
#define _NFS_NFSRVCACHE_H_
diff --git a/sys/nfsserver/nfsrvstats.h b/sys/nfsserver/nfsrvstats.h
index db41859..73a018c 100644
--- a/sys/nfsserver/nfsrvstats.h
+++ b/sys/nfsserver/nfsrvstats.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1989, 1993
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,19 +33,19 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)nfs.h 8.1 (Berkeley) 6/10/93
+ * @(#)nfs.h 8.4 (Berkeley) 5/1/95
* $FreeBSD$
*/
#ifndef _NFS_NFS_H_
#define _NFS_NFS_H_
-#include <nfs/rpcv2.h>
-
/*
* Tunable constants for nfs
*/
+#ifdef KERNEL
+
#define NFS_MAXIOVEC 34
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
@@ -69,7 +69,7 @@
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
-#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
+#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
@@ -89,30 +89,9 @@
/*
* XXX
- * sys/buf.h should be edited to change B_APPENDWRITE --> B_NEEDCOMMIT, but
- * until then...
- * Same goes for sys/malloc.h, which needs M_NFSDIROFF,
- * M_NFSRVDESC and M_NFSBIGFH added.
- * The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
- * exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
-#ifndef B_NEEDCOMMIT
-#define B_NEEDCOMMIT B_APPENDWRITE
-#endif
-#ifndef M_NFSRVDESC
-#define M_NFSRVDESC M_TEMP
-#endif
-#ifndef M_NFSDIROFF
-#define M_NFSDIROFF M_TEMP
-#endif
-#ifndef M_NFSBIGFH
-#define M_NFSBIGFH M_TEMP
-#endif
-#ifndef VA_EXCLUSIVE
-#define VA_EXCLUSIVE 0
-#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
@@ -120,20 +99,6 @@
#endif
/*
- * These ifdefs try to handle the differences between the various 4.4BSD-Lite
- * based vfs interfaces.
- * btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
- * differentiate between NetBSD-1.0 and NetBSD-current, so..
- * I also don't know about BSDi's 2.0 release.
- */
-#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPLEASE 1
-#endif
-#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
-#define HAS_VOPREVOKE 1
-#endif
-
-/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
@@ -164,13 +129,114 @@
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
+#endif /* KERNEL */
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
+/*
+ * Arguments to mount NFS
+ */
+#define NFS_ARGSVERSION 3 /* change when nfs_args changes */
+struct nfs_args {
+ int version; /* args structure version number */
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retries */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
*/
struct nfsd_args {
int sock; /* Socket to serve */
- caddr_t name; /* Client address for connection based sockets */
+ caddr_t name; /* Client addr for connection based sockets */
int namelen; /* Length of name */
};
@@ -200,6 +266,10 @@ struct nfsd_cargs {
};
/*
+ * XXX to allow amd to include nfs.h without nfsproto.h
+ */
+#ifdef NFS_NPROCS
+/*
* Stats structure
*/
struct nfsstats {
@@ -237,6 +307,7 @@ struct nfsstats {
int srvnqnfs_getleases;
int srvvop_writes;
};
+#endif
/*
* Flags for nfssvc() system call.
@@ -267,7 +338,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
-#if defined(KERNEL) || defined(_KERNEL)
+#ifdef KERNEL
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@@ -482,6 +553,8 @@ extern int nfsd_head_flag;
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
+
+int nfs_init __P((struct vfsconf *vfsp));
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
@@ -516,14 +589,12 @@ int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
u_long nfs_hash __P((nfsfh_t *,int));
-void nfsrv_slpderef __P((struct nfssvc_sock *slp));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
-void nfsrv_cleancache __P((void));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
-int nfs_init __P((void));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
+void nfsrv_cleancache __P((void));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
-void nfs_disconnect __P((struct nfsmount *nmp));
+void nfs_disconnect __P((struct nfsmount *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
@@ -531,7 +602,6 @@ int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
-void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_writebp __P((struct buf *,int));
@@ -594,8 +664,8 @@ int nfsrv_symlink __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct proc *procp, struct mbuf **mrq));
-
-
+void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void nfsrv_slpderef __P((struct nfssvc_sock *slp));
#endif /* KERNEL */
#endif
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index 3a6fed2..8c79c59 100644
--- a/sys/scsi/cd.c
+++ b/sys/scsi/cd.c
@@ -75,7 +75,7 @@ static d_strategy_t cdstrategy;
static struct cdevsw cd_cdevsw;
static struct bdevsw cd_bdevsw =
{ cdopen, cdclose, cdstrategy, cdioctl, /*6*/
- nodump, nopsize, 0, "cd", &cd_cdevsw, -1 };
+ nodump, nopsize, D_DISK, "cd", &cd_cdevsw, -1 };
static int32_t cdstrats, cdqueues;
diff --git a/sys/scsi/od.c b/sys/scsi/od.c
index 7964e30..439a47e 100644
--- a/sys/scsi/od.c
+++ b/sys/scsi/od.c
@@ -152,7 +152,7 @@ static d_strategy_t odstrategy;
static struct cdevsw od_cdevsw;
static struct bdevsw od_bdevsw =
{ odopen, odclose, odstrategy, odioctl, /*20*/
- nodump, nopsize, 0, "od", &od_cdevsw, -1 };
+ nodump, nopsize, D_DISK, "od", &od_cdevsw, -1 };
/*
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
index bb310537..3162f1d 100644
--- a/sys/scsi/sd.c
+++ b/sys/scsi/sd.c
@@ -1,3 +1,4 @@
+
/*
* Written by Julian Elischer (julian@dialix.oz.au)
* for TRW Financial Systems for use under the MACH(2.5) operating system.
@@ -120,7 +121,7 @@ static d_strategy_t sdstrategy;
static struct cdevsw sd_cdevsw;
static struct bdevsw sd_bdevsw =
{ sdopen, sdclose, sdstrategy, sdioctl, /*4*/
- sddump, sdsize, 0, "sd", &sd_cdevsw, -1 };
+ sddump, sdsize, D_DISK, "sd", &sd_cdevsw, -1 };
diff --git a/sys/scsi/st.c b/sys/scsi/st.c
index d3735f3..8100f04 100644
--- a/sys/scsi/st.c
+++ b/sys/scsi/st.c
@@ -165,7 +165,7 @@ static d_strategy_t ststrategy;
static struct cdevsw st_cdevsw;
static struct bdevsw st_bdevsw =
{ stopen, stclose, ststrategy, stioctl, /*5*/
- nodump, nopsize, 0, "st", &st_cdevsw, -1 };
+ nodump, nopsize, D_TAPE, "st", &st_cdevsw, -1 };
SCSI_DEVICE_ENTRIES(st)
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index fd5146c..6b8c850 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -79,6 +79,13 @@ typedef int l_start_t __P((struct tty *tp));
typedef int l_modem_t __P((struct tty *tp, int flag));
/*
+ * Types for d_type.
+ */
+#define D_TAPE 1
+#define D_DISK 2
+#define D_TTY 3
+
+/*
* Block device switch table
*/
struct bdevsw {
diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h
index fd5146c..6b8c850 100644
--- a/sys/sys/linedisc.h
+++ b/sys/sys/linedisc.h
@@ -79,6 +79,13 @@ typedef int l_start_t __P((struct tty *tp));
typedef int l_modem_t __P((struct tty *tp, int flag));
/*
+ * Types for d_type.
+ */
+#define D_TAPE 1
+#define D_DISK 2
+#define D_TTY 3
+
+/*
* Block device switch table
*/
struct bdevsw {
diff --git a/sys/sys/lkm.h b/sys/sys/lkm.h
index a594786..f5ff0d9 100644
--- a/sys/sys/lkm.h
+++ b/sys/sys/lkm.h
@@ -222,12 +222,12 @@ struct lkm_table {
sysentp \
}
-#define MOD_VFS(name,vfsslot,vnodeops,vfsconf) \
+#define MOD_VFS(name,vnodeops,vfsconf) \
static struct lkm_vfs _module = { \
LM_VFS, \
LKM_VERSION, \
name, \
- vfsslot, \
+ 0, \
vnodeops, \
vfsconf \
}
diff --git a/sys/sys/lockf.h b/sys/sys/lockf.h
index 4372980..62b3f04 100644
--- a/sys/sys/lockf.h
+++ b/sys/sys/lockf.h
@@ -46,15 +46,19 @@
* the inode structure. Locks are sorted by the starting byte of the lock for
* efficiency.
*/
+TAILQ_HEAD(locklist, lockf);
+
struct lockf {
- short lf_flags; /* Lock semantics: F_POSIX, F_FLOCK, F_WAIT */
- short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
- off_t lf_start; /* The byte # of the start of the lock */
- off_t lf_end; /* The byte # of the end of the lock (-1=EOF)*/
- caddr_t lf_id; /* The id of the resource holding the lock */
- struct lockf **lf_head; /* Back pointer to the head of the lockf list */
- struct lockf *lf_next; /* A pointer to the next lock on this inode */
- struct lockf *lf_block; /* The list of blocked locks */
+ short lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
+ short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
+ off_t lf_start; /* Byte # of the start of the lock */
+ off_t lf_end; /* Byte # of the end of the lock (-1=EOF) */
+ caddr_t lf_id; /* Id of the resource holding the lock */
+ struct lockf **lf_head; /* Back pointer to the head of the locf list */
+ struct inode *lf_inode; /* Back pointer to the inode */
+ struct lockf *lf_next; /* Pointer to the next lock on this inode */
+ struct locklist lf_blkhd; /* List of requests blocked on this lock */
+ TAILQ_ENTRY(lockf) lf_block;/* A request waiting for a lock */
};
/* Maximum length of sleep chains to traverse to try and detect deadlock. */
diff --git a/sys/sys/malloc.h b/sys/sys/malloc.h
index 2b05483..c98dc98 100644
--- a/sys/sys/malloc.h
+++ b/sys/sys/malloc.h
@@ -133,7 +133,8 @@
#define M_GEOM_MOD 86 /* geometry module */
#define M_GEOM_REQ 87 /* geometry request */
#define M_GEOM_MISC 88 /* geometry misc */
-#define M_LAST 89 /* Must be last type + 1 */
+#define M_VFSCONF 89 /* vfsconf structure */
+#define M_LAST 90 /* Must be last type + 1 */
#define INITKMEMNAMES { \
"free", /* 0 M_FREE */ \
@@ -222,6 +223,7 @@
"GEOM mod", /* 86 M_GEOM_MOD */ \
"GEOM req", /* 87 M_GEOM_REQ */ \
"GEOM misc", /* 88 M_GEOM_MISC */ \
+ "VFS conf", /* 89 M_VFSCONF */ \
}
struct kmemstats {
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 3159f4e..90a4fde 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)mount.h 8.13 (Berkeley) 3/27/94
+ * @(#)mount.h 8.21 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -41,8 +41,11 @@
#include <sys/ucred.h>
#endif
#include <sys/queue.h>
+#include <sys/lock.h>
+#include <net/radix.h>
+#include <sys/socket.h> /* XXX for AF_MAX */
-typedef struct fsid { long val[2]; } fsid_t; /* file system id type */
+typedef struct fsid { int32_t val[2]; } fsid_t; /* file system id type */
/*
* File identifier.
@@ -60,7 +63,8 @@ struct fid {
* file system statistics
*/
-#define MNAMELEN 90 /* length of buffer for returned name */
+#define MFSNAMELEN 16 /* length of fs type name, including null */
+#define MNAMELEN 90 /* length of buffer for returned name */
struct statfs {
long f_spare2; /* placeholder */
@@ -75,13 +79,14 @@ struct statfs {
uid_t f_owner; /* user that mounted the filesystem */
int f_type; /* type of filesystem (see below) */
int f_flags; /* copy of mount flags */
- long f_spare[6]; /* spare for later */
+ long f_spare[2]; /* spare for later */
+ char f_fstypename[MFSNAMELEN]; /* fs type name */
char f_mntonname[MNAMELEN]; /* directory on which mounted */
char f_mntfromname[MNAMELEN];/* mounted filesystem */
};
/*
- * File system types.
+ * File system types (for backwards compat with 4.4Lite.)
*/
#define MOUNT_NONE 0
#define MOUNT_UFS 1 /* Fast Filesystem */
@@ -140,11 +145,11 @@ struct mount {
struct vfsconf *mnt_vfc; /* configuration info */
struct vnode *mnt_vnodecovered; /* vnode we mounted on */
struct vnodelst mnt_vnodelist; /* list of vnodes this mount */
+ struct lock mnt_lock; /* mount structure lock */
int mnt_flag; /* flags */
int mnt_maxsymlinklen; /* max size of short symlink */
struct statfs mnt_stat; /* cache of filesystem stats */
qaddr_t mnt_data; /* private data */
-/* struct vfsconf *mnt_vfc; */ /* configuration info */
time_t mnt_time; /* last time written*/
};
@@ -185,58 +190,109 @@ struct mount {
#define MNT_VISFLAGMASK (MNT_RDONLY|MNT_SYNCHRONOUS|MNT_NOEXEC|MNT_NOSUID| \
MNT_NODEV|MNT_UNION|MNT_ASYNC|MNT_EXRDONLY|MNT_EXPORTED| \
MNT_DEFEXPORTED|MNT_EXPORTANON|MNT_EXKERB|MNT_LOCAL| \
- MNT_QUOTA|MNT_ROOTFS|MNT_USER|MNT_NOATIME)
+ MNT_USER|MNT_QUOTA|MNT_ROOTFS|MNT_NOATIME)
/*
- * filesystem control flags.
- *
- * MNT_MLOCK lock the mount entry so that name lookup cannot proceed
- * past the mount point. This keeps the subtree stable during mounts
- * and unmounts.
+ * External filesystem control flags.
*/
#define MNT_UPDATE 0x00010000 /* not a real mount, just an update */
#define MNT_DELEXPORT 0x00020000 /* delete export host lists */
#define MNT_RELOAD 0x00040000 /* reload filesystem data */
#define MNT_FORCE 0x00080000 /* force unmount or readonly change */
-#define MNT_MLOCK 0x00100000 /* lock so that subtree is stable */
-#define MNT_MWAIT 0x00200000 /* someone is waiting for lock */
-#define MNT_MPBUSY 0x00400000 /* scan of mount point in progress */
-#define MNT_MPWANT 0x00800000 /* waiting for mount point */
+/*
+ * Internal filesystem control flags.
+ *
+ * MNT_UNMOUNT locks the mount entry so that name lookup cannot proceed
+ * past the mount point. This keeps the subtree stable during mounts
+ * and unmounts.
+ */
#define MNT_UNMOUNT 0x01000000 /* unmount in progress */
-#define MNT_WANTRDWR 0x02000000 /* want upgrade to read/write */
+#define MNT_MWAIT 0x02000000 /* waiting for unmount to finish */
+#define MNT_WANTRDWR 0x04000000 /* upgrade to read/write requested */
+
+/*
+ * Sysctl CTL_VFS definitions.
+ *
+ * Second level identifier specifies which filesystem. Second level
+ * identifier VFS_GENERIC returns information about all filesystems.
+ */
+#ifdef notyet
+#define VFS_GENERIC 0 /* generic filesystem information */
+#endif
+#define VFS_OVFSCONF 0 /* for backward compatibility w/ FreeBSD 2.1 */
+/*
+ * Third level identifiers for VFS_GENERIC are given below; third
+ * level identifiers for specific filesystems are given in their
+ * mount specific header files.
+ */
+#define VFS_MAXTYPENUM 1 /* int: highest defined filesystem type */
+#define VFS_CONF 2 /* struct: vfsconf for filesystem given
+ as next argument */
+#define VFS_VFSCONF 3 /* for backward compatibility w/ FreeBSD 2.1 */
+
+/*
+ * Flags for various system call interfaces.
+ *
+ * waitfor flags to vfs_sync() and getfsstat()
+ */
+#define MNT_WAIT 1
+#define MNT_NOWAIT 2
+
+/*
+ * Generic file handle
+ */
+struct fhandle {
+ fsid_t fh_fsid; /* File system id of mount point */
+ struct fid fh_fid; /* File sys specific id */
+};
+typedef struct fhandle fhandle_t;
/*
- * used to get configured filesystems information
+ * Export arguments for local filesystem mount calls.
+ */
+struct export_args {
+ int ex_flags; /* export related flags */
+ uid_t ex_root; /* mapping for root uid */
+ struct ucred ex_anon; /* mapping for anonymous user */
+ struct sockaddr *ex_addr; /* net address to which exported */
+ int ex_addrlen; /* and the net address length */
+ struct sockaddr *ex_mask; /* mask of valid bits in saddr */
+ int ex_masklen; /* and the smask length */
+};
+
+/*
+ * Filesystem configuration information. One of these exists for each
+ * type of filesystem supported by the kernel. These are searched at
+ * mount time to identify the requested filesystem.
*/
-#define VFS_MAXNAMELEN 32
struct vfsconf {
- void *vfc_vfsops;
- char vfc_name[VFS_MAXNAMELEN];
- int vfc_index;
- int vfc_refcount;
- int vfc_flags;
+ struct vfsops *vfc_vfsops; /* filesystem operations vector */
+ char vfc_name[MFSNAMELEN]; /* filesystem type name */
+ int vfc_typenum; /* historic filesystem type number */
+ int vfc_refcount; /* number mounted of this type */
+ int vfc_flags; /* permanent flags */
+ struct vfsconf *vfc_next; /* next in list */
};
/*
* NB: these flags refer to IMPLEMENTATION properties, not properties of
* any actual mounts; i.e., it does not make sense to change the flags.
*/
-#define VFCF_STATIC 0x00000001 /* statically compiled into kernel */
-#define VFCF_NETWORK 0x00000002 /* may get data over the network */
-#define VFCF_READONLY 0x00000004 /* writes are not implemented */
-#define VFCF_SYNTHETIC 0x00000008 /* data does not represent real files */
-#define VFCF_LOOPBACK 0x00000010 /* aliases some other mounted FS */
-#define VFCF_UNICODE 0x00000020 /* stores file names as Unicode*/
+#define VFCF_STATIC 0x00010000 /* statically compiled into kernel */
+#define VFCF_NETWORK 0x00020000 /* may get data over the network */
+#define VFCF_READONLY 0x00040000 /* writes are not implemented */
+#define VFCF_SYNTHETIC 0x00080000 /* data does not represent real files */
+#define VFCF_LOOPBACK 0x00100000 /* aliases some other mounted FS */
+#define VFCF_UNICODE 0x00200000 /* stores file names as Unicode*/
-/*
- * Operations supported on mounted file system.
- */
#ifdef KERNEL
-extern int doforce; /* Flag to permit forcible unmounting. */
-extern struct vfsconf void_vfsconf;
-extern struct vfsconf *vfsconf[];
+extern int maxvfsconf; /* highest defined filesystem type */
+extern struct vfsconf *vfsconf; /* head of list of filesystem types */
+/*
+ * Operations supported on mounted file system.
+ */
#ifdef __STDC__
struct nameidata;
struct mbuf;
@@ -262,7 +318,7 @@ struct vfsops {
struct mbuf *nam, struct vnode **vpp,
int *exflagsp, struct ucred **credanonp));
int (*vfs_vptofh) __P((struct vnode *vp, struct fid *fhp));
- int (*vfs_init) __P((void));
+ int (*vfs_init) __P((struct vfsconf *));
};
#define VFS_MOUNT(MP, PATH, DATA, NDP, P) \
@@ -290,10 +346,10 @@ struct vfsops {
#fsname, \
index, \
0, \
- flags \
+ flags, \
}; \
extern struct linker_set MODVNOPS; \
- MOD_VFS(#fsname,index,&MODVNOPS,&_fs_vfsconf); \
+ MOD_VFS(#fsname,&MODVNOPS,&_fs_vfsconf); \
int \
fsname ## _mod(struct lkm_table *lkmtp, int cmd, int ver) { \
DISPATCH(lkmtp, cmd, ver, lkm_nullcmd, lkm_nullcmd, lkm_nullcmd); }
@@ -305,30 +361,13 @@ struct vfsops {
#fsname, \
index, \
0, \
- flags | VFCF_STATIC \
+ flags | VFCF_STATIC, \
}; \
DATA_SET(vfs_set,_fs_vfsconf)
#endif /* VFS_LKM */
#endif /* KERNEL */
-/*
- * Flags for various system call interfaces.
- *
- * waitfor flags to vfs_sync() and getfsstat()
- */
-#define MNT_WAIT 1
-#define MNT_NOWAIT 2
-
-/*
- * Generic file handle
- */
-struct fhandle {
- fsid_t fh_fsid; /* File system id of mount point */
- struct fid fh_fid; /* File sys specific id */
-};
-typedef struct fhandle fhandle_t;
-
#ifdef KERNEL
#include <net/radix.h>
#include <sys/socket.h> /* XXX for AF_MAX */
@@ -349,158 +388,32 @@ struct netexport {
struct netcred ne_defexported; /* Default export */
struct radix_node_head *ne_rtable[AF_MAX+1]; /* Individual exports */
};
-#endif /* KERNEL */
-
-/*
- * Export arguments for local filesystem mount calls.
- */
-struct export_args {
- int ex_flags; /* export related flags */
- uid_t ex_root; /* mapping for root uid */
- struct ucred ex_anon; /* mapping for anonymous user */
- struct sockaddr *ex_addr; /* net address to which exported */
- int ex_addrlen; /* and the net address length */
- struct sockaddr *ex_mask; /* mask of valid bits in saddr */
- int ex_masklen; /* and the smask length */
-};
-
-/*
- * Arguments to mount UFS-based filesystems
- */
-struct ufs_args {
- char *fspec; /* block special device to mount */
- struct export_args export; /* network export information */
-};
-#ifdef MFS
-/*
- * Arguments to mount MFS
- */
-struct mfs_args {
- char *fspec; /* name to export for statfs */
- struct export_args export; /* if exported MFSes are supported */
- caddr_t base; /* base of file system in memory */
- u_long size; /* size of file system */
-};
-#endif /* MFS */
-
-#ifdef MSDOSFS
-/*
- * Arguments to mount MSDOS filesystems.
- */
-struct msdosfs_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 */
-};
-#endif
-
-#ifdef CD9660
-/*
- * Arguments to mount ISO 9660 filesystems.
- */
-struct iso_args {
- char *fspec; /* block special device to mount */
- struct export_args export; /* network export info */
- int flags; /* mounting flags, see below */
-
-};
-#define ISOFSMNT_NORRIP 0x00000001 /* disable Rock Ridge Ext.*/
-#define ISOFSMNT_GENS 0x00000002 /* enable generation numbers */
-#define ISOFSMNT_EXTATT 0x00000004 /* enable extended attributes */
-#endif /* CD9660 */
-
-#ifdef NFS
-/*
- * Arguments to mount NFS
- */
-struct nfs_args {
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
-};
-
-/*
- * NFS mount option flags
- */
-#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
-#define NFSMNT_WSIZE 0x00000002 /* set write size */
-#define NFSMNT_RSIZE 0x00000004 /* set read size */
-#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
-#define NFSMNT_RETRANS 0x00000010 /* set number of request retrys */
-#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
-#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
-#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
-#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
-#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
-#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
-#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
-#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
-#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
-#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
-#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
-#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
-#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
-#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
-#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
-#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
-#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
-#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
-#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
-#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
-#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
-#define NFSMNT_WANTSND 0x02000000 /* Want above */
-#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
-#define NFSMNT_WANTRCV 0x08000000 /* Want above */
-#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
-#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
-#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
-#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
-#endif /* NFS */
-
-#ifdef KERNEL
-extern int (*mountroot) __P((void *));
-extern struct vfsops *mountrootvfsops;
+extern char *mountrootfsname;
/*
* exported vnode operations
*/
int dounmount __P((struct mount *, int, struct proc *));
-struct mount *getvfs __P((fsid_t *)); /* return vfs given fsid */
-void getnewfsid __P((struct mount *, int));
-int vflush __P((struct mount *, struct vnode *, int));
+int vfs_lock __P((struct mount *)); /* lock a vfs */
+void vfs_msync __P((struct mount *, int));
+void vfs_unlock __P((struct mount *)); /* unlock a vfs */
+int vfs_busy __P((struct mount *, int, struct simplelock *, struct proc *));
int vfs_export /* process mount export info */
__P((struct mount *, struct netexport *, struct export_args *));
struct netcred *vfs_export_lookup /* lookup host in fs export list */
__P((struct mount *, struct netexport *, struct mbuf *));
-int vfs_lock __P((struct mount *)); /* lock a vfs */
+void vfs_getnewfsid __P((struct mount *));
+struct mount *vfs_getvfs __P((fsid_t *)); /* return vfs given fsid */
int vfs_mountedon __P((struct vnode *)); /* is a vfs mounted on vp */
-int vfs_mountroot __P((void *)); /* XXX goes away? */
-void vfs_msync __P((struct mount *, int));
-void vfs_unlock __P((struct mount *)); /* unlock a vfs */
+int vfs_mountroot __P((char *));
+int vfs_rootmountalloc __P((char *, char *, struct mount **));
+void vfs_unbusy __P((struct mount *, struct proc *));
void vfs_unmountall __P((void));
-int vfs_busy __P((struct mount *)); /* mark a vfs busy */
-void vfs_unbusy __P((struct mount *)); /* mark a vfs not busy */
extern CIRCLEQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */
-extern struct vfsops *vfssw[]; /* filesystem type table */
+extern struct simplelock mountlist_slock;
-#else /* KERNEL */
+#else /* !KERNEL */
#include <sys/cdefs.h>
@@ -509,7 +422,7 @@ int fstatfs __P((int, struct statfs *));
int getfh __P((const char *, fhandle_t *));
int getfsstat __P((struct statfs *, long, int));
int getmntinfo __P((struct statfs **, int));
-int mount __P((int, const char *, int, void *));
+int mount __P((const char *, const char *, int, void *));
int statfs __P((const char *, struct statfs *));
int unmount __P((const char *, int));
diff --git a/sys/sys/stat.h b/sys/sys/stat.h
index 8d2a83a..cfa097f 100644
--- a/sys/sys/stat.h
+++ b/sys/sys/stat.h
@@ -194,9 +194,7 @@ struct stat {
#endif /* !_POSIX_SOURCE */
-#ifdef KERNEL
-void cvtstat __P((struct stat *, struct ostat *));
-#else /* KERNEL */
+#ifndef KERNEL
#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -214,6 +212,6 @@ int lstat __P((const char *, struct stat *));
#endif
__END_DECLS
-#endif /* KERNEL */
+#endif /* !KERNEL */
#endif /* !_SYS_STAT_H_ */
diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h
index d24e98e..1ca8a15 100644
--- a/sys/sys/syscall-hide.h
+++ b/sys/sys/syscall-hide.h
@@ -197,6 +197,7 @@ HIDE_BSD(__sysctl)
HIDE_BSD(mlock)
HIDE_BSD(munlock)
HIDE_BSD(utrace)
+HIDE_BSD(undelete)
HIDE_BSD(__semctl)
HIDE_BSD(semget)
HIDE_BSD(semop)
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
index b557187..6d7130c 100644
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -191,6 +191,7 @@
#define SYS_mlock 203
#define SYS_munlock 204
#define SYS_utrace 205
+#define SYS_undelete 206
#define SYS___semctl 220
#define SYS_semget 221
#define SYS_semop 222
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index f36b391..ddef56d 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -272,9 +272,6 @@ int sysctl_handle_opaque SYSCTL_HANDLER_ARGS;
/*
* CTL_VFS identifiers
*/
-#define VFS_VFSCONF 0 /* get configured filesystems */
-#define VFS_MAXID 1 /* number of items */
-
#define CTL_VFS_NAMES { \
{ "vfsconf", CTLTYPE_STRUCT }, \
}
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index 7e0dd6c..ec0b4c4 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -42,6 +42,8 @@ struct sysent { /* system call table */
int sy_narg; /* number of arguments */
sy_call_t *sy_call; /* implementing function */
};
+#define SCARG(p,k) ((p)->k) /* get arg from args pointer */
+ /* placeholder till we integrate rest of lite2 syscallargs changes XXX */
struct image_params;
struct trapframe;
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
index 973c12a..8684aaa 100644
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -82,7 +82,7 @@ struct getpid_args {
int dummy;
};
struct mount_args {
- int type;
+ char * type;
char * path;
int flags;
caddr_t data;
@@ -655,6 +655,9 @@ struct utrace_args {
caddr_t addr;
size_t len;
};
+struct undelete_args {
+ char * path;
+};
struct __semctl_args {
int semid;
int semnum;
@@ -777,7 +780,7 @@ int revoke __P((struct proc *, struct revoke_args *, int []));
int symlink __P((struct proc *, struct symlink_args *, int []));
int readlink __P((struct proc *, struct readlink_args *, int []));
int execve __P((struct proc *, struct execve_args *, int []));
-mode_t umask __P((struct proc *, struct umask_args *, int []));
+int umask __P((struct proc *, struct umask_args *, int []));
int chroot __P((struct proc *, struct chroot_args *, int []));
int msync __P((struct proc *, struct msync_args *, int []));
int vfork __P((struct proc *, struct vfork_args *, int []));
@@ -876,6 +879,7 @@ int __sysctl __P((struct proc *, struct sysctl_args *, int []));
int mlock __P((struct proc *, struct mlock_args *, int []));
int munlock __P((struct proc *, struct munlock_args *, int []));
int utrace __P((struct proc *, struct utrace_args *, int []));
+int undelete __P((struct proc *, struct undelete_args *, int []));
int lkmnosys __P((struct proc *, struct nosys_args *, int []));
int __semctl __P((struct proc *, struct __semctl_args *, int []));
int semget __P((struct proc *, struct semget_args *, int []));
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index c99d8e9..e44526d 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -72,7 +72,7 @@ struct tty {
long t_cancc; /* Canonical queue statistics. */
struct clist t_outq; /* Device output queue. */
long t_outcc; /* Output queue statistics. */
- int t_line; /* Interface to device drivers. */
+ u_char t_line; /* Interface to device drivers. */
dev_t t_dev; /* Device. */
int t_state; /* Device and driver (TS*) state. */
int t_flags; /* Tty flags. */
diff --git a/sys/sys/user.h b/sys/sys/user.h
index 17a47df..fe407ff 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -49,7 +49,7 @@
#include <vm/vm.h> /* XXX */
#include <vm/vm_param.h> /* XXX */
#include <vm/pmap.h> /* XXX */
-#include <vm/lock.h> /* XXX */
+#include <sys/lock.h> /* XXX */
#include <vm/vm_map.h> /* XXX */
#else
#include <vm/vm.h> /* XXX */
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index e3b5a4c..f61a056 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -37,6 +37,7 @@
#ifndef _SYS_VNODE_H_
#define _SYS_VNODE_H_
+#include <sys/lock.h>
#include <sys/queue.h>
/*
@@ -70,6 +71,13 @@ LIST_HEAD(buflists, buf);
typedef int vop_t __P((void *));
struct vm_object;
+/*
+ * Reading or writing any of these items requires holding the appropriate lock.
+ * v_freelist is locked by the global vnode_free_list simple lock.
+ * v_mntvnodes is locked by the global mntvnodes simple lock.
+ * v_flag, v_usecount, v_holdcount and v_writecount are
+ * locked by the v_interlock simple lock.
+ */
struct vnode {
u_long v_flag; /* vnode flags (see below) */
int v_usecount; /* reference count of users */
@@ -98,6 +106,8 @@ struct vnode {
int v_clen; /* length of current cluster */
int v_usage; /* Vnode usage counter */
struct vm_object *v_object; /* Place to store VM object */
+ struct simplelock v_interlock; /* lock on usecount and flag */
+ struct lock *v_vnlock; /* used for non-locking fs's */
enum vtagtype v_tag; /* type of underlying data */
void *v_data; /* private data for fs */
};
@@ -109,19 +119,20 @@ struct vnode {
/*
* Vnode flags.
*/
-#define VROOT 0x0001 /* root of its file system */
-#define VTEXT 0x0002 /* vnode is a pure text prototype */
-#define VSYSTEM 0x0004 /* vnode being used by kernel */
-#define VOLOCK 0x0008 /* vnode is locked waiting for an object */
-#define VOWANT 0x0010 /* a process is waiting for VOLOCK */
-#define VXLOCK 0x0100 /* vnode is locked to change underlying type */
-#define VXWANT 0x0200 /* process is waiting for vnode */
-#define VBWAIT 0x0400 /* waiting for output to complete */
-#define VALIASED 0x0800 /* vnode has an alias */
-#define VDIROP 0x1000 /* LFS: vnode is involved in a directory op */
-#define VVMIO 0x2000 /* VMIO flag */
-#define VNINACT 0x4000 /* LFS: skip ufs_inactive() in lfs_vunref */
-#define VAGE 0x8000 /* Insert vnode at head of free list */
+#define VROOT 0x00001 /* root of its file system */
+#define VTEXT 0x00002 /* vnode is a pure text prototype */
+#define VSYSTEM 0x00004 /* vnode being used by kernel */
+#define VISTTY 0x00008 /* vnode represents a tty */
+#define VXLOCK 0x00100 /* vnode is locked to change underlying type */
+#define VXWANT 0x00200 /* process is waiting for vnode */
+#define VBWAIT 0x00400 /* waiting for output to complete */
+#define VALIASED 0x00800 /* vnode has an alias */
+#define VDIROP 0x01000 /* LFS: vnode is involved in a directory op */
+#define VVMIO 0x02000 /* VMIO flag */
+#define VNINACT 0x04000 /* LFS: skip ufs_inactive() in lfs_vunref */
+#define VAGE 0x08000 /* Insert vnode at head of free list */
+#define VOLOCK 0x10000 /* vnode is locked waiting for an object */
+#define VOWANT 0x20000 /* a process is waiting for VOLOCK */
/*
* Vnode attributes. A field value of VNOVAL represents a field whose value
@@ -150,9 +161,10 @@ struct vattr {
};
/*
- * Flags for va_cflags.
+ * Flags for va_vaflags.
*/
#define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */
+#define VA_EXCLUSIVE 0x02 /* exclusive create request */
/*
* Flags for ioflag.
@@ -199,6 +211,7 @@ extern int vttoif_tab[];
#define DOCLOSE 0x0008 /* vclean: close active files */
#define V_SAVE 0x0001 /* vinvalbuf: sync file first */
#define V_SAVEMETA 0x0002 /* vinvalbuf: leave indirect blocks */
+#define REVOKEALL 0x0001 /* vop_revoke: revoke all aliases */
#ifdef DIAGNOSTIC
#define HOLDRELE(vp) holdrele(vp)
@@ -208,12 +221,28 @@ extern int vttoif_tab[];
void holdrele __P((struct vnode *));
void vhold __P((struct vnode *));
+void vref __P((struct vnode *vp));
#else
-#define HOLDRELE(vp) (vp)->v_holdcnt-- /* decrease buf or page ref */
#define VATTR_NULL(vap) (*(vap) = va_null) /* initialize a vattr */
-#define VHOLD(vp) (vp)->v_holdcnt++ /* increase buf or page ref */
+#define HOLDRELE(vp) holdrele(vp) /* decrease buf or page ref */
+static __inline void
+holdrele(struct vnode *vp)
+{
+ simple_lock(&vp->v_interlock);
+ vp->v_holdcnt--;
+ simple_unlock(&vp->v_interlock);
+}
+#define VHOLD(vp) vhold(vp) /* increase buf or page ref */
+static __inline void
+vhold(struct vnode *vp)
+{
+ simple_lock(&vp->v_interlock);
+ vp->v_holdcnt++;
+ simple_unlock(&vp->v_interlock);
+}
#define VREF(vp) vref(vp) /* increase reference */
-#endif
+void vref __P((struct vnode *vp));
+#endif /* DIAGNOSTIC */
#define NULLVP ((struct vnode *)NULL)
@@ -237,24 +266,20 @@ extern struct vattr va_null; /* predefined null vattr structure */
#define LEASE_READ 0x1 /* Check lease for readers */
#define LEASE_WRITE 0x2 /* Check lease for modifiers */
-extern void (*lease_check) __P((struct vnode *vp, struct proc *p,
- struct ucred *ucred, int flag));
+
extern void (*lease_updatetime) __P((int deltat));
#ifdef NFS
#ifdef NQNFS
-#define LEASE_CHECK(vp, p, cred, flag) lease_check((vp), (p), (cred), (flag))
#define LEASE_UPDATETIME(dt) lease_updatetime(dt)
#else
-#define LEASE_CHECK(vp, p, cred, flag)
#define LEASE_UPDATETIME(dt)
#endif /* NQNFS */
#else
-#define LEASE_CHECK(vp, p, cred, flag) \
- do { if(lease_check) lease_check((vp), (p), (cred), (flag)); } while(0)
#define LEASE_UPDATETIME(dt) \
do { if(lease_updatetime) lease_updatetime(dt); } while(0)
#endif /* NFS */
+
#endif /* KERNEL */
@@ -313,6 +338,10 @@ struct vnodeop_desc {
*/
extern struct vnodeop_desc *vnodeop_descs[];
+/*
+ * Interlock for scanning list of vnodes attached to a mountpoint
+ */
+extern struct simplelock mntvnode_slock;
/*
* This macro is very helpful in defining those offsets in the vdesc struct.
@@ -382,6 +411,7 @@ struct componentname;
struct file;
struct mount;
struct nameidata;
+struct ostat;
struct proc;
struct stat;
struct ucred;
@@ -390,6 +420,8 @@ struct vattr;
struct vnode;
struct vop_bwrite_args;
+extern int (*lease_check_hook) __P((struct vop_lease_args *));
+
int bdevvp __P((dev_t dev, struct vnode **vpp));
/* cache_* may belong in namei.h. */
void cache_enter __P((struct vnode *dvp, struct vnode *vp,
@@ -398,23 +430,28 @@ int cache_lookup __P((struct vnode *dvp, struct vnode **vpp,
struct componentname *cnp));
void cache_purge __P((struct vnode *vp));
void cache_purgevfs __P((struct mount *mp));
-struct vnode *
- checkalias __P((struct vnode *vp, dev_t nvp_rdev, struct mount *mp));
+void cvtstat __P((struct stat *st, struct ostat *ost));
int getnewvnode __P((enum vtagtype tag,
struct mount *mp, vop_t **vops, struct vnode **vpp));
void insmntque __P((struct vnode *vp, struct mount *mp));
+int lease_check __P((struct vop_lease_args *ap));
void vattr_null __P((struct vattr *vap));
int vcount __P((struct vnode *vp));
int vfinddev __P((dev_t dev, enum vtype type, struct vnode **vpp));
void vfs_opv_init __P((struct vnodeopv_desc **them));
-int vget __P((struct vnode *vp, int lockflag));
+int vflush __P((struct mount *mp, struct vnode *skipvp, int flags));
+int vget __P((struct vnode *vp, int lockflag, struct proc *p));
void vgone __P((struct vnode *vp));
void vgoneall __P((struct vnode *vp));
int vinvalbuf __P((struct vnode *vp, int save, struct ucred *cred,
struct proc *p, int slpflag, int slptimeo));
+void vprint __P((char *label, struct vnode *vp));
+int vrecycle __P((struct vnode *vp, struct simplelock *inter_lkp,
+ struct proc *p));
int vn_bwrite __P((struct vop_bwrite_args *ap));
int vn_close __P((struct vnode *vp,
int flags, struct ucred *cred, struct proc *p));
+int vn_lock __P((struct vnode *vp, int flags, struct proc *p));
int vn_open __P((struct nameidata *ndp, int fmode, int cmode));
int vn_rdwr __P((enum uio_rw rw, struct vnode *vp, caddr_t base,
int len, off_t offset, enum uio_seg segflg, int ioflg,
@@ -423,9 +460,13 @@ int vn_stat __P((struct vnode *vp, struct stat *sb, struct proc *p));
int vfs_object_create __P((struct vnode *vp, struct proc *p,
struct ucred *cred, int waslocked));
int vn_writechk __P((struct vnode *vp));
-void vprint __P((char *label, struct vnode *vp));
+int vop_noislocked __P((struct vop_islocked_args *));
+int vop_nolock __P((struct vop_lock_args *));
+int vop_nounlock __P((struct vop_unlock_args *));
+int vop_revoke __P((struct vop_revoke_args *));
+struct vnode *
+ checkalias __P((struct vnode *vp, dev_t nvp_rdev, struct mount *mp));
void vput __P((struct vnode *vp));
-void vref __P((struct vnode *vp));
void vrele __P((struct vnode *vp));
#endif /* KERNEL */
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index e1272ab..4787c1c 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94
+ * @(#)ffs_alloc.c 8.18 (Berkeley) 5/26/95
* $FreeBSD$
*/
@@ -57,23 +57,23 @@
extern u_long nextgennumber;
-typedef daddr_t allocfcn_t __P((struct inode *ip, int cg, daddr_t bpref,
- int size));
+typedef ufs_daddr_t allocfcn_t __P((struct inode *ip, int cg, ufs_daddr_t bpref,
+ int size));
-static daddr_t ffs_alloccg __P((struct inode *, int, daddr_t, int));
-static daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, daddr_t));
-#ifdef notyet
-static daddr_t ffs_clusteralloc __P((struct inode *, int, daddr_t, int));
-#endif
+static ufs_daddr_t ffs_alloccg __P((struct inode *, int, ufs_daddr_t, int));
+static ufs_daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, ufs_daddr_t));
+static void ffs_clusteracct __P((struct fs *, struct cg *, ufs_daddr_t,
+ int));
+static ufs_daddr_t ffs_clusteralloc __P((struct inode *, int, ufs_daddr_t,
+ int));
static ino_t ffs_dirpref __P((struct fs *));
-static daddr_t ffs_fragextend __P((struct inode *, int, long, int, int));
+static ufs_daddr_t ffs_fragextend __P((struct inode *, int, long, int, int));
static void ffs_fserr __P((struct fs *, u_int, char *));
static u_long ffs_hashalloc
__P((struct inode *, int, long, int, allocfcn_t *));
-static ino_t ffs_nodealloccg __P((struct inode *, int, daddr_t, int));
-static daddr_t ffs_mapsearch __P((struct fs *, struct cg *, daddr_t, int));
-
-static void ffs_clusteracct __P((struct fs *, struct cg *, daddr_t, int));
+static ino_t ffs_nodealloccg __P((struct inode *, int, ufs_daddr_t, int));
+static ufs_daddr_t ffs_mapsearch __P((struct fs *, struct cg *, ufs_daddr_t,
+ int));
/*
* Allocate a block in the file system.
@@ -97,19 +97,18 @@ static void ffs_clusteracct __P((struct fs *, struct cg *, daddr_t, int));
int
ffs_alloc(ip, lbn, bpref, size, cred, bnp)
register struct inode *ip;
- daddr_t lbn, bpref;
+ ufs_daddr_t lbn, bpref;
int size;
struct ucred *cred;
- daddr_t *bnp;
+ ufs_daddr_t *bnp;
{
register struct fs *fs;
- daddr_t bno;
+ ufs_daddr_t bno;
int cg;
#ifdef QUOTA
int error;
#endif
-
*bnp = 0;
fs = ip->i_fs;
#ifdef DIAGNOSTIC
@@ -136,7 +135,8 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp)
cg = ino_to_cg(fs, ip->i_number);
else
cg = dtog(fs, bpref);
- bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size, ffs_alloccg);
+ bno = (ufs_daddr_t)ffs_hashalloc(ip, cg, (long)bpref, size,
+ ffs_alloccg);
if (bno > 0) {
ip->i_blocks += btodb(size);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
@@ -166,8 +166,8 @@ nospace:
int
ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
register struct inode *ip;
- daddr_t lbprev;
- daddr_t bpref;
+ ufs_daddr_t lbprev;
+ ufs_daddr_t bpref;
int osize, nsize;
struct ucred *cred;
struct buf **bpp;
@@ -175,7 +175,7 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
register struct fs *fs;
struct buf *bp;
int cg, request, error;
- daddr_t bprev, bno;
+ ufs_daddr_t bprev, bno;
*bpp = 0;
fs = ip->i_fs;
@@ -285,7 +285,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
panic("ffs_realloccg: bad optim");
/* NOTREACHED */
}
- bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, ffs_alloccg);
+ bno = (ufs_daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request,
+ ffs_alloccg);
if (bno > 0) {
bp->b_blkno = fsbtodb(fs, bno);
ffs_blkfree(ip, bprev, (long)osize);
@@ -331,7 +332,13 @@ nospace:
* the previous block allocation will be used.
*/
static int doasyncfree = 1;
-SYSCTL_INT(_debug, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
+SYSCTL_INT(_vfs_ffs, FFS_ASYNCFREE, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, "");
+
+int doreallocblks = 1;
+SYSCTL_INT(_vfs_ffs, FFS_REALLOCBLKS, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, "");
+
+static int prtrealloc = 0;
+
int
ffs_reallocblks(ap)
struct vop_reallocblks_args /* {
@@ -346,13 +353,15 @@ ffs_reallocblks(ap)
struct inode *ip;
struct vnode *vp;
struct buf *sbp, *ebp;
- daddr_t *bap, *sbap, *ebap = 0;
+ ufs_daddr_t *bap, *sbap, *ebap = 0;
struct cluster_save *buflist;
- daddr_t start_lbn, end_lbn, soff, newblk, blkno;
+ ufs_daddr_t start_lbn, end_lbn, soff, newblk, blkno;
struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp;
int i, len, start_lvl, end_lvl, pref, ssize;
struct timeval tv;
+ if (doreallocblks == 0)
+ return (ENOSPC);
vp = ap->a_vp;
ip = VTOI(vp);
fs = ip->i_fs;
@@ -363,9 +372,18 @@ ffs_reallocblks(ap)
start_lbn = buflist->bs_children[0]->b_lblkno;
end_lbn = start_lbn + len - 1;
#ifdef DIAGNOSTIC
+ for (i = 0; i < len; i++)
+ if (!ffs_checkblk(ip,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
+ panic("ffs_reallocblks: unallocated block 1");
for (i = 1; i < len; i++)
if (buflist->bs_children[i]->b_lblkno != start_lbn + i)
- panic("ffs_reallocblks: non-cluster");
+ panic("ffs_reallocblks: non-logical cluster");
+ blkno = buflist->bs_children[0]->b_blkno;
+ ssize = fsbtodb(fs, fs->fs_frag);
+ for (i = 1; i < len - 1; i++)
+ if (buflist->bs_children[i]->b_blkno != blkno + (i * ssize))
+ panic("ffs_reallocblks: non-physical cluster %d", i);
#endif
/*
* If the latest allocation is in a new cylinder group, assume that
@@ -390,7 +408,7 @@ ffs_reallocblks(ap)
brelse(sbp);
return (ENOSPC);
}
- sbap = (daddr_t *)sbp->b_data;
+ sbap = (ufs_daddr_t *)sbp->b_data;
soff = idp->in_off;
}
/*
@@ -410,12 +428,12 @@ ffs_reallocblks(ap)
ssize = len - (idp->in_off + 1);
if (bread(vp, idp->in_lbn, (int)fs->fs_bsize, NOCRED, &ebp))
goto fail;
- ebap = (daddr_t *)ebp->b_data;
+ ebap = (ufs_daddr_t *)ebp->b_data;
}
/*
* Search the block map looking for an allocation of the desired size.
*/
- if ((newblk = (daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref,
+ if ((newblk = (ufs_daddr_t)ffs_hashalloc(ip, dtog(fs, pref), (long)pref,
len, ffs_clusteralloc)) == 0)
goto fail;
/*
@@ -425,14 +443,26 @@ ffs_reallocblks(ap)
* block pointers in the inode and indirect blocks associated
* with the file.
*/
+#ifdef DEBUG
+ if (prtrealloc)
+ printf("realloc: ino %d, lbns %d-%d\n\told:", ip->i_number,
+ start_lbn, end_lbn);
+#endif
blkno = newblk;
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
if (i == ssize)
bap = ebap;
#ifdef DIAGNOSTIC
- if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap))
+ if (!ffs_checkblk(ip,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
+ panic("ffs_reallocblks: unallocated block 2");
+ if (dbtofsb(fs, buflist->bs_children[i]->b_blkno) != *bap)
panic("ffs_reallocblks: alloc mismatch");
#endif
+#ifdef DEBUG
+ if (prtrealloc)
+ printf(" %d,", *bap);
+#endif
*bap++ = blkno;
}
/*
@@ -469,11 +499,28 @@ ffs_reallocblks(ap)
/*
* Last, free the old blocks and assign the new blocks to the buffers.
*/
+#ifdef DEBUG
+ if (prtrealloc)
+ printf("\n\tnew:");
+#endif
for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) {
ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
fs->fs_bsize);
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
+#ifdef DEBUG
+ if (!ffs_checkblk(ip,
+ dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
+ panic("ffs_reallocblks: unallocated block 3");
+ if (prtrealloc)
+ printf(" %d,", blkno);
+#endif
+ }
+#ifdef DEBUG
+ if (prtrealloc) {
+ prtrealloc--;
+ printf("\n");
}
+#endif
return (0);
fail:
@@ -615,17 +662,17 @@ ffs_dirpref(fs)
* fs_rotdelay milliseconds. This is to allow time for the processor to
* schedule another I/O transfer.
*/
-daddr_t
+ufs_daddr_t
ffs_blkpref(ip, lbn, indx, bap)
struct inode *ip;
- daddr_t lbn;
+ ufs_daddr_t lbn;
int indx;
- daddr_t *bap;
+ ufs_daddr_t *bap;
{
register struct fs *fs;
register int cg;
int avgbfree, startcg;
- daddr_t nextblk;
+ ufs_daddr_t nextblk;
fs = ip->i_fs;
if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
@@ -740,7 +787,7 @@ ffs_hashalloc(ip, cg, pref, size, allocator)
* Check to see if the necessary fragments are available, and
* if they are, allocate them.
*/
-static daddr_t
+static ufs_daddr_t
ffs_fragextend(ip, cg, bprev, osize, nsize)
struct inode *ip;
int cg;
@@ -810,11 +857,11 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
* Check to see if a block of the appropriate size is available,
* and if it is, allocate it.
*/
-static daddr_t
+static ufs_daddr_t
ffs_alloccg(ip, cg, bpref, size)
struct inode *ip;
int cg;
- daddr_t bpref;
+ ufs_daddr_t bpref;
int size;
{
register struct fs *fs;
@@ -904,13 +951,13 @@ ffs_alloccg(ip, cg, bpref, size)
* Note that this routine only allocates fs_bsize blocks; these
* blocks may be fragmented by the routine that allocates them.
*/
-static daddr_t
+static ufs_daddr_t
ffs_alloccgblk(fs, cgp, bpref)
register struct fs *fs;
register struct cg *cgp;
- daddr_t bpref;
+ ufs_daddr_t bpref;
{
- daddr_t bno, blkno;
+ ufs_daddr_t bno, blkno;
int cylno, pos, delta;
short *cylbp;
register int i;
@@ -1016,21 +1063,22 @@ gotit:
* are multiple choices in the same cylinder group. Instead we just
* take the first one that we find following bpref.
*/
-static daddr_t
+static ufs_daddr_t
ffs_clusteralloc(ip, cg, bpref, len)
struct inode *ip;
int cg;
- daddr_t bpref;
+ ufs_daddr_t bpref;
int len;
{
register struct fs *fs;
register struct cg *cgp;
struct buf *bp;
- int i, run, bno, bit, map;
+ int i, got, run, bno, bit, map;
u_char *mapp;
+ int32_t *lp;
fs = ip->i_fs;
- if (fs->fs_cs(fs, cg).cs_nbfree < len)
+ if (fs->fs_maxcluster[cg] < len)
return (NULL);
if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
NOCRED, &bp))
@@ -1042,11 +1090,25 @@ ffs_clusteralloc(ip, cg, bpref, len)
* Check to see if a cluster of the needed size (or bigger) is
* available in this cylinder group.
*/
+ lp = &cg_clustersum(cgp)[len];
for (i = len; i <= fs->fs_contigsumsize; i++)
- if (cg_clustersum(cgp)[i] > 0)
+ if (*lp++ > 0)
break;
- if (i > fs->fs_contigsumsize)
+ if (i > fs->fs_contigsumsize) {
+ /*
+ * This is the first time looking for a cluster in this
+ * cylinder group. Update the cluster summary information
+ * to reflect the true maximum sized cluster so that
+ * future cluster allocation requests can avoid reading
+ * the cylinder group map only to find no clusters.
+ */
+ lp = &cg_clustersum(cgp)[len - 1];
+ for (i = len - 1; i > 0; i--)
+ if (*lp-- > 0)
+ break;
+ fs->fs_maxcluster[cg] = i;
goto fail;
+ }
/*
* Search the cluster map to find a big enough cluster.
* We take the first one that we find, even if it is larger
@@ -1065,7 +1127,7 @@ ffs_clusteralloc(ip, cg, bpref, len)
mapp = &cg_clustersfree(cgp)[bpref / NBBY];
map = *mapp++;
bit = 1 << (bpref % NBBY);
- for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) {
+ for (run = 0, got = bpref; got < cgp->cg_nclusterblks; got++) {
if ((map & bit) == 0) {
run = 0;
} else {
@@ -1073,22 +1135,27 @@ ffs_clusteralloc(ip, cg, bpref, len)
if (run == len)
break;
}
- if ((i & (NBBY - 1)) != (NBBY - 1)) {
+ if ((got & (NBBY - 1)) != (NBBY - 1)) {
bit <<= 1;
} else {
map = *mapp++;
bit = 1;
}
}
- if (i == cgp->cg_nclusterblks)
+ if (got == cgp->cg_nclusterblks)
goto fail;
/*
* Allocate the cluster that we have found.
*/
- bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1);
+ for (i = 1; i <= len; i++)
+ if (!ffs_isblock(fs, cg_blksfree(cgp), got - run + i))
+ panic("ffs_clusteralloc: map mismatch");
+ bno = cg * fs->fs_fpg + blkstofrags(fs, got - run + 1);
+ if (dtog(fs, bno) != cg)
+ panic("ffs_clusteralloc: allocated out of group");
len = blkstofrags(fs, len);
for (i = 0; i < len; i += fs->fs_frag)
- if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i)
+ if ((got = ffs_alloccgblk(fs, cgp, bno + i)) != bno + i)
panic("ffs_clusteralloc: lost block");
bdwrite(bp);
return (bno);
@@ -1112,7 +1179,7 @@ static ino_t
ffs_nodealloccg(ip, cg, ipref, mode)
struct inode *ip;
int cg;
- daddr_t ipref;
+ ufs_daddr_t ipref;
int mode;
{
register struct fs *fs;
@@ -1191,13 +1258,13 @@ gotit:
void
ffs_blkfree(ip, bno, size)
register struct inode *ip;
- daddr_t bno;
+ ufs_daddr_t bno;
long size;
{
register struct fs *fs;
register struct cg *cgp;
struct buf *bp;
- daddr_t blkno;
+ ufs_daddr_t blkno;
int i, error, cg, blk, frags, bbase;
fs = ip->i_fs;
@@ -1288,6 +1355,56 @@ ffs_blkfree(ip, bno, size)
bdwrite(bp);
}
+#ifdef DIAGNOSTIC
+/*
+ * Verify allocation of a block or fragment. Returns true if block or
+ * fragment is allocated, false if it is free.
+ */
+ffs_checkblk(ip, bno, size)
+ struct inode *ip;
+ ufs_daddr_t bno;
+ long size;
+{
+ struct fs *fs;
+ struct cg *cgp;
+ struct buf *bp;
+ int i, error, frags, free;
+
+ fs = ip->i_fs;
+ if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
+ printf("bsize = %d, size = %d, fs = %s\n",
+ fs->fs_bsize, size, fs->fs_fsmnt);
+ panic("checkblk: bad size");
+ }
+ if ((u_int)bno >= fs->fs_size)
+ panic("checkblk: bad block %d", bno);
+ error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, dtog(fs, bno))),
+ (int)fs->fs_cgsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return;
+ }
+ cgp = (struct cg *)bp->b_data;
+ if (!cg_chkmagic(cgp)) {
+ brelse(bp);
+ return;
+ }
+ bno = dtogd(fs, bno);
+ if (size == fs->fs_bsize) {
+ free = ffs_isblock(fs, cg_blksfree(cgp), fragstoblks(fs, bno));
+ } else {
+ frags = numfrags(fs, size);
+ for (free = 0, i = 0; i < frags; i++)
+ if (isset(cg_blksfree(cgp), bno + i))
+ free++;
+ if (free != 0 && free != frags)
+ panic("checkblk: partially free fragment");
+ }
+ brelse(bp);
+ return (!free);
+}
+#endif /* DIAGNOSTIC */
+
/*
* Free an inode.
*
@@ -1355,14 +1472,14 @@ ffs_vfree(ap)
* It is a panic if a request is made to find a block if none are
* available.
*/
-static daddr_t
+static ufs_daddr_t
ffs_mapsearch(fs, cgp, bpref, allocsiz)
register struct fs *fs;
register struct cg *cgp;
- daddr_t bpref;
+ ufs_daddr_t bpref;
int allocsiz;
{
- daddr_t bno;
+ ufs_daddr_t bno;
int start, len, loc, i;
int blk, field, subfield, pos;
@@ -1423,10 +1540,11 @@ static void
ffs_clusteracct(fs, cgp, blkno, cnt)
struct fs *fs;
struct cg *cgp;
- daddr_t blkno;
+ ufs_daddr_t blkno;
int cnt;
{
- long *sump;
+ int32_t *sump;
+ int32_t *lp;
u_char *freemapp, *mapp;
int i, start, end, forw, back, map, bit;
@@ -1495,6 +1613,14 @@ ffs_clusteracct(fs, cgp, blkno, cnt)
sump[back] -= cnt;
if (forw > 0)
sump[forw] -= cnt;
+ /*
+ * Update cluster summary information.
+ */
+ lp = &sump[fs->fs_contigsumsize];
+ for (i = fs->fs_contigsumsize; i > 0; i--)
+ if (*lp-- > 0)
+ break;
+ fs->fs_maxcluster[cgp->cg_cgx] = i;
}
/*
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
index 4d382fa..5d7d798 100644
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
+ * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
* $FreeBSD$
*/
@@ -56,27 +56,27 @@
* the inode and the logical block number in a file.
*/
int
-ffs_balloc(ip, bn, size, cred, bpp, flags)
+ffs_balloc(ip, lbn, size, cred, bpp, flags)
register struct inode *ip;
- register daddr_t bn;
+ register ufs_daddr_t lbn;
int size;
struct ucred *cred;
struct buf **bpp;
int flags;
{
register struct fs *fs;
- register daddr_t nb;
+ register ufs_daddr_t nb;
struct buf *bp, *nbp;
struct vnode *vp = ITOV(ip);
struct indir indirs[NIADDR + 2];
- daddr_t newb, lbn, *bap, pref;
- int osize, nsize, num, i, error;
+ ufs_daddr_t newb, *bap, pref;
+ int deallocated, osize, nsize, num, i, error;
+ ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
*bpp = NULL;
- if (bn < 0)
+ if (lbn < 0)
return (EFBIG);
fs = ip->i_fs;
- lbn = bn;
/*
* If the next write will extend the file into a new block,
@@ -84,7 +84,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
* this fragment has to be extended to be a full block.
*/
nb = lblkno(fs, ip->i_size);
- if (nb < NDADDR && nb < bn) {
+ if (nb < NDADDR && nb < lbn) {
osize = blksize(fs, ip, nb);
if (osize < fs->fs_bsize && osize > 0) {
error = ffs_realloccg(ip, nb,
@@ -104,10 +104,10 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
/*
* The first NDADDR blocks are direct blocks
*/
- if (bn < NDADDR) {
- nb = ip->i_db[bn];
- if (nb != 0 && ip->i_size >= (bn + 1) * fs->fs_bsize) {
- error = bread(vp, bn, fs->fs_bsize, NOCRED, &bp);
+ if (lbn < NDADDR) {
+ nb = ip->i_db[lbn];
+ if (nb != 0 && ip->i_size >= (lbn + 1) * fs->fs_bsize) {
+ error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
@@ -123,35 +123,35 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
osize = fragroundup(fs, blkoff(fs, ip->i_size));
nsize = fragroundup(fs, size);
if (nsize <= osize) {
- error = bread(vp, bn, osize, NOCRED, &bp);
+ error = bread(vp, lbn, osize, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
} else {
- error = ffs_realloccg(ip, bn,
- ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
- osize, nsize, cred, &bp);
+ error = ffs_realloccg(ip, lbn,
+ ffs_blkpref(ip, lbn, (int)lbn,
+ &ip->i_db[0]), osize, nsize, cred, &bp);
if (error)
return (error);
}
} else {
- if (ip->i_size < (bn + 1) * fs->fs_bsize)
+ if (ip->i_size < (lbn + 1) * fs->fs_bsize)
nsize = fragroundup(fs, size);
else
nsize = fs->fs_bsize;
- error = ffs_alloc(ip, bn,
- ffs_blkpref(ip, bn, (int)bn, &ip->i_db[0]),
+ error = ffs_alloc(ip, lbn,
+ ffs_blkpref(ip, lbn, (int)lbn, &ip->i_db[0]),
nsize, cred, &newb);
if (error)
return (error);
- bp = getblk(vp, bn, nsize, 0, 0);
+ bp = getblk(vp, lbn, nsize, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & B_CLRBUF)
vfs_bio_clrbuf(bp);
}
- ip->i_db[bn] = dbtofsb(fs, bp->b_blkno);
+ ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bpp = bp;
return (0);
@@ -160,8 +160,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
* Determine the number of levels of indirection.
*/
pref = 0;
- error = ufs_getlbns(vp, bn, indirs, &num);
- if (error)
+ if (error = ufs_getlbns(vp, lbn, indirs, &num))
return(error);
#ifdef DIAGNOSTIC
if (num < 1)
@@ -172,26 +171,26 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
*/
--num;
nb = ip->i_ib[indirs[0].in_off];
+ allocib = NULL;
+ allocblk = allociblk;
if (nb == 0) {
- pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
- error = ffs_alloc(ip, lbn, pref,
- (int)fs->fs_bsize, cred, &newb);
- if (error)
+ pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
+ if (error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
+ cred, &newb))
return (error);
nb = newb;
+ *allocblk++ = nb;
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
- bp->b_blkno = fsbtodb(fs, newb);
+ bp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(bp);
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
- error = bwrite(bp);
- if (error) {
- ffs_blkfree(ip, nb, fs->fs_bsize);
- return (error);
- }
- ip->i_ib[indirs[0].in_off] = newb;
+ if (error = bwrite(bp))
+ goto fail;
+ allocib = &ip->i_ib[indirs[0].in_off];
+ *allocib = nb;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
/*
@@ -202,9 +201,9 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
indirs[i].in_lbn, (int)fs->fs_bsize, NOCRED, &bp);
if (error) {
brelse(bp);
- return (error);
+ goto fail;
}
- bap = (daddr_t *)bp->b_data;
+ bap = (ufs_daddr_t *)bp->b_data;
nb = bap[indirs[i].in_off];
if (i == num)
break;
@@ -214,14 +213,14 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
continue;
}
if (pref == 0)
- pref = ffs_blkpref(ip, lbn, 0, (daddr_t *)0);
- error =
- ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb);
- if (error) {
+ pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
+ if (error =
+ ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) {
brelse(bp);
- return (error);
+ goto fail;
}
nb = newb;
+ *allocblk++ = nb;
nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(nbp);
@@ -229,11 +228,9 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
* Write synchronously so that indirect blocks
* never point at garbage.
*/
- error = bwrite(nbp);
- if (error) {
- ffs_blkfree(ip, nb, fs->fs_bsize);
+ if (error = bwrite(nbp)) {
brelse(bp);
- return (error);
+ goto fail;
}
bap[indirs[i - 1].in_off] = nb;
/*
@@ -255,9 +252,10 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
lbn, pref, (int)fs->fs_bsize, cred, &newb);
if (error) {
brelse(bp);
- return (error);
+ goto fail;
}
nb = newb;
+ *allocblk++ = nb;
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
if (flags & B_CLRBUF)
@@ -280,7 +278,7 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
if (error) {
brelse(nbp);
- return (error);
+ goto fail;
}
} else {
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
@@ -288,4 +286,26 @@ ffs_balloc(ip, bn, size, cred, bpp, flags)
}
*bpp = nbp;
return (0);
+fail:
+ /*
+ * If we have failed part way through block allocation, we
+ * have to deallocate any indirect blocks that we have allocated.
+ */
+ for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
+ ffs_blkfree(ip, *blkp, fs->fs_bsize);
+ deallocated += fs->fs_bsize;
+ }
+ if (allocib != NULL)
+ *allocib = 0;
+ if (deallocated) {
+#ifdef QUOTA
+ /*
+ * Restore user's disk quota because allocation failed.
+ */
+ (void) chkdq(ip, (long)-btodb(deallocated), cred, FORCE);
+#endif
+ ip->i_blocks -= btodb(deallocated);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ }
+ return (error);
}
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index c0ef7c4..f168d01 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -30,13 +30,31 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_extern.h 8.3 (Berkeley) 4/16/94
+ * @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95
* $FreeBSD$
*/
#ifndef _UFS_FFS_EXTERN_H
#define _UFS_FFS_EXTERN_H
+/*
+ * Sysctl values for the fast filesystem.
+ */
+#define FFS_CLUSTERREAD 1 /* cluster reading enabled */
+#define FFS_CLUSTERWRITE 2 /* cluster writing enabled */
+#define FFS_REALLOCBLKS 3 /* block reallocation enabled */
+#define FFS_ASYNCFREE 4 /* asynchronous block freeing enabled */
+#define FFS_MAXID 5 /* number of valid ffs ids */
+
+#define FFS_NAMES { \
+ { 0, 0 }, \
+ { "doclusterread", CTLTYPE_INT }, \
+ { "doclusterwrite", CTLTYPE_INT }, \
+ { "doreallocblks", CTLTYPE_INT }, \
+ { "doasyncfree", CTLTYPE_INT }, \
+}
+
+struct buf;
struct fid;
struct fs;
struct inode;
@@ -44,29 +62,28 @@ struct mbuf;
struct mount;
struct statfs;
struct vnode;
+struct mbuf;
int ffs_alloc __P((struct inode *,
- daddr_t, daddr_t, int, struct ucred *, daddr_t *));
+ ufs_daddr_t, ufs_daddr_t, int, struct ucred *, ufs_daddr_t *));
int ffs_balloc __P((struct inode *,
- daddr_t, int, struct ucred *, struct buf **, int));
+ ufs_daddr_t, int, struct ucred *, struct buf **, int));
int ffs_blkatoff __P((struct vop_blkatoff_args *));
-void ffs_blkfree __P((struct inode *, daddr_t, long));
-daddr_t ffs_blkpref __P((struct inode *, daddr_t, int, daddr_t *));
+void ffs_blkfree __P((struct inode *, ufs_daddr_t, long));
+ufs_daddr_t ffs_blkpref __P((struct inode *, ufs_daddr_t, int, ufs_daddr_t *));
int ffs_bmap __P((struct vop_bmap_args *));
-void ffs_clrblock __P((struct fs *, u_char *, daddr_t));
+void ffs_clrblock __P((struct fs *, u_char *, ufs_daddr_t));
int ffs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
struct vnode **, int *, struct ucred **));
-int ffs_flushfiles __P((struct mount *, int, struct proc *));
-void ffs_fragacct __P((struct fs *, int, long [], int));
-int ffs_init __P((void));
-int ffs_isblock __P((struct fs *, u_char *, daddr_t));
+void ffs_fragacct __P((struct fs *, int, int32_t [], int));
+int ffs_isblock __P((struct fs *, u_char *, ufs_daddr_t));
int ffs_mountfs __P((struct vnode *, struct mount *, struct proc *));
int ffs_mountroot __P((void));
int ffs_reallocblks __P((struct vop_reallocblks_args *));
int ffs_realloccg __P((struct inode *,
- daddr_t, daddr_t, int, int, struct ucred *, struct buf **));
+ ufs_daddr_t, ufs_daddr_t, int, int, struct ucred *, struct buf **));
int ffs_reclaim __P((struct vop_reclaim_args *));
-void ffs_setblock __P((struct fs *, u_char *, daddr_t));
+void ffs_setblock __P((struct fs *, u_char *, ufs_daddr_t));
int ffs_statfs __P((struct mount *, struct statfs *, struct proc *));
int ffs_sync __P((struct mount *, int, struct ucred *, struct proc *));
int ffs_truncate __P((struct vop_truncate_args *));
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index ba3e82a..f7af3f3 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_inode.c 8.5 (Berkeley) 12/30/93
+ * @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95
* $FreeBSD$
*/
@@ -59,14 +59,8 @@
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
-static int ffs_indirtrunc __P((struct inode *, daddr_t, daddr_t, daddr_t, int,
- long *));
-
-int
-ffs_init()
-{
- return (ufs_init());
-}
+static int ffs_indirtrunc __P((struct inode *, ufs_daddr_t, ufs_daddr_t,
+ ufs_daddr_t, int, long *));
/*
* Update the access, modified, and inode change times as specified by the
@@ -115,15 +109,15 @@ ffs_update(ap)
*/
tv_sec = time.tv_sec;
if (ip->i_flag & IN_ACCESS)
- ip->i_atime.tv_sec =
+ ip->i_atime =
(ap->a_access == &time ? tv_sec : ap->a_access->tv_sec);
if (ip->i_flag & IN_UPDATE) {
- ip->i_mtime.tv_sec =
+ ip->i_mtime =
(ap->a_modify == &time ? tv_sec : ap->a_modify->tv_sec);
ip->i_modrev++;
}
if (ip->i_flag & IN_CHANGE)
- ip->i_ctime.tv_sec = tv_sec;
+ ip->i_ctime = tv_sec;
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
fs = ip->i_fs;
/*
@@ -169,10 +163,10 @@ ffs_truncate(ap)
} */ *ap;
{
register struct vnode *ovp = ap->a_vp;
- register daddr_t lastblock;
+ ufs_daddr_t lastblock;
register struct inode *oip;
- daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
- daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
+ ufs_daddr_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR];
+ ufs_daddr_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR];
off_t length = ap->a_length;
register struct fs *fs;
struct buf *bp;
@@ -185,8 +179,10 @@ ffs_truncate(ap)
oip = VTOI(ovp);
fs = oip->i_fs;
- if (length < 0 || length > fs->fs_maxfilesize)
+ if (length < 0)
return (EINVAL);
+ if (length > fs->fs_maxfilesize)
+ return (EFBIG);
tv = time;
if (ovp->v_type == VLNK &&
(oip->i_size < ovp->v_mount->mnt_maxsymlinklen || oip->i_din.di_blocks == 0)) {
@@ -220,12 +216,12 @@ ffs_truncate(ap)
aflags = B_CLRBUF;
if (ap->a_flags & IO_SYNC)
aflags |= B_SYNC;
- vnode_pager_setsize(ovp, length);
error = ffs_balloc(oip, lbn, offset + 1, ap->a_cred,
&bp, aflags);
if (error)
return (error);
oip->i_size = length;
+ vnode_pager_setsize(ovp, length);
if (aflags & B_SYNC)
bwrite(bp);
else if (ovp->v_mount->mnt_flag & MNT_ASYNC)
@@ -264,6 +260,7 @@ ffs_truncate(ap)
else
bawrite(bp);
}
+ vnode_pager_setsize(ovp, length);
/*
* Calculate index into inode's block list of
* last direct and indirect blocks (if any)
@@ -413,17 +410,17 @@ done:
static int
ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
register struct inode *ip;
- daddr_t lbn, lastbn;
- daddr_t dbn;
+ ufs_daddr_t lbn, lastbn;
+ ufs_daddr_t dbn;
int level;
long *countp;
{
register int i;
struct buf *bp;
register struct fs *fs = ip->i_fs;
- register daddr_t *bap;
+ register ufs_daddr_t *bap;
struct vnode *vp;
- daddr_t *copy = NULL, nb, nlbn, last;
+ ufs_daddr_t *copy = NULL, nb, nlbn, last;
long blkcount, factor;
int nblocks, blocksreleased = 0;
int error = 0, allerror = 0;
@@ -466,12 +463,12 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
return (error);
}
- bap = (daddr_t *)bp->b_data;
+ bap = (ufs_daddr_t *)bp->b_data;
if (lastbn != -1) {
- MALLOC(copy, daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
+ MALLOC(copy, ufs_daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->fs_bsize);
bzero((caddr_t)&bap[last + 1],
- (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t));
+ (u_int)(NINDIR(fs) - (last + 1)) * sizeof (ufs_daddr_t));
if ((vp->v_mount->mnt_flag & MNT_ASYNC) == 0) {
error = bwrite(bp);
if (error)
@@ -491,9 +488,8 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
if (nb == 0)
continue;
if (level > SINGLE) {
- error = ffs_indirtrunc(ip, nlbn,
- fsbtodb(fs, nb), (daddr_t)-1, level - 1, &blkcount);
- if (error)
+ if (error = ffs_indirtrunc(ip, nlbn, fsbtodb(fs, nb),
+ (ufs_daddr_t)-1, level - 1, &blkcount))
allerror = error;
blocksreleased += blkcount;
}
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index 1cb9f3f..629a228 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -30,22 +30,26 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93
+ * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95
* $FreeBSD$
*/
#include <sys/param.h>
-#include <ufs/ffs/fs.h>
-#ifdef KERNEL
+#ifndef KERNEL
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+#else
#include "opt_ddb.h"
#include <sys/systm.h>
#include <sys/vnode.h>
-#include <ufs/ffs/ffs_extern.h>
#include <sys/buf.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+#include <ufs/ffs/ffs_extern.h>
/*
* Return buffer with the contents of block "offset" from the beginning of
@@ -64,7 +68,7 @@ ffs_blkatoff(ap)
struct inode *ip;
register struct fs *fs;
struct buf *bp;
- daddr_t lbn;
+ ufs_daddr_t lbn;
int bsize, error;
ip = VTOI(ap->a_vp);
@@ -93,7 +97,7 @@ void
ffs_fragacct(fs, fragmap, fraglist, cnt)
struct fs *fs;
int fragmap;
- long fraglist[];
+ int32_t fraglist[];
int cnt;
{
int inblk;
@@ -127,7 +131,7 @@ ffs_checkoverlap(bp, ip)
struct inode *ip;
{
register struct buf *ebp, *ep;
- register daddr_t start, last;
+ register ufs_daddr_t start, last;
struct vnode *vp;
ebp = &buf[nbuf];
@@ -137,7 +141,8 @@ ffs_checkoverlap(bp, ip)
if (ep == bp || (ep->b_flags & B_INVAL) ||
ep->b_vp == NULLVP)
continue;
- if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0, NULL, NULL))
+ if (VOP_BMAP(ep->b_vp, (ufs_daddr_t)0, &vp, (ufs_daddr_t)0,
+ NULL))
continue;
if (vp != ip->i_devvp)
continue;
@@ -163,7 +168,7 @@ int
ffs_isblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
- daddr_t h;
+ ufs_daddr_t h;
{
unsigned char mask;
@@ -191,7 +196,7 @@ void
ffs_clrblock(fs, cp, h)
struct fs *fs;
u_char *cp;
- daddr_t h;
+ ufs_daddr_t h;
{
switch ((int)fs->fs_frag) {
@@ -219,7 +224,7 @@ void
ffs_setblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
- daddr_t h;
+ ufs_daddr_t h;
{
switch ((int)fs->fs_frag) {
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 4b86cb0..c8b8959 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94
+ * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -72,8 +72,9 @@
static int ffs_sbupdate __P((struct ufsmount *, int));
static int ffs_reload __P((struct mount *,struct ucred *,struct proc *));
static int ffs_oldfscompat __P((struct fs *));
-static int ffs_mount __P((struct mount *,
- char *, caddr_t, struct nameidata *, struct proc *));
+static int ffs_mount __P((struct mount *, char *, caddr_t,
+ struct nameidata *, struct proc *));
+static int ffs_init __P((struct vfsconf *));
struct vfsops ufs_vfsops = {
ffs_mount,
@@ -93,7 +94,6 @@ VFS_SET(ufs_vfsops, ufs, MOUNT_UFS, 0);
extern u_long nextgennumber;
-
/*
* ffs_mount
*
@@ -133,7 +133,7 @@ extern u_long nextgennumber;
*/
static int
ffs_mount( mp, path, data, ndp, p)
- register struct mount *mp; /* mount struct pointer*/
+ struct mount *mp; /* mount struct pointer*/
char *path; /* path to mount point*/
caddr_t data; /* arguments to FS specific mount*/
struct nameidata *ndp; /* mount point credentials*/
@@ -159,13 +159,10 @@ ffs_mount( mp, path, data, ndp, p)
*/
/* Get vnode for root device*/
- if( bdevvp( rootdev, &rootvp))
- panic("ffs_mountroot: can't setup bdevvp for root");
-
- /*
- * FS specific handling
- */
- mp->mnt_flag |= MNT_RDONLY; /* XXX globally applicable?*/
+ if ((err = bdevvp( rootdev, &rootvp))) {
+ printf("ffs_mountroot: can't setup bdevvp for root");
+ return (err);
+ }
/*
* Attempt mount
@@ -202,12 +199,7 @@ ffs_mount( mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp)) {
- err = EBUSY;
- goto error_1;
- }
err = ffs_flushfiles(mp, flags, p);
- vfs_unbusy(mp);
}
if (!err && (mp->mnt_flag & MNT_RELOAD))
err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
@@ -341,7 +333,6 @@ success:
return( err);
}
-
/*
* Reload all incore data for a filesystem (used after running fsck on
* the root filesystem and finding things to fix). The filesystem must
@@ -365,8 +356,10 @@ ffs_reload(mp, cred, p)
struct inode *ip;
struct csum *space;
struct buf *bp;
- struct fs *fs;
+ struct fs *fs, *newfs;
+ struct partinfo dpart;
int i, blks, size, error;
+ int32_t *lp;
if ((mp->mnt_flag & MNT_RDONLY) == 0)
return (EINVAL);
@@ -379,24 +372,33 @@ ffs_reload(mp, cred, p)
/*
* Step 2: re-read superblock from disk.
*/
- error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp);
- if (error)
+ if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
+ size = DEV_BSIZE;
+ else
+ size = dpart.disklab->d_secsize;
+ if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp))
return (error);
- fs = (struct fs *)bp->b_data;
- fs->fs_fmod = 0;
- if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
- fs->fs_bsize < sizeof(struct fs)) {
- brelse(bp);
- return (EIO); /* XXX needs translation */
+ newfs = (struct fs *)bp->b_data;
+ if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
+ newfs->fs_bsize < sizeof(struct fs)) {
+ brelse(bp);
+ return (EIO); /* XXX needs translation */
}
fs = VFSTOUFS(mp)->um_fs;
- bcopy(&fs->fs_csp[0], &((struct fs *)bp->b_data)->fs_csp[0],
- sizeof(fs->fs_csp));
- bcopy(bp->b_data, fs, (u_int)fs->fs_sbsize);
+ /*
+ * Copy pointer fields back into superblock before copying in XXX
+ * new superblock. These should really be in the ufsmount. XXX
+ * Note that important parameters (eg fs_ncg) are unchanged.
+ */
+ bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
+ newfs->fs_maxcluster = fs->fs_maxcluster;
+ bcopy(newfs, fs, (u_int)fs->fs_sbsize);
if (fs->fs_sbsize < SBSIZE)
bp->b_flags |= B_INVAL;
brelse(bp);
+ mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
ffs_oldfscompat(fs);
+
/*
* Step 3: re-read summary information from disk.
*/
@@ -413,21 +415,36 @@ ffs_reload(mp, cred, p)
bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
brelse(bp);
}
+ /*
+ * We no longer know anything about clusters per cylinder group.
+ */
+ if (fs->fs_contigsumsize > 0) {
+ lp = fs->fs_maxcluster;
+ for (i = 0; i < fs->fs_ncg; i++)
+ *lp++ = fs->fs_contigsumsize;
+ }
+
loop:
+ simple_lock(&mntvnode_slock);
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
+ if (vp->v_mount != mp) {
+ simple_unlock(&mntvnode_slock);
+ goto loop;
+ }
nvp = vp->v_mntvnodes.le_next;
/*
* Step 4: invalidate all inactive vnodes.
*/
- if (vp->v_usecount == 0) {
- vgone(vp);
- continue;
- }
+ if (vrecycle(vp, &mntvnode_slock, p))
+ goto loop;
/*
* Step 5: invalidate all cached file data.
*/
- if (vget(vp, 1))
+ simple_lock(&vp->v_interlock);
+ simple_unlock(&mntvnode_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
goto loop;
+ }
if (vinvalbuf(vp, 0, cred, p, 0, 0))
panic("ffs_reload: dirty2");
/*
@@ -445,9 +462,9 @@ loop:
ino_to_fsbo(fs, ip->i_number));
brelse(bp);
vput(vp);
- if (vp->v_mount != mp)
- goto loop;
+ simple_lock(&mntvnode_slock);
}
+ simple_unlock(&mntvnode_slock);
return (0);
}
@@ -463,15 +480,18 @@ ffs_mountfs(devvp, mp, p)
register struct ufsmount *ump;
struct buf *bp;
register struct fs *fs;
- dev_t dev = devvp->v_rdev;
+ dev_t dev;
struct partinfo dpart;
caddr_t base, space;
- int havepart = 0, blks;
- int error, i, size;
- int ronly;
+ int error, i, blks, size, ronly;
+ int32_t *lp;
+ struct ucred *cred;
+ u_int64_t maxfilesize; /* XXX */
u_int strsize;
int ncount;
+ dev = devvp->v_rdev;
+ cred = p ? p->p_ucred : NOCRED;
/*
* Disallow multiple mounts of the same device.
* Disallow mounting of a device that is currently in use
@@ -486,25 +506,21 @@ ffs_mountfs(devvp, mp, p)
ncount -= 1;
if (ncount > 1 && devvp != rootvp)
return (EBUSY);
- error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
- if (error)
+ if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
return (error);
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
if (error)
return (error);
- if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
+ if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
size = DEV_BSIZE;
- else {
- havepart = 1;
+ else
size = dpart.disklab->d_secsize;
- }
bp = NULL;
ump = NULL;
- error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp);
- if (error)
+ if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp))
goto out;
fs = (struct fs *)bp->b_data;
if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
@@ -522,6 +538,11 @@ ffs_mountfs(devvp, mp, p)
goto out;
}
}
+ /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
+ if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
+ error = EROFS; /* needs translation */
+ goto out;
+ }
ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
bzero((caddr_t)ump, sizeof *ump);
ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
@@ -537,16 +558,17 @@ ffs_mountfs(devvp, mp, p)
fs->fs_fmod = 1;
fs->fs_clean = 0;
}
- blks = howmany(fs->fs_cssize, fs->fs_fsize);
- base = space = malloc((u_long)fs->fs_cssize, M_UFSMNT,
- M_WAITOK);
+ size = fs->fs_cssize;
+ blks = howmany(size, fs->fs_fsize);
+ if (fs->fs_contigsumsize > 0)
+ size += fs->fs_ncg * sizeof(int32_t);
+ base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
for (i = 0; i < blks; i += fs->fs_frag) {
size = fs->fs_bsize;
if (i + fs->fs_frag > blks)
size = (blks - i) * fs->fs_fsize;
- error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
- NOCRED, &bp);
- if (error) {
+ if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
+ cred, &bp)) {
free(base, M_UFSMNT);
goto out;
}
@@ -556,11 +578,15 @@ ffs_mountfs(devvp, mp, p)
brelse(bp);
bp = NULL;
}
+ if (fs->fs_contigsumsize > 0) {
+ fs->fs_maxcluster = lp = (int32_t *)space;
+ for (i = 0; i < fs->fs_ncg; i++)
+ *lp++ = fs->fs_contigsumsize;
+ }
mp->mnt_data = (qaddr_t)ump;
mp->mnt_stat.f_fsid.val[0] = (long)dev;
- mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
+ mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
- mp->mnt_flag |= MNT_LOCAL;
ump->um_mountp = mp;
ump->um_dev = dev;
ump->um_devvp = devvp;
@@ -589,8 +615,15 @@ ffs_mountfs(devvp, mp, p)
*/
mp->mnt_time = fs->fs_time;
}
- if (ronly == 0)
- ffs_sbupdate(ump, MNT_WAIT);
+
+ ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
+ maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
+ if (fs->fs_maxfilesize > maxfilesize) /* XXX */
+ fs->fs_maxfilesize = maxfilesize; /* XXX */
+ if (ronly == 0) {
+ fs->fs_clean = 0;
+ (void) ffs_sbupdate(ump, MNT_WAIT);
+ }
/*
* Only VMIO the backing device if the backing device is a real
* block device. This excludes the original MFS implementation.
@@ -604,7 +637,7 @@ ffs_mountfs(devvp, mp, p)
out:
if (bp)
brelse(bp);
- (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
+ (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
if (ump) {
free(ump->um_fs, M_UFSMNT);
free(ump, M_UFSMNT);
@@ -630,7 +663,8 @@ ffs_oldfscompat(fs)
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
#if 0
int i; /* XXX */
- quad_t sizepb = fs->fs_bsize; /* XXX */
+ u_int64_t sizepb = fs->fs_bsize; /* XXX */
+ /* XXX */
fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
for (i = 0; i < NIADDR; i++) { /* XXX */
sizepb *= NINDIR(fs); /* XXX */
@@ -655,7 +689,7 @@ ffs_unmount(mp, mntflags, p)
{
register struct ufsmount *ump;
register struct fs *fs;
- int error, flags, ronly;
+ int error, flags;
flags = 0;
if (mntflags & MNT_FORCE) {
@@ -666,18 +700,21 @@ ffs_unmount(mp, mntflags, p)
return (error);
ump = VFSTOUFS(mp);
fs = ump->um_fs;
- ronly = fs->fs_ronly;
- if (!ronly) {
+ if (fs->fs_ronly == 0) {
fs->fs_clean = 1;
- ffs_sbupdate(ump, MNT_WAIT);
+ error = ffs_sbupdate(ump, MNT_WAIT);
+ if (error) {
+ fs->fs_clean = 0;
+ return (error);
+ }
}
ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
- VOP_LOCK(ump->um_devvp);
- vnode_pager_uncache(ump->um_devvp);
- VOP_UNLOCK(ump->um_devvp);
+ vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
+ vnode_pager_uncache(ump->um_devvp, p);
+ VOP_UNLOCK(ump->um_devvp, 0, p);
- error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,
+ error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
vrele(ump->um_devvp);
@@ -686,7 +723,6 @@ ffs_unmount(mp, mntflags, p)
free(fs, M_UFSMNT);
free(ump, M_UFSMNT);
mp->mnt_data = (qaddr_t)0;
- mp->mnt_flag &= ~MNT_LOCAL;
return (error);
}
@@ -702,8 +738,6 @@ ffs_flushfiles(mp, flags, p)
register struct ufsmount *ump;
int error;
- if (!doforce)
- flags &= ~FORCECLOSE;
ump = VFSTOUFS(mp);
#ifdef QUOTA
if (mp->mnt_flag & MNT_QUOTA) {
@@ -742,7 +776,6 @@ ffs_statfs(mp, sbp, p)
fs = ump->um_fs;
if (fs->fs_magic != FS_MAGIC)
panic("ffs_statfs");
- sbp->f_type = MOUNT_UFS;
sbp->f_bsize = fs->fs_fsize;
sbp->f_iosize = fs->fs_bsize;
sbp->f_blocks = fs->fs_dsize;
@@ -752,6 +785,7 @@ ffs_statfs(mp, sbp, p)
sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
sbp->f_ffree = fs->fs_cstotal.cs_nifree;
if (sbp != &mp->mnt_stat) {
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
bcopy((caddr_t)mp->mnt_stat.f_mntonname,
(caddr_t)&sbp->f_mntonname[0], MNAMELEN);
bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
@@ -774,31 +808,22 @@ ffs_sync(mp, waitfor, cred, p)
struct ucred *cred;
struct proc *p;
{
- register struct vnode *vp, *nvp;
- register struct inode *ip;
- register struct ufsmount *ump = VFSTOUFS(mp);
- register struct fs *fs;
+ struct vnode *nvp, *vp;
+ struct inode *ip;
+ struct ufsmount *ump = VFSTOUFS(mp);
+ struct fs *fs;
struct timeval tv;
int error, allerror = 0;
fs = ump->um_fs;
- /*
- * Write back modified superblock.
- * Consistency check that the superblock
- * is still in the buffer cache.
- */
- if (fs->fs_fmod != 0) {
- if (fs->fs_ronly != 0) { /* XXX */
- printf("fs = %s\n", fs->fs_fsmnt);
- panic("update: rofs mod");
- }
- fs->fs_fmod = 0;
- fs->fs_time = time.tv_sec;
- allerror = ffs_sbupdate(ump, waitfor);
+ if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
+ printf("fs = %s\n", fs->fs_fsmnt);
+ panic("update: rofs mod");
}
/*
* Write back each (modified) inode.
*/
+ simple_lock(&mntvnode_slock);
loop:
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
/*
@@ -807,27 +832,40 @@ loop:
*/
if (vp->v_mount != mp)
goto loop;
+ simple_lock(&vp->v_interlock);
nvp = vp->v_mntvnodes.le_next;
- if (VOP_ISLOCKED(vp))
- continue;
ip = VTOI(vp);
- if ((((ip->i_flag &
- (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)) &&
- vp->v_dirtyblkhd.lh_first == NULL)
+ if (((ip->i_flag &
+ (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
+ vp->v_dirtyblkhd.lh_first == NULL) {
+ simple_unlock(&vp->v_interlock);
continue;
+ }
if (vp->v_type != VCHR) {
- if (vget(vp, 1))
- goto loop;
- error = VOP_FSYNC(vp, cred, waitfor, p);
- if (error)
+ simple_unlock(&mntvnode_slock);
+ error =
+ vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
+ if (error) {
+ simple_lock(&mntvnode_slock);
+ if (error == ENOENT)
+ goto loop;
+ continue;
+ }
+ if (error = VOP_FSYNC(vp, cred, waitfor, p))
allerror = error;
- vput(vp);
+ VOP_UNLOCK(vp, 0, p);
+ vrele(vp);
+ simple_lock(&mntvnode_slock);
} else {
+ simple_unlock(&mntvnode_slock);
+ simple_unlock(&vp->v_interlock);
tv = time;
/* VOP_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT); */
VOP_UPDATE(vp, &tv, &tv, 0);
+ simple_lock(&mntvnode_slock);
}
}
+ simple_unlock(&mntvnode_slock);
/*
* Force stale file system control information to be flushed.
*/
@@ -837,6 +875,15 @@ loop:
#ifdef QUOTA
qsync(mp);
#endif
+ /*
+ * Write back modified superblock.
+ */
+ if (fs->fs_fmod != 0) {
+ fs->fs_fmod = 0;
+ fs->fs_time = time.tv_sec;
+ if (error = ffs_sbupdate(ump, waitfor))
+ allerror = error;
+ }
return (allerror);
}
@@ -854,8 +901,8 @@ ffs_vget(mp, ino, vpp)
ino_t ino;
struct vnode **vpp;
{
- register struct fs *fs;
- register struct inode *ip;
+ struct fs *fs;
+ struct inode *ip;
struct ufsmount *ump;
struct buf *bp;
struct vnode *vp;
@@ -903,6 +950,7 @@ restart:
return (error);
}
bzero((caddr_t)ip, sizeof(struct inode));
+ lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
vp->v_data = ip;
ip->i_vnode = vp;
ip->i_fs = fs = ump->um_fs;
@@ -1035,6 +1083,17 @@ ffs_vptofh(vp, fhp)
}
/*
+ * Initialize the filesystem; just use ufs_init.
+ */
+static int
+ffs_init(vfsp)
+ struct vfsconf *vfsp;
+{
+
+ return (ufs_init(vfsp));
+}
+
+/*
* Write a superblock and associated information back to disk.
*/
static int
@@ -1042,21 +1101,15 @@ ffs_sbupdate(mp, waitfor)
struct ufsmount *mp;
int waitfor;
{
- register struct fs *fs = mp->um_fs;
+ register struct fs *dfs, *fs = mp->um_fs;
register struct buf *bp;
int blks;
caddr_t space;
- int i, size, error = 0;
+ int i, size, error, allerror = 0;
- bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
- bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
- /* Restore compatibility to old file systems. XXX */
- if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
- ((struct fs *)bp->b_data)->fs_nrpos = -1; /* XXX */
- if (waitfor == MNT_WAIT)
- error = bwrite(bp);
- else
- bawrite(bp);
+ /*
+ * First write back the summary information.
+ */
blks = howmany(fs->fs_cssize, fs->fs_fsize);
space = (caddr_t)fs->fs_csp[0];
for (i = 0; i < blks; i += fs->fs_frag) {
@@ -1067,10 +1120,37 @@ ffs_sbupdate(mp, waitfor)
size, 0, 0);
bcopy(space, bp->b_data, (u_int)size);
space += size;
- if (waitfor == MNT_WAIT)
- error = bwrite(bp);
- else
+ if (waitfor != MNT_WAIT)
bawrite(bp);
+ else if (error = bwrite(bp))
+ allerror = error;
}
- return (error);
+ /*
+ * Now write back the superblock itself. If any errors occurred
+ * up to this point, then fail so that the superblock avoids
+ * being written out as clean.
+ */
+ if (allerror)
+ return (allerror);
+ bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
+ bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
+ /* Restore compatibility to old file systems. XXX */
+ dfs = (struct fs *)bp->b_data; /* XXX */
+ if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
+ dfs->fs_nrpos = -1; /* XXX */
+ if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
+ int32_t *lp, tmp; /* XXX */
+ /* XXX */
+ lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
+ tmp = lp[4]; /* XXX */
+ for (i = 4; i > 0; i--) /* XXX */
+ lp[i] = lp[i-1]; /* XXX */
+ lp[0] = tmp; /* XXX */
+ } /* XXX */
+ dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
+ if (waitfor != MNT_WAIT)
+ bawrite(bp);
+ else if (error = bwrite(bp))
+ allerror = error;
+ return (allerror);
}
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index c3f750b..ddce646 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ffs_vnops.c 8.7 (Berkeley) 2/3/94
+ * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
* $FreeBSD$
*/
@@ -62,6 +62,7 @@
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/dir.h>
+#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/fs.h>
@@ -78,6 +79,7 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *)vn_default_error },
{ &vop_lookup_desc, (vop_t *)ufs_lookup }, /* lookup */
{ &vop_create_desc, (vop_t *)ufs_create }, /* create */
+ { &vop_whiteout_desc, (vop_t *)ufs_whiteout }, /* whiteout */
{ &vop_mknod_desc, (vop_t *)ufs_mknod }, /* mknod */
{ &vop_open_desc, (vop_t *)ufs_open }, /* open */
{ &vop_close_desc, (vop_t *)ufs_close }, /* close */
@@ -86,8 +88,10 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)ffs_read }, /* read */
{ &vop_write_desc, (vop_t *)ffs_write }, /* write */
+ { &vop_lease_desc, (vop_t *)ufs_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)ufs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)ufs_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)ufs_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)ufs_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)ffs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)ufs_seek }, /* seek */
@@ -101,7 +105,7 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_readlink_desc, (vop_t *)ufs_readlink }, /* readlink */
{ &vop_abortop_desc, (vop_t *)ufs_abortop }, /* abortop */
{ &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */
+ { &vop_reclaim_desc, (vop_t *)ffs_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */
{ &vop_bmap_desc, (vop_t *)ufs_bmap }, /* bmap */
@@ -136,8 +140,10 @@ static struct vnodeopv_entry_desc ffs_specop_entries[] = {
{ &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)ufsspec_read }, /* read */
{ &vop_write_desc, (vop_t *)ufsspec_write }, /* write */
+ { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)spec_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)ffs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
@@ -151,7 +157,7 @@ static struct vnodeopv_entry_desc ffs_specop_entries[] = {
{ &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
{ &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
{ &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */
+ { &vop_reclaim_desc, (vop_t *)ffs_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */
{ &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
@@ -186,8 +192,10 @@ static struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
{ &vop_setattr_desc, (vop_t *)ufs_setattr }, /* setattr */
{ &vop_read_desc, (vop_t *)ufsfifo_read }, /* read */
{ &vop_write_desc, (vop_t *)ufsfifo_write }, /* write */
+ { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
{ &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)fifo_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)ffs_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
@@ -201,7 +209,7 @@ static struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
{ &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
{ &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
{ &vop_inactive_desc, (vop_t *)ufs_inactive }, /* inactive */
- { &vop_reclaim_desc, (vop_t *)ufs_reclaim }, /* reclaim */
+ { &vop_reclaim_desc, (vop_t *)ffs_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *)ufs_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *)ufs_unlock }, /* unlock */
{ &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
@@ -226,20 +234,16 @@ VNODEOP_SET(ffs_vnodeop_opv_desc);
VNODEOP_SET(ffs_specop_opv_desc);
VNODEOP_SET(ffs_fifoop_opv_desc);
-#ifdef DEBUG
/*
* Enabling cluster read/write operations.
*/
-#include <sys/sysctl.h>
int doclusterread = 1;
-SYSCTL_INT(_debug, 11, doclusterread, CTLFLAG_RW, &doclusterread, 0, "");
int doclusterwrite = 1;
-SYSCTL_INT(_debug, 12, doclusterwrite, CTLFLAG_RW, &doclusterwrite, 0, "");
-#else
-/* XXX for ufs_readwrite */
-#define doclusterread 1
-#define doclusterwrite 1
-#endif
+
+#include <sys/sysctl.h>
+SYSCTL_NODE(_vfs_ffs, MOUNT_UFS, ffs, CTLFLAG_RW, 0, "FFS");
+SYSCTL_INT(_vfs_ffs, FFS_CLUSTERREAD, doclusterread, CTLFLAG_RW, &doclusterread, 0, "");
+SYSCTL_INT(_vfs_ffs, FFS_CLUSTERWRITE, doclusterwrite, CTLFLAG_RW, &doclusterwrite, 0, "");
#include <ufs/ufs/ufs_readwrite.c>
@@ -320,3 +324,24 @@ loop:
tv = time;
return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
}
+
+/*
+ * Reclaim an inode so that it can be used for other purposes.
+ */
+int
+ffs_reclaim(ap)
+ struct vop_reclaim_args /* {
+ struct vnode *a_vp;
+ struct proc *a_p;
+ } */ *ap;
+{
+ register struct vnode *vp = ap->a_vp;
+ int error;
+
+ if (error = ufs_reclaim(vp, ap->a_p))
+ return (error);
+ FREE(vp->v_data, VFSTOUFS(vp->v_mount)->um_devvp->v_tag == VT_MFS ?
+ M_MFSNODE : M_FFSNODE);
+ vp->v_data = NULL;
+ return (0);
+}
diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h
index 16862c4..02720da 100644
--- a/sys/ufs/ffs/fs.h
+++ b/sys/ufs/ffs/fs.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)fs.h 8.7 (Berkeley) 4/19/94
+ * @(#)fs.h 8.13 (Berkeley) 3/21/95
* $FreeBSD$
*/
@@ -65,8 +65,8 @@
#define SBSIZE 8192
#define BBOFF ((off_t)(0))
#define SBOFF ((off_t)(BBOFF + BBSIZE))
-#define BBLOCK ((daddr_t)(0))
-#define SBLOCK ((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
+#define BBLOCK ((ufs_daddr_t)(0))
+#define SBLOCK ((ufs_daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
/*
* Addresses stored in inodes are capable of addressing fragments
@@ -102,12 +102,18 @@
* The path name on which the file system is mounted is maintained
* in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
* the super block for this name.
+ */
+#define MAXMNTLEN 512
+
+/*
* The limit on the amount of summary information per file system
* is defined by MAXCSBUFS. It is currently parameterized for a
- * maximum of two million cylinders.
+ * size of 128 bytes (2 million cylinder groups on machines with
+ * 32-bit pointers, and 1 million on 64-bit machines). One pointer
+ * is taken away to point to an array of cluster sizes that is
+ * computed as cylinder groups are inspected.
*/
-#define MAXMNTLEN 512
-#define MAXCSBUFS 32
+#define MAXCSBUFS ((128 / sizeof(void *)) - 1)
/*
* A summary of contiguous blocks of various sizes is maintained
@@ -142,103 +148,105 @@
* the ``fs_cs'' macro to work (see below).
*/
struct csum {
- long cs_ndir; /* number of directories */
- long cs_nbfree; /* number of free blocks */
- long cs_nifree; /* number of free inodes */
- long cs_nffree; /* number of free frags */
+ int32_t cs_ndir; /* number of directories */
+ int32_t cs_nbfree; /* number of free blocks */
+ int32_t cs_nifree; /* number of free inodes */
+ int32_t cs_nffree; /* number of free frags */
};
/*
- * Super block for a file system.
+ * Super block for an FFS file system.
*/
struct fs {
- struct fs *fs_link; /* linked list of file systems */
- struct fs *fs_rlink; /* used for incore super blocks */
- daddr_t fs_sblkno; /* addr of super-block in filesys */
- daddr_t fs_cblkno; /* offset of cyl-block in filesys */
- daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
- daddr_t fs_dblkno; /* offset of first data after cg */
- long fs_cgoffset; /* cylinder group offset in cylinder */
- long fs_cgmask; /* used to calc mod fs_ntrak */
- time_t fs_time; /* last time written */
- long fs_size; /* number of blocks in fs */
- long fs_dsize; /* number of data blocks in fs */
- long fs_ncg; /* number of cylinder groups */
- long fs_bsize; /* size of basic blocks in fs */
- long fs_fsize; /* size of frag blocks in fs */
- long fs_frag; /* number of frags in a block in fs */
+ int32_t fs_firstfield; /* historic file system linked list, */
+ int32_t fs_unused_1; /* used for incore super blocks */
+ ufs_daddr_t fs_sblkno; /* addr of super-block in filesys */
+ ufs_daddr_t fs_cblkno; /* offset of cyl-block in filesys */
+ ufs_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
+ ufs_daddr_t fs_dblkno; /* offset of first data after cg */
+ int32_t fs_cgoffset; /* cylinder group offset in cylinder */
+ int32_t fs_cgmask; /* used to calc mod fs_ntrak */
+ time_t fs_time; /* last time written */
+ int32_t fs_size; /* number of blocks in fs */
+ int32_t fs_dsize; /* number of data blocks in fs */
+ int32_t fs_ncg; /* number of cylinder groups */
+ int32_t fs_bsize; /* size of basic blocks in fs */
+ int32_t fs_fsize; /* size of frag blocks in fs */
+ int32_t fs_frag; /* number of frags in a block in fs */
/* these are configuration parameters */
- long fs_minfree; /* minimum percentage of free blocks */
- long fs_rotdelay; /* num of ms for optimal next block */
- long fs_rps; /* disk revolutions per second */
+ int32_t fs_minfree; /* minimum percentage of free blocks */
+ int32_t fs_rotdelay; /* num of ms for optimal next block */
+ int32_t fs_rps; /* disk revolutions per second */
/* these fields can be computed from the others */
- long fs_bmask; /* ``blkoff'' calc of blk offsets */
- long fs_fmask; /* ``fragoff'' calc of frag offsets */
- long fs_bshift; /* ``lblkno'' calc of logical blkno */
- long fs_fshift; /* ``numfrags'' calc number of frags */
+ int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */
+ int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */
+ int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */
+ int32_t fs_fshift; /* ``numfrags'' calc number of frags */
/* these are configuration parameters */
- long fs_maxcontig; /* max number of contiguous blks */
- long fs_maxbpg; /* max number of blks per cyl group */
+ int32_t fs_maxcontig; /* max number of contiguous blks */
+ int32_t fs_maxbpg; /* max number of blks per cyl group */
/* these fields can be computed from the others */
- long fs_fragshift; /* block to frag shift */
- long fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
- long fs_sbsize; /* actual size of super block */
- long fs_csmask; /* csum block offset */
- long fs_csshift; /* csum block number */
- long fs_nindir; /* value of NINDIR */
- long fs_inopb; /* value of INOPB */
- long fs_nspf; /* value of NSPF */
+ int32_t fs_fragshift; /* block to frag shift */
+ int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */
+ int32_t fs_sbsize; /* actual size of super block */
+ int32_t fs_csmask; /* csum block offset */
+ int32_t fs_csshift; /* csum block number */
+ int32_t fs_nindir; /* value of NINDIR */
+ int32_t fs_inopb; /* value of INOPB */
+ int32_t fs_nspf; /* value of NSPF */
/* yet another configuration parameter */
- long fs_optim; /* optimization preference, see below */
+ int32_t fs_optim; /* optimization preference, see below */
/* these fields are derived from the hardware */
- long fs_npsect; /* # sectors/track including spares */
- long fs_interleave; /* hardware sector interleave */
- long fs_trackskew; /* sector 0 skew, per track */
- long fs_headswitch; /* head switch time, usec */
- long fs_trkseek; /* track-to-track seek, usec */
+ int32_t fs_npsect; /* # sectors/track including spares */
+ int32_t fs_interleave; /* hardware sector interleave */
+ int32_t fs_trackskew; /* sector 0 skew, per track */
+ int32_t fs_headswitch; /* head switch time, usec */
+ int32_t fs_trkseek; /* track-to-track seek, usec */
/* sizes determined by number of cylinder groups and their sizes */
- daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
- long fs_cssize; /* size of cyl grp summary area */
- long fs_cgsize; /* cylinder group size */
+ ufs_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */
+ int32_t fs_cssize; /* size of cyl grp summary area */
+ int32_t fs_cgsize; /* cylinder group size */
/* these fields are derived from the hardware */
- long fs_ntrak; /* tracks per cylinder */
- long fs_nsect; /* sectors per track */
- long fs_spc; /* sectors per cylinder */
+ int32_t fs_ntrak; /* tracks per cylinder */
+ int32_t fs_nsect; /* sectors per track */
+ int32_t fs_spc; /* sectors per cylinder */
/* this comes from the disk driver partitioning */
- long fs_ncyl; /* cylinders in file system */
+ int32_t fs_ncyl; /* cylinders in file system */
/* these fields can be computed from the others */
- long fs_cpg; /* cylinders per group */
- long fs_ipg; /* inodes per group */
- long fs_fpg; /* blocks per group * fs_frag */
+ int32_t fs_cpg; /* cylinders per group */
+ int32_t fs_ipg; /* inodes per group */
+ int32_t fs_fpg; /* blocks per group * fs_frag */
/* this data must be re-computed after crashes */
struct csum fs_cstotal; /* cylinder summary information */
/* these fields are cleared at mount time */
- char fs_fmod; /* super block modified flag */
- char fs_clean; /* file system is clean flag */
- char fs_ronly; /* mounted read-only flag */
- char fs_flags; /* currently unused flag */
- char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
+ int8_t fs_fmod; /* super block modified flag */
+ int8_t fs_clean; /* file system is clean flag */
+ int8_t fs_ronly; /* mounted read-only flag */
+ int8_t fs_flags; /* currently unused flag */
+ u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
/* these fields retain the current block allocation info */
- long fs_cgrotor; /* last cg searched */
+ int32_t fs_cgrotor; /* last cg searched */
struct csum *fs_csp[MAXCSBUFS];/* list of fs_cs info buffers */
- long fs_cpc; /* cyl per cycle in postbl */
- short fs_opostbl[16][8]; /* old rotation block list head */
- long fs_sparecon[50]; /* reserved for future constants */
- long fs_contigsumsize; /* size of cluster summary array */
- long fs_maxsymlinklen; /* max length of an internal symlink */
- long fs_inodefmt; /* format of on-disk inodes */
- u_quad_t fs_maxfilesize; /* maximum representable file size */
- quad_t fs_qbmask; /* ~fs_bmask - for use with quad size */
- quad_t fs_qfmask; /* ~fs_fmask - for use with quad size */
- long fs_state; /* validate fs_clean field */
- long fs_postblformat; /* format of positional layout tables */
- long fs_nrpos; /* number of rotational positions */
- long fs_postbloff; /* (short) rotation block list head */
- long fs_rotbloff; /* (u_char) blocks for each rotation */
- long fs_magic; /* magic number */
- u_char fs_space[1]; /* list of blocks for each rotation */
+ int32_t *fs_maxcluster; /* max cluster in each cyl group */
+ int32_t fs_cpc; /* cyl per cycle in postbl */
+ int16_t fs_opostbl[16][8]; /* old rotation block list head */
+ int32_t fs_sparecon[50]; /* reserved for future constants */
+ int32_t fs_contigsumsize; /* size of cluster summary array */
+ int32_t fs_maxsymlinklen; /* max length of an internal symlink */
+ int32_t fs_inodefmt; /* format of on-disk inodes */
+ u_int64_t fs_maxfilesize; /* maximum representable file size */
+ int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */
+ int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */
+ int32_t fs_state; /* validate fs_clean field */
+ int32_t fs_postblformat; /* format of positional layout tables */
+ int32_t fs_nrpos; /* number of rotational positions */
+ int32_t fs_postbloff; /* (u_int16) rotation block list head */
+ int32_t fs_rotbloff; /* (u_int8) blocks for each rotation */
+ int32_t fs_magic; /* magic number */
+ u_int8_t fs_space[1]; /* list of blocks for each rotation */
/* actually longer */
};
+
/*
* Filesystem identification
*/
@@ -263,11 +271,12 @@ struct fs {
#define fs_postbl(fs, cylno) \
(((fs)->fs_postblformat == FS_42POSTBLFMT) \
? ((fs)->fs_opostbl[cylno]) \
- : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos))
+ : ((int16_t *)((u_int8_t *)(fs) + \
+ (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos))
#define fs_rotbl(fs) \
(((fs)->fs_postblformat == FS_42POSTBLFMT) \
? ((fs)->fs_space) \
- : ((u_char *)((char *)(fs) + (fs)->fs_rotbloff)))
+ : ((u_int8_t *)((u_int8_t *)(fs) + (fs)->fs_rotbloff)))
/*
* The size of a cylinder group is calculated by CGSIZE. The maximum size
@@ -276,13 +285,13 @@ struct fs {
* cylinder group and the (struct cg) size.
*/
#define CGSIZE(fs) \
- /* base cg */ (sizeof(struct cg) + sizeof(long) + \
- /* blktot size */ (fs)->fs_cpg * sizeof(long) + \
- /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
+ /* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \
+ /* blktot size */ (fs)->fs_cpg * sizeof(int32_t) + \
+ /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(int16_t) + \
/* inode map */ howmany((fs)->fs_ipg, NBBY) + \
/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY) +\
/* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \
- /* cluster sum */ (fs)->fs_contigsumsize * sizeof(long) + \
+ /* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \
/* cluster map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPB(fs), NBBY)))
/*
@@ -297,79 +306,81 @@ struct fs {
* Cylinder group block for a file system.
*/
#define CG_MAGIC 0x090255
-struct cg {
- struct cg *cg_link; /* linked list of cyl groups */
- long cg_magic; /* magic number */
- time_t cg_time; /* time last written */
- long cg_cgx; /* we are the cgx'th cylinder group */
- short cg_ncyl; /* number of cyl's this cg */
- short cg_niblk; /* number of inode blocks this cg */
- long cg_ndblk; /* number of data blocks this cg */
+struct cg {
+ int32_t cg_firstfield; /* historic cyl groups linked list */
+ int32_t cg_magic; /* magic number */
+ time_t cg_time; /* time last written */
+ int32_t cg_cgx; /* we are the cgx'th cylinder group */
+ int16_t cg_ncyl; /* number of cyl's this cg */
+ int16_t cg_niblk; /* number of inode blocks this cg */
+ int32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
- long cg_rotor; /* position of last used block */
- long cg_frotor; /* position of last used frag */
- long cg_irotor; /* position of last used inode */
- long cg_frsum[MAXFRAG]; /* counts of available frags */
- long cg_btotoff; /* (long) block totals per cylinder */
- long cg_boff; /* (short) free block positions */
- long cg_iusedoff; /* (char) used inode map */
- long cg_freeoff; /* (u_char) free block map */
- long cg_nextfreeoff; /* (u_char) next available space */
- long cg_clustersumoff; /* (long) counts of avail clusters */
- long cg_clusteroff; /* (char) free cluster map */
- long cg_nclusterblks; /* number of clusters this cg */
- long cg_sparecon[13]; /* reserved for future use */
- u_char cg_space[1]; /* space for cylinder group maps */
+ int32_t cg_rotor; /* position of last used block */
+ int32_t cg_frotor; /* position of last used frag */
+ int32_t cg_irotor; /* position of last used inode */
+ int32_t cg_frsum[MAXFRAG]; /* counts of available frags */
+ int32_t cg_btotoff; /* (int32) block totals per cylinder */
+ int32_t cg_boff; /* (u_int16) free block positions */
+ int32_t cg_iusedoff; /* (u_int8) used inode map */
+ int32_t cg_freeoff; /* (u_int8) free block map */
+ int32_t cg_nextfreeoff; /* (u_int8) next available space */
+ int32_t cg_clustersumoff; /* (u_int32) counts of avail clusters */
+ int32_t cg_clusteroff; /* (u_int8) free cluster map */
+ int32_t cg_nclusterblks; /* number of clusters this cg */
+ int32_t cg_sparecon[13]; /* reserved for future use */
+ u_int8_t cg_space[1]; /* space for cylinder group maps */
/* actually longer */
};
+
/*
* Macros for access to cylinder group array structures
*/
#define cg_blktot(cgp) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_btot) \
- : ((long *)((char *)(cgp) + (cgp)->cg_btotoff)))
+ : ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_btotoff)))
#define cg_blks(fs, cgp, cylno) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_b[cylno]) \
- : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos))
+ : ((int16_t *)((u_int8_t *)(cgp) + \
+ (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos))
#define cg_inosused(cgp) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_iused) \
- : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff)))
+ : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff)))
#define cg_blksfree(cgp) \
(((cgp)->cg_magic != CG_MAGIC) \
? (((struct ocg *)(cgp))->cg_free) \
- : ((u_char *)((char *)(cgp) + (cgp)->cg_freeoff)))
+ : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_freeoff)))
#define cg_chkmagic(cgp) \
((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC)
#define cg_clustersfree(cgp) \
- ((u_char *)((char *)(cgp) + (cgp)->cg_clusteroff))
+ ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_clusteroff))
#define cg_clustersum(cgp) \
- ((long *)((char *)(cgp) + (cgp)->cg_clustersumoff))
+ ((int32_t *)((u_int8_t *)(cgp) + (cgp)->cg_clustersumoff))
/*
* The following structure is defined
* for compatibility with old file systems.
*/
-struct ocg {
- struct ocg *cg_link; /* linked list of cyl groups */
- struct ocg *cg_rlink; /* used for incore cyl groups */
- time_t cg_time; /* time last written */
- long cg_cgx; /* we are the cgx'th cylinder group */
- short cg_ncyl; /* number of cyl's this cg */
- short cg_niblk; /* number of inode blocks this cg */
- long cg_ndblk; /* number of data blocks this cg */
+struct ocg {
+ int32_t cg_firstfield; /* historic linked list of cyl groups */
+ int32_t cg_unused_1; /* used for incore cyl groups */
+ time_t cg_time; /* time last written */
+ int32_t cg_cgx; /* we are the cgx'th cylinder group */
+ int16_t cg_ncyl; /* number of cyl's this cg */
+ int16_t cg_niblk; /* number of inode blocks this cg */
+ int32_t cg_ndblk; /* number of data blocks this cg */
struct csum cg_cs; /* cylinder summary information */
- long cg_rotor; /* position of last used block */
- long cg_frotor; /* position of last used frag */
- long cg_irotor; /* position of last used inode */
- long cg_frsum[8]; /* counts of available frags */
- long cg_btot[32]; /* block totals per cylinder */
- short cg_b[32][8]; /* positions of free blocks */
- char cg_iused[256]; /* used inode map */
- long cg_magic; /* magic number */
- u_char cg_free[1]; /* free block map */
+ int32_t cg_rotor; /* position of last used block */
+ int32_t cg_frotor; /* position of last used frag */
+ int32_t cg_irotor; /* position of last used inode */
+ int32_t cg_frsum[8]; /* counts of available frags */
+ int32_t cg_btot[32]; /* block totals per cylinder */
+ int16_t cg_b[32][8]; /* positions of free blocks */
+ u_int8_t cg_iused[256]; /* used inode map */
+ int32_t cg_magic; /* magic number */
+ u_int8_t cg_free[1]; /* free block map */
/* actually longer */
};
@@ -384,7 +395,7 @@ struct ocg {
* Cylinder group macros to locate things in cylinder groups.
* They calc file system addresses of cylinder group data structures.
*/
-#define cgbase(fs, c) ((daddr_t)((fs)->fs_fpg * (c)))
+#define cgbase(fs, c) ((ufs_daddr_t)((fs)->fs_fpg * (c)))
#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */
#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */
#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */
@@ -400,7 +411,7 @@ struct ocg {
*/
#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg)
#define ino_to_fsba(fs, x) \
- ((daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
+ ((ufs_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \
(blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs))))))
#define ino_to_fsbo(fs, x) ((x) % INOPB(fs))
@@ -457,7 +468,7 @@ struct ocg {
/*
* Determine the number of available frags given a
- * percentage to hold in reserve
+ * percentage to hold in reserve.
*/
#define freespace(fs, percentreserved) \
(blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
@@ -476,19 +487,20 @@ struct ocg {
: (fragroundup(fs, blkoff(fs, (dip)->di_size))))
/*
- * Number of disk sectors per block; assumes DEV_BSIZE byte sector size.
+ * Number of disk sectors per block/fragment; assumes DEV_BSIZE byte
+ * sector size.
*/
#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift)
#define NSPF(fs) ((fs)->fs_nspf)
/*
- * INOPB is the number of inodes in a secondary storage block.
+ * Number of inodes in a secondary storage block/fragment.
*/
#define INOPB(fs) ((fs)->fs_inopb)
#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift)
/*
- * NINDIR is the number of indirects in a file system block.
+ * Number of indirects in a file system block.
*/
#define NINDIR(fs) ((fs)->fs_nindir)
diff --git a/sys/ufs/lfs/lfs_subr.c b/sys/ufs/lfs/lfs_subr.c
index 7cd938b..737d2c5 100644
--- a/sys/ufs/lfs/lfs_subr.c
+++ b/sys/ufs/lfs/lfs_subr.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)lfs_subr.c 8.2 (Berkeley) 9/21/93
+ * @(#)lfs_subr.c 8.4 (Berkeley) 5/8/95
* $FreeBSD$
*/
@@ -65,13 +65,13 @@ lfs_blkatoff(ap)
register struct lfs *fs;
struct inode *ip;
struct buf *bp;
- daddr_t lbn;
+ ufs_daddr_t lbn;
int bsize, error;
ip = VTOI(ap->a_vp);
fs = ip->i_lfs;
lbn = lblkno(fs, ap->a_offset);
- bsize = blksize(fs);
+ bsize = blksize(fs, ip, lbn);
*ap->a_bpp = NULL;
if (error = bread(ap->a_vp, lbn, bsize, NOCRED, &bp)) {
@@ -112,7 +112,8 @@ lfs_seglock(fs, flags)
sp = fs->lfs_sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK);
sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) /
- sizeof(daddr_t) + 1) * sizeof(struct buf *), M_SEGMENT, M_WAITOK);
+ sizeof(ufs_daddr_t) + 1) * sizeof(struct buf *),
+ M_SEGMENT, M_WAITOK);
sp->seg_flags = flags;
sp->vp = NULL;
(void) lfs_initseg(fs);
diff --git a/sys/ufs/lfs/lfs_syscalls.c b/sys/ufs/lfs/lfs_syscalls.c
index 01e63e2..6ec1d9e 100644
--- a/sys/ufs/lfs/lfs_syscalls.c
+++ b/sys/ufs/lfs/lfs_syscalls.c
@@ -115,7 +115,7 @@ lfs_markv(p, uap, retval)
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
cnt = uap->blkcnt;
@@ -286,7 +286,7 @@ lfs_bmapv(p, uap, retval)
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
cnt = uap->blkcnt;
@@ -347,7 +347,7 @@ lfs_segclean(p, uap, retval)
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
fs = VFSTOUFS(mntp)->um_lfs;
@@ -413,14 +413,14 @@ lfs_segwait(p, uap, retval)
if (fsid == (fsid_t)-1)
addr = &lfs_allclean_wakeup;
else {
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
return (EINVAL);
addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
}
#else
if (error = copyin(uap->fsidp, &fsid, sizeof(fsid_t)))
return (error);
- if ((mntp = getvfs(&fsid)) == NULL)
+ if ((mntp = vfs_getvfs(&fsid)) == NULL)
addr = &lfs_allclean_wakeup;
else
addr = &VFSTOUFS(mntp)->um_lfs->lfs_nextseg;
diff --git a/sys/ufs/mfs/mfs_extern.h b/sys/ufs/mfs/mfs_extern.h
index e2bd561..1556659 100644
--- a/sys/ufs/mfs/mfs_extern.h
+++ b/sys/ufs/mfs/mfs_extern.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)mfs_extern.h 8.1 (Berkeley) 6/11/93
+ * @(#)mfs_extern.h 8.4 (Berkeley) 3/30/95
* $FreeBSD$
*/
@@ -44,4 +44,6 @@ void mfs_doio __P((struct buf *bp, caddr_t base));
int mfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
int mfs_mountroot __P((void));
+#define mfs_revoke vop_revoke
+
#endif /* !_UFS_MFS_MFS_EXTERN_H_ */
diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c
index 372d9db..3847603 100644
--- a/sys/ufs/mfs/mfs_vfsops.c
+++ b/sys/ufs/mfs/mfs_vfsops.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)mfs_vfsops.c 8.4 (Berkeley) 4/16/94
+ * @(#)mfs_vfsops.c 8.11 (Berkeley) 6/19/95
* $FreeBSD$
*/
@@ -84,7 +84,7 @@ static int mfs_mount __P((struct mount *mp,
static int mfs_start __P((struct mount *mp, int flags, struct proc *p));
static int mfs_statfs __P((struct mount *mp, struct statfs *sbp,
struct proc *p));
-static int mfs_init __P((void));
+static int mfs_init __P((struct vfsconf *));
/*
* mfs vfs operations.
@@ -230,8 +230,8 @@ mfs_mount(mp, path, data, ndp, p)
struct vnode *devvp;
struct mfs_args args;
struct ufsmount *ump;
- register struct fs *fs;
- register struct mfsnode *mfsp;
+ struct fs *fs;
+ struct mfsnode *mfsp;
u_int size;
int flags, err;
@@ -282,8 +282,10 @@ mfs_mount(mp, path, data, ndp, p)
/* Get vnode for root device*/
- if( bdevvp( rootdev, &rootvp))
- panic("mfs_mountroot: can't setup bdevvp for rootdev");
+ if (error = bdevvp( rootdev, &rootvp)) {
+ printf("mfs_mountroot: can't setup bdevvp for rootdev");
+ return (error);
+ }
/*
* FS specific handling
@@ -342,12 +344,7 @@ mfs_mount(mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (vfs_busy(mp)) {
- err = EBUSY;
- goto error_1;
- }
err = ffs_flushfiles(mp, flags, p);
- vfs_unbusy(mp);
if (err)
goto error_1;
}
@@ -503,7 +500,7 @@ mfs_statfs(mp, sbp, p)
int error;
error = ffs_statfs(mp, sbp, p);
- sbp->f_type = MOUNT_MFS;
+ sbp->f_type = mp->mnt_vfc->vfc_typenum;
return (error);
}
@@ -511,7 +508,8 @@ mfs_statfs(mp, sbp, p)
* Memory based filesystem initialization.
*/
static int
-mfs_init()
+mfs_init(vfsp)
+ struct vfsconf *vfsp;
{
return (0);
}
diff --git a/sys/ufs/mfs/mfs_vnops.c b/sys/ufs/mfs/mfs_vnops.c
index 29eae7d..75ccd85 100644
--- a/sys/ufs/mfs/mfs_vnops.c
+++ b/sys/ufs/mfs/mfs_vnops.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)mfs_vnops.c 8.3 (Berkeley) 9/21/93
+ * @(#)mfs_vnops.c 8.11 (Berkeley) 5/22/95
* $FreeBSD$
*/
@@ -51,12 +51,6 @@
#include <ufs/mfs/mfsiom.h>
#include <ufs/mfs/mfs_extern.h>
-#if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k)
-static int mfsmap_want; /* 1 => need kernel I/O resources */
-struct map mfsmap[MFS_MAPSIZE];
-extern char mfsiobuf[];
-#endif
-
static int mfs_badop __P((void));
static int mfs_bmap __P((struct vop_bmap_args *));
static int mfs_close __P((struct vop_close_args *));
@@ -84,6 +78,7 @@ static struct vnodeopv_entry_desc mfs_vnodeop_entries[] = {
{ &vop_write_desc, (vop_t *)mfs_write }, /* write */
{ &vop_ioctl_desc, (vop_t *)mfs_ioctl }, /* ioctl */
{ &vop_select_desc, (vop_t *)mfs_select }, /* select */
+ { &vop_revoke_desc, (vop_t *)mfs_revoke }, /* revoke */
{ &vop_mmap_desc, (vop_t *)mfs_mmap }, /* mmap */
{ &vop_fsync_desc, (vop_t *)spec_fsync }, /* fsync */
{ &vop_seek_desc, (vop_t *)mfs_seek }, /* seek */
@@ -227,9 +222,9 @@ static int
mfs_bmap(ap)
struct vop_bmap_args /* {
struct vnode *a_vp;
- daddr_t a_bn;
+ ufs_daddr_t a_bn;
struct vnode **a_vpp;
- daddr_t *a_bnp;
+ ufs_daddr_t *a_bnp;
int *a_runp;
} */ *ap;
{
@@ -300,13 +295,16 @@ static int
mfs_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
- register struct mfsnode *mfsp = VTOMFS(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct mfsnode *mfsp = VTOMFS(vp);
if (!TAILQ_EMPTY(&mfsp->buf_queue))
panic("mfs_inactive: not inactive (next buffer %p)",
TAILQ_FIRST(&mfsp->buf_queue));
+ VOP_UNLOCK(vp, 0, ap->a_p);
return (0);
}
@@ -319,9 +317,10 @@ mfs_reclaim(ap)
struct vnode *a_vp;
} */ *ap;
{
+ register struct vnode *vp = ap->a_vp;
- FREE(ap->a_vp->v_data, M_MFSNODE);
- ap->a_vp->v_data = NULL;
+ FREE(vp->v_data, M_MFSNODE);
+ vp->v_data = NULL;
return (0);
}
@@ -351,4 +350,3 @@ mfs_badop()
panic("mfs_badop called");
/* NOTREACHED */
}
-
diff --git a/sys/ufs/mfs/mfsnode.h b/sys/ufs/mfs/mfsnode.h
index 29fbd33..403d473 100644
--- a/sys/ufs/mfs/mfsnode.h
+++ b/sys/ufs/mfs/mfsnode.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)mfsnode.h 8.2 (Berkeley) 8/11/93
+ * @(#)mfsnode.h 8.3 (Berkeley) 5/19/95
* $FreeBSD$
*/
@@ -78,9 +78,9 @@ struct mfsnode {
#define mfs_readdir ((int (*) __P((struct vop_readdir_args *)))mfs_badop)
#define mfs_readlink ((int (*) __P((struct vop_readlink_args *)))mfs_badop)
#define mfs_abortop ((int (*) __P((struct vop_abortop_args *)))mfs_badop)
-#define mfs_lock ((int (*) __P((struct vop_lock_args *)))nullop)
-#define mfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop)
-#define mfs_islocked ((int (*) __P((struct vop_islocked_args *)))nullop)
+#define mfs_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
+#define mfs_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
+#define mfs_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
#define mfs_pathconf ((int (*) __P((struct vop_pathconf_args *)))mfs_badop)
#define mfs_advlock ((int (*) __P((struct vop_advlock_args *)))mfs_badop)
#define mfs_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))mfs_badop)
diff --git a/sys/ufs/ufs/dinode.h b/sys/ufs/ufs/dinode.h
index c2fd5bd..461a6c0 100644
--- a/sys/ufs/ufs/dinode.h
+++ b/sys/ufs/ufs/dinode.h
@@ -51,32 +51,46 @@
#define ROOTINO ((ino_t)2)
/*
+ * The Whiteout inode# is a dummy non-zero inode number which will
+ * never be allocated to a real file. It is used as a place holder
+ * in the directory entry which has been tagged as a DT_W entry.
+ * See the comments about ROOTINO above.
+ */
+#define WINO ((ino_t)1)
+
+/*
* A dinode contains all the meta-data associated with a UFS file.
- * This structure defines the on-disk format of a dinode.
+ * This structure defines the on-disk format of a dinode. Since
+ * this structure describes an on-disk structure, all its fields
+ * are defined by types with precise widths.
*/
+/* typedef int32_t ufs_daddr_t; */
#define NDADDR 12 /* Direct addresses in inode. */
#define NIADDR 3 /* Indirect addresses in inode. */
struct dinode {
- u_short di_mode; /* 0: IFMT and permissions. */
- short di_nlink; /* 2: File link count. */
+ u_int16_t di_mode; /* 0: IFMT, permissions; see below. */
+ int16_t di_nlink; /* 2: File link count. */
union {
- u_short oldids[2]; /* 4: Ffs: old user and group ids. */
- ino_t inumber; /* 4: Lfs: inode number. */
+ u_int16_t oldids[2]; /* 4: Ffs: old user and group ids. */
+ int32_t inumber; /* 4: Lfs: inode number. */
} di_u;
- u_quad_t di_size; /* 8: File byte count. */
- struct timespec di_atime; /* 16: Last access time. */
- struct timespec di_mtime; /* 24: Last modified time. */
- struct timespec di_ctime; /* 32: Last inode change time. */
- daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
- daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
- u_long di_flags; /* 100: Status flags (chflags). */
- long di_blocks; /* 104: Blocks actually held. */
- long di_gen; /* 108: Generation number. */
- u_long di_uid; /* 112: File owner. */
- u_long di_gid; /* 116: File group. */
- long di_spare[2]; /* 120: Reserved; currently unused */
+ u_int64_t di_size; /* 8: File byte count. */
+ int32_t di_atime; /* 16: Last access time. */
+ int32_t di_atimensec; /* 20: Last access time. */
+ int32_t di_mtime; /* 24: Last modified time. */
+ int32_t di_mtimensec; /* 28: Last modified time. */
+ int32_t di_ctime; /* 32: Last inode change time. */
+ int32_t di_ctimensec; /* 36: Last inode change time. */
+ ufs_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */
+ ufs_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */
+ u_int32_t di_flags; /* 100: Status flags (chflags). */
+ int32_t di_blocks; /* 104: Blocks actually held. */
+ int32_t di_gen; /* 108: Generation number. */
+ u_int32_t di_uid; /* 112: File owner. */
+ u_int32_t di_gid; /* 116: File group. */
+ int32_t di_spare[2]; /* 120: Reserved; currently unused */
};
/*
@@ -91,9 +105,9 @@ struct dinode {
#define di_ouid di_u.oldids[0]
#define di_rdev di_db[0]
#define di_shortlink di_db
-#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(daddr_t))
+#define MAXSYMLINKLEN ((NDADDR + NIADDR) * sizeof(ufs_daddr_t))
-/* File modes. */
+/* File permissions. */
#define IEXEC 0000100 /* Executable. */
#define IWRITE 0000200 /* Writeable. */
#define IREAD 0000400 /* Readable. */
@@ -110,5 +124,6 @@ struct dinode {
#define IFREG 0100000 /* Regular file. */
#define IFLNK 0120000 /* Symbolic link. */
#define IFSOCK 0140000 /* UNIX domain socket. */
+#define IFWHT 0160000 /* Whiteout. */
#endif
diff --git a/sys/ufs/ufs/dir.h b/sys/ufs/ufs/dir.h
index 3a3ceb8..0c8680e 100644
--- a/sys/ufs/ufs/dir.h
+++ b/sys/ufs/ufs/dir.h
@@ -43,6 +43,17 @@
#define _UFS_UFS_DIR_H_
/*
+ * Theoretically, directories can be more than 2Gb in length, however, in
+ * practice this seems unlikely. So, we define the type doff_t as a 32-bit
+ * quantity to keep down the cost of doing lookup on a 32-bit machine.
+ */
+#define doff_t int32_t
+
+#ifdef notused
+#define MAXDIRSIZE (0x7fffffff)
+#endif
+
+/*
* A directory consists of some number of blocks of DIRBLKSIZ
* bytes, where DIRBLKSIZ is chosen such that it can be transferred
* to disk in a single atomic operation (e.g. 512 bytes on most machines).
@@ -71,11 +82,11 @@
#define MAXNAMLEN 255
struct direct {
- u_long d_ino; /* inode number of entry */
- u_short d_reclen; /* length of this record */
- u_char d_type; /* file type, see below */
- u_char d_namlen; /* length of string in d_name */
- char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */
+ u_int32_t d_ino; /* inode number of entry */
+ u_int16_t d_reclen; /* length of this record */
+ u_int8_t d_type; /* file type, see below */
+ u_int8_t d_namlen; /* length of string in d_name */
+ char d_name[MAXNAMLEN + 1];/* name with length <= MAXNAMLEN */
};
/*
@@ -89,6 +100,7 @@ struct direct {
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
+#define DT_WHT 14
/*
* Convert between stat structure types and directory types.
@@ -118,34 +130,33 @@ struct direct {
#define NEWDIRFMT 0
/*
- * Template for manipulating directories.
- * Should use struct direct's, but the name field
- * is MAXNAMLEN - 1, and this just won't do.
+ * Template for manipulating directories. Should use struct direct's,
+ * but the name field is MAXNAMLEN - 1, and this just won't do.
*/
struct dirtemplate {
- u_long dot_ino;
- short dot_reclen;
- u_char dot_type;
- u_char dot_namlen;
- char dot_name[4]; /* must be multiple of 4 */
- u_long dotdot_ino;
- short dotdot_reclen;
- u_char dotdot_type;
- u_char dotdot_namlen;
- char dotdot_name[4]; /* ditto */
+ u_int32_t dot_ino;
+ int16_t dot_reclen;
+ u_int8_t dot_type;
+ u_int8_t dot_namlen;
+ char dot_name[4]; /* must be multiple of 4 */
+ u_int32_t dotdot_ino;
+ int16_t dotdot_reclen;
+ u_int8_t dotdot_type;
+ u_int8_t dotdot_namlen;
+ char dotdot_name[4]; /* ditto */
};
/*
* This is the old format of directories, sanz type element.
*/
struct odirtemplate {
- u_long dot_ino;
- short dot_reclen;
- u_short dot_namlen;
- char dot_name[4]; /* must be multiple of 4 */
- u_long dotdot_ino;
- short dotdot_reclen;
- u_short dotdot_namlen;
- char dotdot_name[4]; /* ditto */
+ u_int32_t dot_ino;
+ int16_t dot_reclen;
+ u_int16_t dot_namlen;
+ char dot_name[4]; /* must be multiple of 4 */
+ u_int32_t dotdot_ino;
+ int16_t dotdot_reclen;
+ u_int16_t dotdot_namlen;
+ char dotdot_name[4]; /* ditto */
};
#endif /* !_DIR_H_ */
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index dc19d34..438471f 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -35,42 +35,33 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)inode.h 8.4 (Berkeley) 1/21/94
+ * @(#)inode.h 8.9 (Berkeley) 5/14/95
* $FreeBSD$
*/
#ifndef _UFS_UFS_INODE_H_
#define _UFS_UFS_INODE_H_
+#include <ufs/ufs/dir.h>
#include <ufs/ufs/dinode.h>
/*
- * Theoretically, directories can be more than 2Gb in length, however, in
- * practice this seems unlikely. So, we define the type doff_t as a long
- * to keep down the cost of doing lookup on a 32-bit machine. If you are
- * porting to a 64-bit architecture, you should make doff_t the same as off_t.
- */
-#define doff_t long
-
-/*
- * The inode is used to describe each active (or recently active)
- * file in the UFS filesystem. It is composed of two types of
- * information. The first part is the information that is needed
- * only while the file is active (such as the identity of the file
- * and linkage to speed its lookup). The second part is the
- * permanent meta-data associated with the file which is read
- * in from the permanent dinode from long term storage when the
- * file becomes active, and is put back when the file is no longer
- * being used.
+ * The inode is used to describe each active (or recently active) file in the
+ * UFS filesystem. It is composed of two types of information. The first part
+ * is the information that is needed only while the file is active (such as
+ * the identity of the file and linkage to speed its lookup). The second part
+ * is the permanent meta-data associated with the file which is read in
+ * from the permanent dinode from long term storage when the file becomes
+ * active, and is put back when the file is no longer being used.
*/
struct inode {
- struct inode *i_next; /* Hash chain forward. */
- struct inode **i_prev; /* Hash chain back. */
- struct vnode *i_vnode; /* Vnode associated with this inode. */
- struct vnode *i_devvp; /* Vnode for block I/O. */
- u_long i_flag; /* I* flags. */
- dev_t i_dev; /* Device associated with the inode. */
- ino_t i_number; /* The identity of the inode. */
+ LIST_ENTRY(inode) i_hash;/* Hash chain. */
+ struct vnode *i_vnode;/* Vnode associated with this inode. */
+ struct vnode *i_devvp;/* Vnode for block I/O. */
+ u_int32_t i_flag; /* flags, see below */
+ dev_t i_dev; /* Device associated with the inode. */
+ ino_t i_number; /* The identity of the inode. */
+
union { /* Associated filesystem. */
struct fs *fs; /* FFS */
struct lfs *lfs; /* LFS */
@@ -79,22 +70,21 @@ struct inode {
#define i_fs inode_u.fs
#define i_lfs inode_u.lfs
#define i_e2fs inode_u.e2fs
- struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
- u_quad_t i_modrev; /* Revision level for lease. */
- struct lockf *i_lockf; /* Head of byte-level lock list. */
- pid_t i_lockholder; /* DEBUG: holder of inode lock. */
- pid_t i_lockwaiter; /* DEBUG: latest blocked for inode lock. */
+ struct dquot *i_dquot[MAXQUOTAS]; /* Dquot structures. */
+ u_quad_t i_modrev; /* Revision level for NFS lease. */
+ struct lockf *i_lockf;/* Head of byte-level lock list. */
+ struct lock i_lock; /* Inode lock. */
/*
* Side effects; used during directory lookup.
*/
- long i_count; /* Size of free slot in directory. */
- doff_t i_endoff; /* End of useful stuff in directory. */
- 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. */
- u_long i_reclen; /* Size of found directory entry. */
- int i_lockcount; /* Process lock count (recursion) */
- long i_spare[10]; /* Spares to round up to 128 bytes. */
+ int32_t i_count; /* Size of free slot in directory. */
+ doff_t i_endoff; /* End of useful stuff in directory. */
+ 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. */
+ u_int32_t i_reclen; /* Size of found directory entry. */
+ int i_lockcount; /* Process lock count (recursion) */
+ int i_spare[10]; /* XXX spare storage (for ext2fs) */
/*
* The on-disk dinode itself.
*/
@@ -102,8 +92,10 @@ struct inode {
};
#define i_atime i_din.di_atime
+#define i_atimensec i_din.di_atimensec
#define i_blocks i_din.di_blocks
#define i_ctime i_din.di_ctime
+#define i_ctimensec i_din.di_ctimensec
#define i_db i_din.di_db
#define i_flags i_din.di_flags
#define i_gen i_din.di_gen
@@ -111,6 +103,7 @@ struct inode {
#define i_ib i_din.di_ib
#define i_mode i_din.di_mode
#define i_mtime i_din.di_mtime
+#define i_mtimensec i_din.di_mtimensec
#define i_nlink i_din.di_nlink
#define i_rdev i_din.di_rdev
#define i_shortlink i_din.di_shortlink
@@ -120,15 +113,12 @@ struct inode {
/* These flags are kept in i_flag. */
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
-#define IN_EXLOCK 0x0004 /* File has exclusive lock. */
-#define IN_LOCKED 0x0008 /* Inode lock. */
-#define IN_LWAIT 0x0010 /* Process waiting on file lock. */
-#define IN_MODIFIED 0x0020 /* Inode has been modified. */
-#define IN_RENAME 0x0040 /* Inode is being renamed. */
-#define IN_SHLOCK 0x0080 /* File has shared lock. */
-#define IN_UPDATE 0x0100 /* Modification time update request. */
-#define IN_WANTED 0x0200 /* Inode is wanted by a process. */
-#define IN_RECURSE 0x0400 /* Recursion expected */
+#define IN_UPDATE 0x0004 /* Modification time update request. */
+#define IN_MODIFIED 0x0008 /* Inode has been modified. */
+#define IN_RENAME 0x0010 /* Inode is being renamed. */
+#define IN_SHLOCK 0x0020 /* File has shared lock. */
+#define IN_EXLOCK 0x0040 /* File has exclusive lock. */
+#define IN_RECURSE 0x0080 /* Recursion expected */
#ifdef KERNEL
/*
@@ -136,7 +126,7 @@ struct inode {
* ufs_getlbns and used by truncate and bmap code.
*/
struct indir {
- daddr_t in_lbn; /* Logical block number. */
+ ufs_daddr_t in_lbn; /* Logical block number. */
int in_off; /* Offset in buffer. */
int in_exists; /* Flag if the block exists. */
};
@@ -155,25 +145,25 @@ struct indir {
if ((ip)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { \
(ip)->i_flag |= IN_MODIFIED; \
if ((ip)->i_flag & IN_ACCESS) \
- (ip)->i_atime.tv_sec \
+ (ip)->i_atime \
= ((t1) == &time ? tv_sec : (t1)->tv_sec); \
if ((ip)->i_flag & IN_UPDATE) { \
- (ip)->i_mtime.tv_sec \
+ (ip)->i_mtime \
= ((t2) == &time ? tv_sec : (t2)->tv_sec); \
(ip)->i_modrev++; \
} \
if ((ip)->i_flag & IN_CHANGE) \
- (ip)->i_ctime.tv_sec = tv_sec; \
+ (ip)->i_ctime = tv_sec; \
(ip)->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); \
} \
}
/* This overlays the fid structure (see mount.h). */
struct ufid {
- u_short ufid_len; /* Length of structure. */
- u_short ufid_pad; /* Force long alignment. */
- ino_t ufid_ino; /* File number (ino). */
- long ufid_gen; /* Generation number. */
+ u_int16_t ufid_len; /* Length of structure. */
+ u_int16_t ufid_pad; /* Force 32-bit alignment. */
+ ino_t ufid_ino; /* File number (ino). */
+ int32_t ufid_gen; /* Generation number. */
};
#endif /* KERNEL */
diff --git a/sys/ufs/ufs/quota.h b/sys/ufs/ufs/quota.h
index e780865..7b9ff40 100644
--- a/sys/ufs/ufs/quota.h
+++ b/sys/ufs/ufs/quota.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)quota.h 8.1 (Berkeley) 6/11/93
+ * @(#)quota.h 8.3 (Berkeley) 8/19/94
* $FreeBSD$
*/
@@ -49,8 +49,8 @@
* failure). The timer is started when the user crosses their soft limit, it
* is reset when they go below their soft limit.
*/
-#define MAX_IQ_TIME (7*24*60*60) /* 1 week */
-#define MAX_DQ_TIME (7*24*60*60) /* 1 week */
+#define MAX_IQ_TIME (7*24*60*60) /* seconds in 1 week */
+#define MAX_DQ_TIME (7*24*60*60) /* seconds in 1 week */
/*
* The following constants define the usage of the quota file array in the
@@ -97,15 +97,15 @@
* the vnode for each quota file (a pointer is retained in the ufsmount
* structure).
*/
-struct dqblk {
- u_long dqb_bhardlimit; /* absolute limit on disk blks alloc */
- u_long dqb_bsoftlimit; /* preferred limit on disk blks */
- u_long dqb_curblocks; /* current block count */
- u_long dqb_ihardlimit; /* maximum # allocated inodes + 1 */
- u_long dqb_isoftlimit; /* preferred inode limit */
- u_long dqb_curinodes; /* current # allocated inodes */
- time_t dqb_btime; /* time limit for excessive disk use */
- time_t dqb_itime; /* time limit for excessive files */
+struct dqblk {
+ u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
+ u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */
+ u_int32_t dqb_curblocks; /* current block count */
+ u_int32_t dqb_ihardlimit; /* maximum # allocated inodes + 1 */
+ u_int32_t dqb_isoftlimit; /* preferred inode limit */
+ u_int32_t dqb_curinodes; /* current # allocated inodes */
+ time_t dqb_btime; /* time limit for excessive disk use */
+ time_t dqb_itime; /* time limit for excessive files */
};
/*
@@ -114,14 +114,14 @@ struct dqblk {
* filesystem for the current user or group. A cache is kept of recently
* used entries.
*/
-struct dquot {
- struct dquot *dq_forw, **dq_back; /* hash list */
- struct dquot *dq_freef, **dq_freeb; /* free list */
- short dq_flags; /* flags, see below */
- short dq_cnt; /* count of active references */
- short dq_spare; /* unused spare padding */
- short dq_type; /* quota type of this dquot */
- u_long dq_id; /* identifier this applies to */
+struct dquot {
+ LIST_ENTRY(dquot) dq_hash; /* hash list */
+ TAILQ_ENTRY(dquot) dq_freelist; /* free list */
+ u_int16_t dq_flags; /* flags, see below */
+ u_int16_t dq_cnt; /* count of active references */
+ u_int16_t dq_spare; /* unused spare padding */
+ u_int16_t dq_type; /* quota type of this dquot */
+ u_int32_t dq_id; /* identifier this applies to */
struct ufsmount *dq_ump; /* filesystem that this is taken from */
struct dqblk dq_dqb; /* actual usage & quotas */
};
@@ -147,11 +147,11 @@ struct dquot {
#define dq_itime dq_dqb.dqb_itime
/*
- * If the system has never checked for a quota for this file, then it is set
- * to NODQUOT. Once a write attempt is made the inode pointer is set to
- * reference a dquot structure.
+ * If the system has never checked for a quota for this file, then it is
+ * set to NODQUOT. Once a write attempt is made the inode pointer is set
+ * to reference a dquot structure.
*/
-#define NODQUOT ((struct dquot *) 0)
+#define NODQUOT NULL
/*
* Flags to chkdq() and chkiq()
diff --git a/sys/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c
index e17b5b7..aef2b83 100644
--- a/sys/ufs/ufs/ufs_bmap.c
+++ b/sys/ufs/ufs/ufs_bmap.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_bmap.c 8.6 (Berkeley) 1/21/94
+ * @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
* $FreeBSD$
*/
@@ -63,9 +63,9 @@ int
ufs_bmap(ap)
struct vop_bmap_args /* {
struct vnode *a_vp;
- daddr_t a_bn;
+ ufs_daddr_t a_bn;
struct vnode **a_vpp;
- daddr_t *a_bnp;
+ ufs_daddr_t *a_bnp;
int *a_runp;
int *a_runb;
} */ *ap;
@@ -100,8 +100,8 @@ ufs_bmap(ap)
int
ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
struct vnode *vp;
- register daddr_t bn;
- daddr_t *bnp;
+ ufs_daddr_t bn;
+ ufs_daddr_t *bnp;
struct indir *ap;
int *nump;
int *runp;
@@ -113,7 +113,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
struct mount *mp;
struct vnode *devvp;
struct indir a[NIADDR+1], *xap;
- daddr_t daddr;
+ ufs_daddr_t daddr;
long metalbn;
int error, maxrun = 0, num;
@@ -209,12 +209,13 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
}
}
- daddr = ((daddr_t *)bp->b_data)[xap->in_off];
+ daddr = ((ufs_daddr_t *)bp->b_data)[xap->in_off];
if (num == 1 && daddr && runp) {
for (bn = xap->in_off + 1;
bn < MNINDIR(ump) && *runp < maxrun &&
- is_sequential(ump, ((daddr_t *)bp->b_data)[bn - 1],
- ((daddr_t *)bp->b_data)[bn]);
+ is_sequential(ump,
+ ((ufs_daddr_t *)bp->b_data)[bn - 1],
+ ((ufs_daddr_t *)bp->b_data)[bn]);
++bn, ++*runp);
bn = xap->in_off;
if (runb && bn) {
@@ -245,7 +246,7 @@ ufs_bmaparray(vp, bn, bnp, ap, nump, runp, runb)
int
ufs_getlbns(vp, bn, ap, nump)
struct vnode *vp;
- register daddr_t bn;
+ ufs_daddr_t bn;
struct indir *ap;
int *nump;
{
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h
index 4c114d9..a450e92 100644
--- a/sys/ufs/ufs/ufs_extern.h
+++ b/sys/ufs/ufs/ufs_extern.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_extern.h 8.3 (Berkeley) 4/16/94
+ * @(#)ufs_extern.h 8.10 (Berkeley) 5/14/95
* $FreeBSD$
*/
@@ -49,8 +49,8 @@ struct proc;
struct ucred;
struct uio;
struct vattr;
+struct vfsconf;
struct vnode;
-struct ufs_args;
int ufs_abortop __P((struct vop_abortop_args *));
int ufs_access __P((struct vop_access_args *));
@@ -71,7 +71,7 @@ int ufs_dirremove __P((struct vnode *, struct componentname*));
int ufs_dirrewrite
__P((struct inode *, struct inode *, struct componentname *));
int ufs_getattr __P((struct vop_getattr_args *));
-int ufs_getlbns __P((struct vnode *, daddr_t, struct indir *, int *));
+int ufs_getlbns __P((struct vnode *, ufs_daddr_t, struct indir *, int *));
struct vnode *
ufs_ihashget __P((dev_t, ino_t));
void ufs_ihashinit __P((void));
@@ -80,9 +80,14 @@ struct vnode *
ufs_ihashlookup __P((dev_t, ino_t));
void ufs_ihashrem __P((struct inode *));
int ufs_inactive __P((struct vop_inactive_args *));
-int ufs_init __P((void));
+int ufs_init __P((struct vfsconf *));
int ufs_ioctl __P((struct vop_ioctl_args *));
int ufs_islocked __P((struct vop_islocked_args *));
+#ifdef NFS
+#define ufs_lease_check lease_check
+#else
+#define ufs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
+#endif
int ufs_link __P((struct vop_link_args *));
int ufs_lock __P((struct vop_lock_args *));
int ufs_lookup __P((struct vop_lookup_args *));
@@ -95,9 +100,10 @@ int ufs_pathconf __P((struct vop_pathconf_args *));
int ufs_print __P((struct vop_print_args *));
int ufs_readdir __P((struct vop_readdir_args *));
int ufs_readlink __P((struct vop_readlink_args *));
-int ufs_reclaim __P((struct vop_reclaim_args *));
+int ufs_reclaim __P((struct vnode *, struct proc *));
int ufs_remove __P((struct vop_remove_args *));
int ufs_rename __P((struct vop_rename_args *));
+#define ufs_revoke vop_revoke
int ufs_rmdir __P((struct vop_rmdir_args *));
int ufs_root __P((struct mount *, struct vnode **));
int ufs_seek __P((struct vop_seek_args *));
@@ -108,6 +114,7 @@ int ufs_strategy __P((struct vop_strategy_args *));
int ufs_symlink __P((struct vop_symlink_args *));
int ufs_unlock __P((struct vop_unlock_args *));
int ufs_vinit __P((struct mount *, vop_t **, vop_t **, struct vnode **));
+int ufs_whiteout __P((struct vop_whiteout_args *));
int ufsspec_close __P((struct vop_close_args *));
int ufsspec_read __P((struct vop_read_args *));
int ufsspec_write __P((struct vop_write_args *));
diff --git a/sys/ufs/ufs/ufs_ihash.c b/sys/ufs/ufs/ufs_ihash.c
index a51af00..ea83308 100644
--- a/sys/ufs/ufs/ufs_ihash.c
+++ b/sys/ufs/ufs/ufs_ihash.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1982, 1986, 1989, 1991, 1993
+ * Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_ihash.c 8.4 (Berkeley) 12/30/93
+ * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
* $FreeBSD$
*/
@@ -47,9 +47,10 @@
/*
* Structures associated with inode cacheing.
*/
-struct inode **ihashtbl;
+LIST_HEAD(ihashhead, inode) *ihashtbl;
u_long ihash; /* size of hash table - 1 */
-#define INOHASH(device, inum) (((device) + (inum)) & ihash)
+#define INOHASH(device, inum) (&ihashtbl[((device) + (inum)) & ihash])
+struct simplelock ufs_ihash_slock;
/*
* Initialize inode hash table.
@@ -59,6 +60,7 @@ ufs_ihashinit()
{
ihashtbl = hashinit(desiredvnodes, M_UFSMNT, &ihash);
+ simple_lock_init(&ufs_ihash_slock);
}
/*
@@ -66,19 +68,21 @@ ufs_ihashinit()
* to it. If it is in core, return it, even if it is locked.
*/
struct vnode *
-ufs_ihashlookup(device, inum)
- dev_t device;
+ufs_ihashlookup(dev, inum)
+ dev_t dev;
ino_t inum;
{
- register struct inode *ip;
+ struct inode *ip;
- for (ip = ihashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
- if (ip == NULL)
- return (NULL);
- if (inum == ip->i_number && device == ip->i_dev)
- return (ITOV(ip));
- }
- /* NOTREACHED */
+ simple_lock(&ufs_ihash_slock);
+ for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next)
+ if (inum == ip->i_number && dev == ip->i_dev)
+ break;
+ simple_unlock(&ufs_ihash_slock);
+
+ if (ip)
+ return (ITOV(ip));
+ return (NULLVP);
}
/*
@@ -86,36 +90,28 @@ ufs_ihashlookup(device, inum)
* to it. If it is in core, but locked, wait for it.
*/
struct vnode *
-ufs_ihashget(device, inum)
- dev_t device;
+ufs_ihashget(dev, inum)
+ dev_t dev;
ino_t inum;
{
- register struct inode *ip;
+ struct proc *p = curproc; /* XXX */
+ struct inode *ip;
struct vnode *vp;
- for (;;)
- for (ip = ihashtbl[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) {
- if( curproc->p_pid != ip->i_lockholder) {
- ip->i_flag |= IN_WANTED;
- (void) tsleep(ip, PINOD, "uihget", 0);
- break;
- } else if (ip->i_flag & IN_RECURSE) {
- ip->i_lockcount++;
- } else {
- panic("ufs_ihashget: recursive lock not expected -- pid %d\n", ip->i_lockholder);
- }
- }
- vp = ITOV(ip);
- if (!vget(vp, 1))
- return (vp);
- break;
- }
+loop:
+ simple_lock(&ufs_ihash_slock);
+ for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) {
+ if (inum == ip->i_number && dev == ip->i_dev) {
+ vp = ITOV(ip);
+ simple_lock(&vp->v_interlock);
+ simple_unlock(&ufs_ihash_slock);
+ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p))
+ goto loop;
+ return (vp);
}
- /* NOTREACHED */
+ }
+ simple_unlock(&ufs_ihash_slock);
+ return (NULL);
}
/*
@@ -125,26 +121,16 @@ void
ufs_ihashins(ip)
struct inode *ip;
{
- struct inode **ipp, *iq;
+ struct proc *p = curproc; /* XXX */
+ struct ihashhead *ipp;
- ipp = &ihashtbl[INOHASH(ip->i_dev, ip->i_number)];
- iq = *ipp;
- if (iq)
- iq->i_prev = &ip->i_next;
- ip->i_next = iq;
- ip->i_prev = ipp;
- *ipp = ip;
- if ((ip->i_flag & IN_LOCKED) &&
- ((ip->i_flag & IN_RECURSE) == 0 ||
- (!curproc || (curproc && (ip->i_lockholder != curproc->p_pid)))))
- panic("ufs_ihashins: already locked");
- if (curproc) {
- ip->i_lockcount += 1;
- ip->i_lockholder = curproc->p_pid;
- } else {
- ip->i_lockholder = -1;
- }
- ip->i_flag |= IN_LOCKED;
+ /* lock the inode, then put it on the appropriate hash list */
+ lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p);
+
+ simple_lock(&ufs_ihash_slock);
+ ipp = INOHASH(ip->i_dev, ip->i_number);
+ LIST_INSERT_HEAD(ipp, ip, i_hash);
+ simple_unlock(&ufs_ihash_slock);
}
/*
@@ -152,16 +138,13 @@ ufs_ihashins(ip)
*/
void
ufs_ihashrem(ip)
- register struct inode *ip;
+ struct inode *ip;
{
- register struct inode *iq;
-
- iq = ip->i_next;
- if (iq)
- iq->i_prev = ip->i_prev;
- *ip->i_prev = iq;
+ simple_lock(&ufs_ihash_slock);
+ LIST_REMOVE(ip, i_hash);
#ifdef DIAGNOSTIC
- ip->i_next = NULL;
- ip->i_prev = NULL;
+ ip->i_hash.le_next = NULL;
+ ip->i_hash.le_prev = NULL;
#endif
+ simple_unlock(&ufs_ihash_slock);
}
diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c
index 45616bb..dd59142 100644
--- a/sys/ufs/ufs/ufs_inode.c
+++ b/sys/ufs/ufs/ufs_inode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1991, 1993
+ * Copyright (c) 1991, 1993, 1995
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_inode.c 8.4 (Berkeley) 1/21/94
+ * @(#)ufs_inode.c 8.9 (Berkeley) 5/14/95
* $FreeBSD$
*/
@@ -57,24 +57,6 @@
u_long nextgennumber; /* Next generation number to assign. */
int prtactive = 0; /* 1 => print out reclaim of active vnodes */
-int
-ufs_init()
-{
- static int first = 1;
-
- if (!first)
- return (0);
- first = 0;
-
-#ifdef DIAGNOSTIC
- if ((sizeof(struct inode) - 1) & sizeof(struct inode))
- printf("ufs_init: bad size %d\n", sizeof(struct inode));
-#endif
- ufs_ihashinit();
- dqinit();
- return (0);
-}
-
/*
* Last reference to an inode. If necessary, write or delete it.
*/
@@ -82,39 +64,29 @@ int
ufs_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
+ struct proc *a_p;
} */ *ap;
{
- register struct vnode *vp = ap->a_vp;
- register struct inode *ip = VTOI(vp);
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
+ struct proc *p = ap->a_p;
struct timeval tv;
- int mode, error;
+ int mode, error = 0;
if (prtactive && vp->v_usecount != 0)
vprint("ufs_inactive: pushing active", vp);
- /* Get rid of inodes related to stale file handles. */
- if (ip->i_mode == 0) {
- if ((vp->v_flag & VXLOCK) == 0)
- vgone(vp);
- return (0);
- }
-
- error = 0;
-#ifdef DIAGNOSTIC
- if (VOP_ISLOCKED(vp))
- panic("ufs_inactive: locked inode");
- if (curproc)
- ip->i_lockholder = curproc->p_pid;
- else
- ip->i_lockholder = -1;
-#endif
- ip->i_flag |= IN_LOCKED;
+ /*
+ * Ignore inodes related to stale file handles.
+ */
+ if (ip->i_mode == 0)
+ goto out;
if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
#ifdef QUOTA
if (!getinoquota(ip))
(void)chkiq(ip, -1, NOCRED, 0);
#endif
- error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL);
+ error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, p);
ip->i_rdev = 0;
mode = ip->i_mode;
ip->i_mode = 0;
@@ -125,13 +97,14 @@ ufs_inactive(ap)
tv = time;
VOP_UPDATE(vp, &tv, &tv, 0);
}
- VOP_UNLOCK(vp);
+out:
+ VOP_UNLOCK(vp, 0, p);
/*
* If we are done with the inode, reclaim it
* so that it can be reused immediately.
*/
- if (vp->v_usecount == 0 && ip->i_mode == 0)
- vgone(vp);
+ if (ip->i_mode == 0)
+ vrecycle(vp, (struct simplelock *)0, p);
return (error);
}
@@ -139,14 +112,11 @@ ufs_inactive(ap)
* Reclaim an inode so that it can be used for other purposes.
*/
int
-ufs_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
+ufs_reclaim(vp, p)
+ struct vnode *vp;
+ struct proc *p;
{
- register struct vnode *vp = ap->a_vp;
register struct inode *ip;
- int type;
#ifdef QUOTA
int i;
#endif
@@ -174,23 +144,5 @@ ufs_reclaim(ap)
}
}
#endif
- switch (vp->v_mount->mnt_stat.f_type) {
- case MOUNT_EXT2FS:
- type = M_FFSNODE;
- break;
- case MOUNT_UFS:
- type = M_FFSNODE;
- break;
- case MOUNT_MFS:
- type = M_MFSNODE;
- break;
- case MOUNT_LFS:
- type = M_LFSNODE;
- break;
- default:
- panic("ufs_reclaim: not ufs file");
- }
- FREE(vp->v_data, type);
- vp->v_data = NULL;
return (0);
}
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
index 4b99584..38fe929 100644
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94
+ * @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95
* $FreeBSD$
*/
@@ -128,6 +128,7 @@ ufs_lookup(ap)
struct ucred *cred = cnp->cn_cred;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
+ struct proc *p = cnp->cn_proc;
bp = NULL;
slotoffset = -1;
@@ -175,14 +176,14 @@ ufs_lookup(ap)
VREF(vdp);
error = 0;
} else if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp);
- error = vget(vdp, 1);
+ VOP_UNLOCK(pdp, 0, p);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!error && lockparent && (flags & ISLASTCN))
- error = VOP_LOCK(pdp);
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
} else {
- error = vget(vdp, 1);
+ error = vget(vdp, LK_EXCLUSIVE, p);
if (!lockparent || error || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
/*
* Check that the capability number did not change
@@ -193,10 +194,9 @@ ufs_lookup(ap)
return (0);
vput(vdp);
if (lockparent && pdp != vdp && (flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
}
- error = VOP_LOCK(pdp);
- if (error)
+ if (error = vn_lock(pdp, LK_EXCLUSIVE, p))
return (error);
vdp = pdp;
dp = VTOI(pdp);
@@ -337,6 +337,17 @@ searchloop:
* reclen in ndp->ni_ufs area, and release
* directory buffer.
*/
+ if (vdp->v_mount->mnt_maxsymlinklen > 0 &&
+ ep->d_type == DT_WHT) {
+ slotstatus = FOUND;
+ slotoffset = dp->i_offset;
+ slotsize = ep->d_reclen;
+ dp->i_reclen = slotsize;
+ enduseful = dp->i_size;
+ ap->a_cnp->cn_flags |= ISWHITEOUT;
+ numdirpasses--;
+ goto notfound;
+ }
dp->i_ino = ep->d_ino;
dp->i_reclen = ep->d_reclen;
brelse(bp);
@@ -349,7 +360,7 @@ searchloop:
if (ep->d_ino)
enduseful = dp->i_offset;
}
-/* notfound: */
+notfound:
/*
* If we started in the middle of the directory and failed
* to find our target, we must check the beginning as well.
@@ -367,7 +378,10 @@ searchloop:
* directory has not been removed, then can consider
* allowing file to be created.
*/
- if ((nameiop == CREATE || nameiop == RENAME) &&
+ if ((nameiop == CREATE || nameiop == RENAME ||
+ (nameiop == DELETE &&
+ (ap->a_cnp->cn_flags & DOWHITEOUT) &&
+ (ap->a_cnp->cn_flags & ISWHITEOUT))) &&
(flags & ISLASTCN) && dp->i_nlink != 0) {
/*
* Access for write is interpreted as allowing
@@ -389,6 +403,12 @@ searchloop:
dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ);
dp->i_count = 0;
enduseful = dp->i_offset;
+ } else if (nameiop == DELETE) {
+ dp->i_offset = slotoffset;
+ if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0)
+ dp->i_count = 0;
+ else
+ dp->i_count = dp->i_offset - prevoff;
} else {
dp->i_offset = slotoffset;
dp->i_count = slotsize;
@@ -412,7 +432,7 @@ searchloop:
*/
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (EJUSTRETURN);
}
/*
@@ -484,13 +504,14 @@ found:
if ((dp->i_mode & ISVTX) &&
cred->cr_uid != 0 &&
cred->cr_uid != dp->i_uid &&
+ tdp->v_type != VLNK &&
VTOI(tdp)->i_uid != cred->cr_uid) {
vput(tdp);
return (EPERM);
}
*vpp = tdp;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (0);
}
@@ -500,10 +521,8 @@ found:
* Must get inode of directory entry to verify it's a
* regular file, or empty directory.
*/
- if (nameiop == RENAME && wantparent &&
- (flags & ISLASTCN)) {
- error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc);
- if (error)
+ if (nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
+ if (error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc))
return (error);
/*
* Careful about locking second inode.
@@ -517,7 +536,7 @@ found:
*vpp = tdp;
cnp->cn_flags |= SAVENAME;
if (!lockparent)
- VOP_UNLOCK(vdp);
+ VOP_UNLOCK(vdp, 0, p);
return (0);
}
@@ -542,14 +561,13 @@ found:
*/
pdp = vdp;
if (flags & ISDOTDOT) {
- VOP_UNLOCK(pdp); /* race to get the inode */
- error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
- if (error) {
- VOP_LOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p); /* race to get the inode */
+ if (error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp)) {
+ vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, p);
return (error);
}
if (lockparent && (flags & ISLASTCN) &&
- (error = VOP_LOCK(pdp))) {
+ (error = vn_lock(pdp, LK_EXCLUSIVE, p))) {
vput(tdp);
return (error);
}
@@ -562,7 +580,7 @@ found:
if (error)
return (error);
if (!lockparent || !(flags & ISLASTCN))
- VOP_UNLOCK(pdp);
+ VOP_UNLOCK(pdp, 0, p);
*vpp = tdp;
}
@@ -621,6 +639,8 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock)
printf("First bad\n");
goto bad;
}
+ if (ep->d_ino == 0)
+ return (0);
for (i = 0; i < namlen; i++)
if (ep->d_name[i] == '\0') {
/*return (1); */
@@ -629,9 +649,9 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock)
}
if (ep->d_name[i])
goto bad;
- return (ep->d_name[i]);
+ return (0);
bad:
- return(1);
+ return (1);
}
/*
@@ -648,15 +668,8 @@ ufs_direnter(ip, dvp, cnp)
struct vnode *dvp;
register struct componentname *cnp;
{
- register struct direct *ep, *nep;
register struct inode *dp;
- struct buf *bp;
struct direct newdir;
- struct iovec aiov;
- struct uio auio;
- u_int dsize;
- int error, loc, newentrysize, spacefree;
- char *dirbuf;
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & SAVENAME) == 0)
@@ -676,7 +689,33 @@ ufs_direnter(ip, dvp, cnp)
newdir.d_type = tmp; }
# endif
}
- newentrysize = DIRSIZ(OFSFMT(dvp), &newdir);
+ return (ufs_direnter2(dvp, &newdir, cnp->cn_cred, cnp->cn_proc));
+}
+
+/*
+ * Common entry point for directory entry removal used by ufs_direnter
+ * and ufs_whiteout
+ */
+int
+ufs_direnter2(dvp, dirp, cr, p)
+ struct vnode *dvp;
+ struct direct *dirp;
+ struct ucred *cr;
+ struct proc *p;
+{
+ int newentrysize;
+ struct inode *dp;
+ struct buf *bp;
+ struct iovec aiov;
+ struct uio auio;
+ u_int dsize;
+ struct direct *ep, *nep;
+ int error, loc, spacefree;
+ char *dirbuf;
+
+ dp = VTOI(dvp);
+ newentrysize = DIRSIZ(OFSFMT(dvp), dirp);
+
if (dp->i_count == 0) {
/*
* If dp->i_count is 0, then namei could find no
@@ -685,22 +724,22 @@ ufs_direnter(ip, dvp, cnp)
* new entry into a fresh block.
*/
if (dp->i_offset & (DIRBLKSIZ - 1))
- panic("ufs_direnter: newblk");
+ panic("ufs_direnter2: newblk");
auio.uio_offset = dp->i_offset;
- newdir.d_reclen = DIRBLKSIZ;
+ dirp->d_reclen = DIRBLKSIZ;
auio.uio_resid = newentrysize;
aiov.iov_len = newentrysize;
- aiov.iov_base = (caddr_t)&newdir;
+ aiov.iov_base = (caddr_t)dirp;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_WRITE;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_procp = (struct proc *)0;
- error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred);
+ error = VOP_WRITE(dvp, &auio, IO_SYNC, cr);
if (DIRBLKSIZ >
VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
/* XXX should grow with balloc() */
- panic("ufs_direnter: frag size");
+ panic("ufs_direnter2: frag size");
else if (!error) {
dp->i_size = roundup2(dp->i_size, DIRBLKSIZ);
dp->i_flag |= IN_CHANGE;
@@ -761,18 +800,20 @@ ufs_direnter(ip, dvp, cnp)
* Update the pointer fields in the previous entry (if any),
* copy in the new entry, and write out the block.
*/
- if (ep->d_ino == 0) {
+ if (ep->d_ino == 0 ||
+ (ep->d_ino == WINO &&
+ bcmp(ep->d_name, dirp->d_name, dirp->d_namlen) == 0)) {
if (spacefree + dsize < newentrysize)
- panic("ufs_direnter: compact1");
- newdir.d_reclen = spacefree + dsize;
+ panic("ufs_direnter2: compact1");
+ dirp->d_reclen = spacefree + dsize;
} else {
if (spacefree < newentrysize)
- panic("ufs_direnter: compact2");
- newdir.d_reclen = spacefree;
+ panic("ufs_direnter2: compact2");
+ dirp->d_reclen = spacefree;
ep->d_reclen = dsize;
ep = (struct direct *)((char *)ep + dsize);
}
- bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize);
+ bcopy((caddr_t)dirp, (caddr_t)ep, (u_int)newentrysize);
if (dvp->v_mount->mnt_flag & MNT_ASYNC) {
bdwrite(bp);
@@ -782,8 +823,7 @@ ufs_direnter(ip, dvp, cnp)
}
dp->i_flag |= IN_CHANGE | IN_UPDATE;
if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
- error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC,
- cnp->cn_cred, cnp->cn_proc);
+ error = VOP_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr, p);
return (error);
}
@@ -810,6 +850,21 @@ ufs_dirremove(dvp, cnp)
int error;
dp = VTOI(dvp);
+
+ if (cnp->cn_flags & DOWHITEOUT) {
+ /*
+ * Whiteout entry: set d_ino to WINO.
+ */
+ if (error =
+ VOP_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp))
+ return (error);
+ ep->d_ino = WINO;
+ ep->d_type = DT_WHT;
+ error = VOP_BWRITE(bp);
+ dp->i_flag |= IN_CHANGE | IN_UPDATE;
+ return (error);
+ }
+
if (dp->i_count == 0) {
/*
* First entry in block: set d_ino to zero.
@@ -906,7 +961,7 @@ ufs_dirempty(ip, parentino, cred)
if (dp->d_reclen == 0)
return (0);
/* skip empty entries */
- if (dp->d_ino == 0)
+ if (dp->d_ino == 0 || dp->d_ino == WINO)
continue;
/* accept only "." and ".." */
# if (BYTE_ORDER == LITTLE_ENDIAN)
diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c
index 88d659d..6d69a98 100644
--- a/sys/ufs/ufs/ufs_quota.c
+++ b/sys/ufs/ufs/ufs_quota.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1982, 1986, 1990, 1993
+ * Copyright (c) 1982, 1986, 1990, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_quota.c 8.2 (Berkeley) 12/30/93
+ * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -379,8 +379,8 @@ quotaon(p, mp, type, fname)
register int type;
caddr_t fname;
{
- register struct ufsmount *ump = VFSTOUFS(mp);
- register struct vnode *vp, **vpp;
+ struct ufsmount *ump = VFSTOUFS(mp);
+ struct vnode *vp, **vpp;
struct vnode *nextvp;
struct dquot *dq;
int error;
@@ -392,15 +392,11 @@ quotaon(p, mp, type, fname)
if (error)
return (error);
vp = nd.ni_vp;
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
if (vp->v_type != VREG) {
(void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
return (EACCES);
}
- if (vfs_busy(mp)) {
- (void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
- return (EBUSY);
- }
if (*vpp != vp)
quotaoff(p, mp, type);
ump->um_qflags[type] |= QTF_OPENING;
@@ -432,7 +428,7 @@ again:
nextvp = vp->v_mntvnodes.le_next;
if (vp->v_writecount == 0)
continue;
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto again;
error = getinoquota(VTOI(vp));
if (error) {
@@ -446,7 +442,6 @@ again:
ump->um_qflags[type] &= ~QTF_OPENING;
if (error)
quotaoff(p, mp, type);
- vfs_unbusy(mp);
return (error);
}
@@ -459,15 +454,13 @@ quotaoff(p, mp, type)
struct mount *mp;
register int type;
{
- register struct vnode *vp;
+ struct vnode *vp;
struct vnode *qvp, *nextvp;
struct ufsmount *ump = VFSTOUFS(mp);
- register struct dquot *dq;
- register struct inode *ip;
+ struct dquot *dq;
+ struct inode *ip;
int error;
- if ((mp->mnt_flag & MNT_MPBUSY) == 0)
- panic("quotaoff: not busy");
if ((qvp = ump->um_quotas[type]) == NULLVP)
return (0);
ump->um_qflags[type] |= QTF_CLOSING;
@@ -478,7 +471,7 @@ quotaoff(p, mp, type)
again:
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) {
nextvp = vp->v_mntvnodes.le_next;
- if (vget(vp, 1))
+ if (vget(vp, LK_EXCLUSIVE, p))
goto again;
ip = VTOI(vp);
dq = ip->i_dquot[type];
@@ -641,16 +634,15 @@ qsync(mp)
struct mount *mp;
{
struct ufsmount *ump = VFSTOUFS(mp);
- register struct vnode *vp, *nextvp;
- register struct dquot *dq;
- register int i;
+ struct proc *p = curproc; /* XXX */
+ struct vnode *vp, *nextvp;
+ struct dquot *dq;
+ int i, error;
/*
* Check if the mount point has any quotas.
* If not, simply return.
*/
- if ((mp->mnt_flag & MNT_MPBUSY) == 0)
- panic("qsync: not busy");
for (i = 0; i < MAXQUOTAS; i++)
if (ump->um_quotas[i] != NULLVP)
break;
@@ -660,36 +652,48 @@ qsync(mp)
* Search vnodes associated with this mount point,
* synchronizing any modified dquot structures.
*/
+ simple_lock(&mntvnode_slock);
again:
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) {
+ if (vp->v_mount != mp)
+ goto again;
nextvp = vp->v_mntvnodes.le_next;
- if (VOP_ISLOCKED(vp))
+ simple_lock(&vp->v_interlock);
+ simple_unlock(&mntvnode_slock);
+ error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
+ if (error) {
+ simple_lock(&mntvnode_slock);
+ if (error == ENOENT)
+ goto again;
continue;
- if (vget(vp, 1))
- goto again;
+ }
for (i = 0; i < MAXQUOTAS; i++) {
dq = VTOI(vp)->i_dquot[i];
if (dq != NODQUOT && (dq->dq_flags & DQ_MOD))
dqsync(vp, dq);
}
vput(vp);
- if (vp->v_mntvnodes.le_next != nextvp || vp->v_mount != mp)
+ simple_lock(&mntvnode_slock);
+ if (vp->v_mntvnodes.le_next != nextvp)
goto again;
}
+ simple_unlock(&mntvnode_slock);
return (0);
}
/*
* Code pertaining to management of the in-core dquot data structures.
*/
-static struct dquot **dqhashtbl;
+#define DQHASH(dqvp, id) \
+ (&dqhashtbl[((((int)(dqvp)) >> 8) + id) & dqhash])
+static LIST_HEAD(dqhash, dquot) *dqhashtbl;
static u_long dqhash;
/*
* Dquot free list.
*/
#define DQUOTINC 5 /* minimum free dquots desired */
-static struct dquot *dqfreel, **dqback = &dqfreel;
+TAILQ_HEAD(dqfreelist, dquot) dqfreelist;
static long numdquot, desireddquot = DQUOTINC;
/*
@@ -700,6 +704,7 @@ dqinit()
{
dqhashtbl = hashinit(desiredvnodes, M_DQUOT, &dqhash);
+ TAILQ_INIT(&dqfreelist);
}
/*
@@ -714,8 +719,10 @@ dqget(vp, id, ump, type, dqp)
register int type;
struct dquot **dqp;
{
- register struct dquot *dq, *dp, **dpp;
- register struct vnode *dqvp;
+ struct proc *p = curproc; /* XXX */
+ struct dquot *dq;
+ struct dqhash *dqh;
+ struct vnode *dqvp;
struct iovec aiov;
struct uio auio;
int error;
@@ -728,8 +735,8 @@ dqget(vp, id, ump, type, dqp)
/*
* Check the cache first.
*/
- dpp = &dqhashtbl[((((int)(dqvp)) >> 8) + id) & dqhash];
- for (dq = *dpp; dq; dq = dq->dq_forw) {
+ dqh = DQHASH(dqvp, id);
+ for (dq = dqh->lh_first; dq; dq = dq->dq_hash.le_next) {
if (dq->dq_id != id ||
dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
continue;
@@ -737,13 +744,8 @@ dqget(vp, id, ump, type, dqp)
* Cache hit with no references. Take
* the structure off the free list.
*/
- if (dq->dq_cnt == 0) {
- if ((dp = dq->dq_freef) != NODQUOT)
- dp->dq_freeb = dq->dq_freeb;
- else
- dqback = dq->dq_freeb;
- *dq->dq_freeb = dp;
- }
+ if (dq->dq_cnt == 0)
+ TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
DQREF(dq);
*dqp = dq;
return (0);
@@ -751,43 +753,30 @@ dqget(vp, id, ump, type, dqp)
/*
* Not in cache, allocate a new one.
*/
- if (dqfreel == NODQUOT && numdquot < MAXQUOTAS * desiredvnodes)
+ if (dqfreelist.tqh_first == NODQUOT &&
+ numdquot < MAXQUOTAS * desiredvnodes)
desireddquot += DQUOTINC;
if (numdquot < desireddquot) {
dq = (struct dquot *)malloc(sizeof *dq, M_DQUOT, M_WAITOK);
bzero((char *)dq, sizeof *dq);
numdquot++;
} else {
- if ((dq = dqfreel) == NULL) {
+ if ((dq = dqfreelist.tqh_first) == NULL) {
tablefull("dquot");
*dqp = NODQUOT;
return (EUSERS);
}
if (dq->dq_cnt || (dq->dq_flags & DQ_MOD))
panic("free dquot isn't");
- if ((dp = dq->dq_freef) != NODQUOT)
- dp->dq_freeb = &dqfreel;
- else
- dqback = &dqfreel;
- dqfreel = dp;
- dq->dq_freef = NULL;
- dq->dq_freeb = NULL;
- dp = dq->dq_forw;
- if (dp)
- dp->dq_back = dq->dq_back;
- *dq->dq_back = dp;
+ TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
+ LIST_REMOVE(dq, dq_hash);
}
/*
* Initialize the contents of the dquot structure.
*/
if (vp != dqvp)
- VOP_LOCK(dqvp);
- dp = *dpp;
- if (dp)
- dp->dq_back = &dq->dq_forw;
- dq->dq_forw = dp;
- dq->dq_back = dpp;
- *dpp = dq;
+ vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p);
+ LIST_INSERT_HEAD(dqh, dq, dq_hash);
DQREF(dq);
dq->dq_flags = DQ_LOCK;
dq->dq_id = id;
@@ -806,7 +795,7 @@ dqget(vp, id, ump, type, dqp)
if (auio.uio_resid == sizeof(struct dqblk) && error == 0)
bzero((caddr_t)&dq->dq_dqb, sizeof(struct dqblk));
if (vp != dqvp)
- VOP_UNLOCK(dqvp);
+ VOP_UNLOCK(dqvp, 0, p);
if (dq->dq_flags & DQ_WANT)
wakeup((caddr_t)dq);
dq->dq_flags = 0;
@@ -815,12 +804,7 @@ dqget(vp, id, ump, type, dqp)
* quota structure and reflect problem to caller.
*/
if (error) {
- dp = dq->dq_forw;
- if (dp)
- dp->dq_back = dq->dq_back;
- *dq->dq_back = dp;
- dq->dq_forw = NULL;
- dq->dq_back = NULL;
+ LIST_REMOVE(dq, dq_hash);
dqrele(vp, dq);
*dqp = NODQUOT;
return (error);
@@ -874,15 +858,7 @@ dqrele(vp, dq)
(void) dqsync(vp, dq);
if (--dq->dq_cnt > 0)
return;
- if (dqfreel != NODQUOT) {
- *dqback = dq;
- dq->dq_freeb = dqback;
- } else {
- dqfreel = dq;
- dq->dq_freeb = &dqfreel;
- }
- dq->dq_freef = NODQUOT;
- dqback = &dq->dq_freef;
+ TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist);
}
/*
@@ -891,8 +867,9 @@ dqrele(vp, dq)
static int
dqsync(vp, dq)
struct vnode *vp;
- register struct dquot *dq;
+ struct dquot *dq;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *dqvp;
struct iovec aiov;
struct uio auio;
@@ -905,13 +882,13 @@ dqsync(vp, dq)
if ((dqvp = dq->dq_ump->um_quotas[dq->dq_type]) == NULLVP)
panic("dqsync: file");
if (vp != dqvp)
- VOP_LOCK(dqvp);
+ vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p);
while (dq->dq_flags & DQ_LOCK) {
dq->dq_flags |= DQ_WANT;
(void) tsleep((caddr_t)dq, PINOD+2, "dqsync", 0);
if ((dq->dq_flags & DQ_MOD) == 0) {
if (vp != dqvp)
- VOP_UNLOCK(dqvp);
+ VOP_UNLOCK(dqvp, 0, p);
return (0);
}
}
@@ -932,7 +909,7 @@ dqsync(vp, dq)
wakeup((caddr_t)dq);
dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT);
if (vp != dqvp)
- VOP_UNLOCK(dqvp);
+ VOP_UNLOCK(dqvp, 0, p);
return (error);
}
@@ -943,26 +920,22 @@ static void
dqflush(vp)
register struct vnode *vp;
{
- register struct dquot *dq, *dp, **dpp, *nextdq;
+ register struct dquot *dq, *nextdq;
+ struct dqhash *dqh;
/*
* Move all dquot's that used to refer to this quota
* file off their hash chains (they will eventually
* fall off the head of the free list and be re-used).
*/
- for (dpp = &dqhashtbl[dqhash]; dpp >= dqhashtbl; dpp--) {
- for (dq = *dpp; dq; dq = nextdq) {
- nextdq = dq->dq_forw;
+ for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) {
+ for (dq = dqh->lh_first; dq; dq = nextdq) {
+ nextdq = dq->dq_hash.le_next;
if (dq->dq_ump->um_quotas[dq->dq_type] != vp)
continue;
if (dq->dq_cnt)
panic("dqflush: stray dquot");
- dp = dq->dq_forw;
- if (dp)
- dp->dq_back = dq->dq_back;
- *dq->dq_back = dp;
- dq->dq_forw = NULL;
- dq->dq_back = NULL;
+ LIST_REMOVE(dq, dq_hash);
dq->dq_ump = (struct ufsmount *)0;
}
}
diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c
index 99497e6..c83ba17 100644
--- a/sys/ufs/ufs/ufs_readwrite.c
+++ b/sys/ufs/ufs/ufs_readwrite.c
@@ -30,12 +30,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_readwrite.c 8.7 (Berkeley) 1/21/94
+ * @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95
* $FreeBSD$
*/
#ifdef LFS_READWRITE
-#define BLKSIZE(a, b, c) blksize(a)
+#define BLKSIZE(a, b, c) blksize(a, b, c)
#define FS struct lfs
#define I_FS i_lfs
#define READ lfs_read
@@ -75,7 +75,7 @@ READ(ap)
register struct uio *uio;
register FS *fs;
struct buf *bp;
- daddr_t lbn, nextlbn;
+ ufs_daddr_t lbn, nextlbn;
off_t bytesinfile;
long size, xfersize, blkoffset;
int error;
@@ -99,7 +99,7 @@ READ(ap)
panic("%s: type %d", READ_S, vp->v_type);
#endif
fs = ip->I_FS;
- if ((u_quad_t)uio->uio_offset > fs->fs_maxfilesize)
+ if ((u_int64_t)uio->uio_offset > fs->fs_maxfilesize)
return (EFBIG);
for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
@@ -189,7 +189,7 @@ WRITE(ap)
register FS *fs;
struct buf *bp;
struct proc *p;
- daddr_t lbn;
+ ufs_daddr_t lbn;
off_t osize;
int blkoffset, error, flags, ioflag, resid, size, xfersize;
struct timeval tv;
@@ -223,7 +223,7 @@ WRITE(ap)
fs = ip->I_FS;
if (uio->uio_offset < 0 ||
- (u_quad_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
+ (u_int64_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
return (EFBIG);
/*
* Maybe this should be above the vnode op call, but so long as
@@ -253,7 +253,7 @@ WRITE(ap)
#ifdef LFS_READWRITE
(void)lfs_check(vp, lbn);
- error = lfs_balloc(vp, xfersize, lbn, &bp);
+ error = lfs_balloc(vp, blkoffset, xfersize, lbn, &bp);
#else
if (fs->fs_bsize > xfersize)
flags |= B_CLRBUF;
diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c
index 7ae2a27..a0d6af5 100644
--- a/sys/ufs/ufs/ufs_vfsops.c
+++ b/sys/ufs/ufs/ufs_vfsops.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_vfsops.c 8.4 (Berkeley) 4/16/94
+ * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95
* $FreeBSD$
*/
@@ -57,11 +57,6 @@
#include <ufs/ufs/ufs_extern.h>
/*
- * Flag to permit forcible unmounting.
- */
-int doforce = 1;
-
-/*
* Make a filesystem operational.
* Nothing to do at the moment.
*/
@@ -129,40 +124,61 @@ ufs_quotactl(mp, cmds, uid, arg, p)
type = cmds & SUBCMDMASK;
if ((u_int)type >= MAXQUOTAS)
return (EINVAL);
+ if (vfs_busy(mp, LK_NOWAIT, 0, p))
+ return (0);
switch (cmd) {
case Q_QUOTAON:
- return (quotaon(p, mp, type, arg));
+ error = quotaon(p, mp, type, arg);
+ break;
case Q_QUOTAOFF:
- if (vfs_busy(mp))
- return (0);
error = quotaoff(p, mp, type);
- vfs_unbusy(mp);
- return (error);
+ break;
case Q_SETQUOTA:
- return (setquota(mp, uid, type, arg));
+ error = setquota(mp, uid, type, arg);
+ break;
case Q_SETUSE:
- return (setuse(mp, uid, type, arg));
+ error = setuse(mp, uid, type, arg);
+ break;
case Q_GETQUOTA:
- return (getquota(mp, uid, type, arg));
+ error = getquota(mp, uid, type, arg);
+ break;
case Q_SYNC:
- if (vfs_busy(mp))
- return (0);
error = qsync(mp);
- vfs_unbusy(mp);
- return (error);
+ break;
default:
- return (EINVAL);
+ error = EINVAL;
+ break;
}
- /* NOTREACHED */
+ vfs_unbusy(mp, p);
+ return (error);
+#endif
+}
+
+/*
+ * Initial UFS filesystems, done only once.
+ */
+int
+ufs_init(vfsp)
+ struct vfsconf *vfsp;
+{
+ static int done;
+
+ if (done)
+ return (0);
+ done = 1;
+ ufs_ihashinit();
+#ifdef QUOTA
+ dqinit();
#endif
+ return (0);
}
/*
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index edc022f..66527c1 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1982, 1986, 1989, 1993
+ * Copyright (c) 1982, 1986, 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufs_vnops.c 8.10 (Berkeley) 4/1/94
+ * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
* $FreeBSD$
*/
@@ -80,8 +80,8 @@ static int ufs_chown
#endif /* EXT2FS */
union _qcvt {
- quad_t qcvt;
- long val[2];
+ int64_t qcvt;
+ int32_t val[2];
};
#define SETHIGH(q, h) { \
union _qcvt tmp; \
@@ -204,8 +204,10 @@ ufs_close(ap)
register struct vnode *vp = ap->a_vp;
register struct inode *ip = VTOI(vp);
- if (vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
+ simple_lock(&vp->v_interlock);
+ if (vp->v_usecount > 1)
ITIMES(ip, &time, &time);
+ simple_unlock(&vp->v_interlock);
return (0);
}
@@ -317,9 +319,12 @@ ufs_getattr(ap)
vap->va_gid = ip->i_gid;
vap->va_rdev = (dev_t)ip->i_rdev;
vap->va_size = ip->i_din.di_size;
- vap->va_atime = ip->i_atime;
- vap->va_mtime = ip->i_mtime;
- vap->va_ctime = ip->i_ctime;
+ vap->va_atime.tv_sec = ip->i_atime;
+ vap->va_atime.tv_nsec = ip->i_atimensec;
+ vap->va_mtime.tv_sec = ip->i_mtime;
+ vap->va_mtime.tv_nsec = ip->i_mtimensec;
+ vap->va_ctime.tv_sec = ip->i_ctime;
+ vap->va_ctime.tv_nsec = ip->i_ctimensec;
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
/* this doesn't belong here */
@@ -329,7 +334,7 @@ ufs_getattr(ap)
vap->va_blocksize = MAXBSIZE;
else
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
- vap->va_bytes = dbtob(ip->i_blocks);
+ vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
vap->va_type = vp->v_type;
vap->va_filerev = ip->i_modrev;
return (0);
@@ -376,7 +381,8 @@ ufs_setattr(ap)
return (EPERM);
ip->i_flags = vap->va_flags;
} else {
- if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND))
+ if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND) ||
+ (vap->va_flags & UF_SETTABLE) != vap->va_flags)
return (EPERM);
ip->i_flags &= SF_SETTABLE;
ip->i_flags |= (vap->va_flags & UF_SETTABLE);
@@ -393,8 +399,7 @@ ufs_setattr(ap)
if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
- error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p);
- if (error)
+ if (error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p))
return (error);
}
if (vap->va_size != VNOVAL) {
@@ -412,8 +417,7 @@ ufs_setattr(ap)
return (EROFS);
break;
}
- error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p);
- if (error)
+ if (error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p))
return (error);
}
ip = VTOI(vp);
@@ -711,6 +715,7 @@ ufs_link(ap)
struct vnode *vp = ap->a_vp;
struct vnode *tdvp = ap->a_tdvp;
struct componentname *cnp = ap->a_cnp;
+ struct proc *p = cnp->cn_proc;
struct inode *ip;
struct timeval tv;
int error;
@@ -719,12 +724,12 @@ ufs_link(ap)
if ((cnp->cn_flags & HASBUF) == 0)
panic("ufs_link: no name");
#endif
- if (vp->v_mount != tdvp->v_mount) {
+ if (tdvp->v_mount != vp->v_mount) {
VOP_ABORTOP(tdvp, cnp);
error = EXDEV;
goto out2;
}
- if (vp != tdvp && (error = VOP_LOCK(vp))) {
+ if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
VOP_ABORTOP(tdvp, cnp);
goto out2;
}
@@ -761,13 +766,69 @@ ufs_link(ap)
}
FREE(cnp->cn_pnbuf, M_NAMEI);
out1:
- if (vp != tdvp)
- VOP_UNLOCK(vp);
+ if (tdvp != vp)
+ VOP_UNLOCK(vp, 0, p);
out2:
vput(tdvp);
return (error);
}
+/*
+ * whiteout vnode call
+ */
+int
+ufs_whiteout(ap)
+ struct vop_whiteout_args /* {
+ struct vnode *a_dvp;
+ struct componentname *a_cnp;
+ int a_flags;
+ } */ *ap;
+{
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ struct direct newdir;
+ int error = 0;
+
+ switch (ap->a_flags) {
+ case LOOKUP:
+ /* 4.4 format directories support whiteout operations */
+ if (dvp->v_mount->mnt_maxsymlinklen > 0)
+ return (0);
+ return (EOPNOTSUPP);
+
+ case CREATE:
+ /* create a new directory whiteout */
+#ifdef DIAGNOSTIC
+ if ((cnp->cn_flags & SAVENAME) == 0)
+ panic("ufs_whiteout: missing name");
+ if (dvp->v_mount->mnt_maxsymlinklen <= 0)
+ panic("ufs_whiteout: old format filesystem");
+#endif
+
+ newdir.d_ino = WINO;
+ newdir.d_namlen = cnp->cn_namelen;
+ bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
+ newdir.d_type = DT_WHT;
+ error = ufs_direnter2(dvp, &newdir, cnp->cn_cred, cnp->cn_proc);
+ break;
+
+ case DELETE:
+ /* remove an existing directory whiteout */
+#ifdef DIAGNOSTIC
+ if (dvp->v_mount->mnt_maxsymlinklen <= 0)
+ panic("ufs_whiteout: old format filesystem");
+#endif
+
+ cnp->cn_flags &= ~DOWHITEOUT;
+ error = ufs_dirremove(dvp, cnp);
+ break;
+ }
+ if (cnp->cn_flags & HASBUF) {
+ FREE(cnp->cn_pnbuf, M_NAMEI);
+ cnp->cn_flags &= ~HASBUF;
+ }
+ return (error);
+}
/*
* Rename system call.
@@ -810,6 +871,7 @@ ufs_rename(ap)
struct vnode *fdvp = ap->a_fdvp;
struct componentname *tcnp = ap->a_tcnp;
struct componentname *fcnp = ap->a_fcnp;
+ struct proc *p = fcnp->cn_proc;
struct inode *ip, *xp, *dp;
struct dirtemplate dirbuf;
struct timeval tv;
@@ -899,13 +961,12 @@ abortit:
}
return (VOP_REMOVE(fdvp, fvp, fcnp));
}
- error = VOP_LOCK(fvp);
- if (error)
+ if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
goto abortit;
dp = VTOI(fdvp);
ip = VTOI(fvp);
if ((ip->i_flags & (IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) {
- VOP_UNLOCK(fvp);
+ VOP_UNLOCK(fvp, 0, p);
error = EPERM;
goto abortit;
}
@@ -916,7 +977,7 @@ abortit:
if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT ||
(ip->i_flag & IN_RENAME)) {
- VOP_UNLOCK(fvp);
+ VOP_UNLOCK(fvp, 0, p);
error = EINVAL;
goto abortit;
}
@@ -944,9 +1005,8 @@ abortit:
ip->i_nlink++;
ip->i_flag |= IN_CHANGE;
tv = time;
- error = VOP_UPDATE(fvp, &tv, &tv, 1);
- if (error) {
- VOP_UNLOCK(fvp);
+ if (error = VOP_UPDATE(fvp, &tv, &tv, 1)) {
+ VOP_UNLOCK(fvp, 0, p);
goto bad;
}
@@ -961,7 +1021,7 @@ abortit:
* call to checkpath().
*/
error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
- VOP_UNLOCK(fvp);
+ VOP_UNLOCK(fvp, 0, p);
if (oldparent != dp->i_number)
newparent = dp->i_number;
if (doingdirectory && newparent) {
@@ -1235,7 +1295,9 @@ bad:
vput(ITOV(xp));
vput(ITOV(dp));
out:
- if (VOP_LOCK(fvp) == 0) {
+ if (doingdirectory)
+ ip->i_flag &= ~IN_RENAME;
+ if (vn_lock(fvp, LK_EXCLUSIVE, p) == 0) {
ip->i_nlink--;
ip->i_flag |= IN_CHANGE;
ip->i_flag &= ~IN_RENAME;
@@ -1314,6 +1376,8 @@ ufs_mkdir(ap)
ip->i_mode = dmode;
tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
ip->i_nlink = 2;
+ if (cnp->cn_flags & ISWHITEOUT)
+ ip->i_flags |= UF_OPAQUE;
tv = time;
error = VOP_UPDATE(tvp, &tv, &tv, 1);
@@ -1545,13 +1609,15 @@ ufs_readdir(ap)
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
- int *a_ncookies;
- u_int **cookies;
+ int *a_eofflag;
+ int *ncookies;
+ u_long **a_cookies;
} */ *ap;
{
register struct uio *uio = ap->a_uio;
+ int error;
+ size_t count, lost;
off_t off;
- int count, lost, error;
if (ap->a_ncookies != NULL)
/*
@@ -1561,10 +1627,11 @@ ufs_readdir(ap)
uio->uio_offset &= ~(DIRBLKSIZ - 1);
off = uio->uio_offset;
count = uio->uio_resid;
- count &= ~(DIRBLKSIZ - 1);
- lost = uio->uio_resid - count;
- if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
+ /* Make sure we don't return partial entries. */
+ count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
+ if (count <= 0)
return (EINVAL);
+ lost = uio->uio_resid - count;
uio->uio_resid = count;
uio->uio_iov->iov_len = count;
# if (BYTE_ORDER == LITTLE_ENDIAN)
@@ -1614,8 +1681,8 @@ ufs_readdir(ap)
struct dirent* dpEnd;
struct dirent* dp;
int ncookies;
- u_int *cookies;
- u_int *cookiep;
+ u_long *cookies;
+ u_long *cookiep;
if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
panic("ufs_readdir: unexpected uio from NFS server");
@@ -1626,20 +1693,20 @@ ufs_readdir(ap)
dp < dpEnd;
dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
ncookies++;
- MALLOC(cookies, u_int *, ncookies * sizeof(u_int),
- M_TEMP, M_WAITOK);
+ MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
+ M_WAITOK);
for (dp = dpStart, cookiep = cookies;
dp < dpEnd;
dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
off += dp->d_reclen;
- *cookiep++ = (u_int) off;
+ *cookiep++ = (u_long) off;
}
*ap->a_ncookies = ncookies;
*ap->a_cookies = cookies;
}
+ uio->uio_resid += lost;
if (ap->a_eofflag)
*ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
- uio->uio_resid += lost;
return (error);
}
@@ -1691,95 +1758,31 @@ int
ufs_lock(ap)
struct vop_lock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- struct proc *p = curproc;
- register struct vnode *vp = ap->a_vp;
- register struct inode *ip;
-
-start:
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t)vp, PINOD, "ufslk1", 0);
- }
- if (vp->v_tag == VT_NON)
- return (ENOENT);
- ip = VTOI(vp);
- if (ip->i_flag & IN_LOCKED) {
- if (p->p_pid == ip->i_lockholder) {
- if( (ip->i_flag & IN_RECURSE) == 0)
- panic("ufs_lock: recursive lock not expected, pid: %d\n",
- ip->i_lockholder);
- } else {
- ip->i_flag |= IN_WANTED;
-#ifdef DIAGNOSTIC
- if (p)
- ip->i_lockwaiter = p->p_pid;
- else
- ip->i_lockwaiter = -1;
-#endif
- (void) tsleep((caddr_t)ip, PINOD, "ufslk2", 0);
- goto start;
- }
- }
-#ifdef DIAGNOSTIC
- ip->i_lockwaiter = 0;
- if (((ip->i_flag & IN_RECURSE) == 0) && (ip->i_lockholder != 0))
- panic("lockholder (%d) != 0", ip->i_lockholder);
- if (p && p->p_pid == 0)
- printf("locking by process 0\n");
-#endif
-
- if ((ip->i_flag & IN_RECURSE) == 0)
- ip->i_lockcount = 1;
- else
- ++ip->i_lockcount;
+ struct vnode *vp = ap->a_vp;
- if (p)
- ip->i_lockholder = p->p_pid;
- else
- ip->i_lockholder = -1;
- ip->i_flag |= IN_LOCKED;
- return (0);
+ return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
+ ap->a_p));
}
/*
- * Unlock an inode. If WANT bit is on, wakeup.
+ * Unlock an inode.
*/
-int lockcount = 90;
int
ufs_unlock(ap)
struct vop_unlock_args /* {
struct vnode *a_vp;
+ int a_flags;
+ struct proc *a_p;
} */ *ap;
{
- register struct inode *ip = VTOI(ap->a_vp);
-
-#ifdef DIAGNOSTIC
- struct proc *p = curproc;
+ struct vnode *vp = ap->a_vp;
- if ((ip->i_flag & IN_LOCKED) == 0) {
- vprint("ufs_unlock: unlocked inode", ap->a_vp);
- panic("ufs_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);
-#endif
- if (--ip->i_lockcount > 0) {
- if ((ip->i_flag & IN_RECURSE) == 0)
- panic("ufs_unlock: recursive lock prematurely released, pid=%d\n",
- ip->i_lockholder);
- return (0);
- }
- ip->i_lockholder = 0;
- ip->i_flag &= ~(IN_LOCKED|IN_RECURSE);
- 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, ap->a_p));
}
/*
@@ -1792,9 +1795,7 @@ ufs_islocked(ap)
} */ *ap;
{
- if (VTOI(ap->a_vp)->i_flag & IN_LOCKED)
- return (1);
- return (0);
+ return (lockstatus(&VTOI(ap->a_vp)->i_lock));
}
/*
@@ -1850,14 +1851,11 @@ ufs_print(ap)
printf("tag VT_UFS, ino %ld, on dev %d, %d", ip->i_number,
major(ip->i_dev), minor(ip->i_dev));
+#ifdef FIFO
if (vp->v_type == VFIFO)
fifo_printinfo(vp);
- printf("%s\n", (ip->i_flag & IN_LOCKED) ? " (LOCKED)" : "");
- if (ip->i_lockholder == 0)
- return (0);
- printf("\towner pid %lu", (u_long)ip->i_lockholder);
- if (ip->i_lockwaiter)
- printf(" waiting pid %lu", (u_long)ip->i_lockwaiter);
+#endif /* FIFO */
+ lockmgr_printinfo(&ip->i_lock);
printf("\n");
return (0);
}
@@ -1916,10 +1914,13 @@ ufsspec_close(ap)
struct proc *a_p;
} */ *ap;
{
- register struct inode *ip = VTOI(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
- if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
+ simple_lock(&vp->v_interlock);
+ if (ap->a_vp->v_usecount > 1)
ITIMES(ip, &time, &time);
+ simple_unlock(&vp->v_interlock);
return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
}
@@ -1975,10 +1976,13 @@ ufsfifo_close(ap)
struct proc *a_p;
} */ *ap;
{
- register struct inode *ip = VTOI(ap->a_vp);
+ struct vnode *vp = ap->a_vp;
+ struct inode *ip = VTOI(vp);
- if (ap->a_vp->v_usecount > 1 && !(ip->i_flag & IN_LOCKED))
+ simple_lock(&vp->v_interlock);
+ if (ap->a_vp->v_usecount > 1)
ITIMES(ip, &time, &time);
+ simple_unlock(&vp->v_interlock);
return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
}
@@ -2061,9 +2065,9 @@ ufs_vinit(mntp, specops, fifoops, vpp)
if (nvp) {
/*
* Discard unneeded vnode, but save its inode.
+ * Note that the lock is carried over in the inode
+ * to the replacement vnode.
*/
- ufs_ihashrem(ip);
- VOP_UNLOCK(vp);
nvp->v_data = vp->v_data;
vp->v_data = NULL;
vp->v_op = spec_vnodeop_p;
@@ -2074,7 +2078,6 @@ ufs_vinit(mntp, specops, fifoops, vpp)
*/
vp = nvp;
ip->i_vnode = vp;
- ufs_ihashins(ip);
}
break;
case VFIFO:
@@ -2149,6 +2152,9 @@ ufs_makeinode(mode, dvp, vpp, cnp)
suser(cnp->cn_cred, NULL))
ip->i_mode &= ~ISGID;
+ if (cnp->cn_flags & ISWHITEOUT)
+ ip->i_flags |= UF_OPAQUE;
+
/*
* Make sure inode goes to disk before directory entry.
*/
diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h
index d7b7b28..87041a6 100644
--- a/sys/ufs/ufs/ufsmount.h
+++ b/sys/ufs/ufs/ufsmount.h
@@ -30,13 +30,34 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)ufsmount.h 8.2 (Berkeley) 1/12/94
+ * @(#)ufsmount.h 8.6 (Berkeley) 3/30/95
* $FreeBSD$
*/
#ifndef _UFS_UFS_UFSMOUNT_H_
#define _UFS_UFS_UFSMOUNT_H_
+/*
+ * Arguments to mount UFS-based filesystems
+ */
+struct ufs_args {
+ char *fspec; /* block special device to mount */
+ struct export_args export; /* network export information */
+};
+
+#ifdef MFS
+/*
+ * Arguments to mount MFS
+ */
+struct mfs_args {
+ char *fspec; /* name to export for statfs */
+ struct export_args export; /* if exported MFSes are supported */
+ caddr_t base; /* base of file system in memory */
+ u_long size; /* size of file system */
+};
+#endif /* MFS */
+
+#ifdef KERNEL
struct buf;
struct inode;
struct nameidata;
@@ -51,6 +72,7 @@ struct ufsmount {
struct mount *um_mountp; /* filesystem vfs structure */
dev_t um_dev; /* device mounted */
struct vnode *um_devvp; /* block device mounted vnode */
+
union { /* pointer to superblock */
struct lfs *lfs; /* LFS */
struct fs *fs; /* FFS */
@@ -60,6 +82,7 @@ struct ufsmount {
#define um_lfs ufsmount_u.lfs
#define um_e2fs ufsmount_u.e2fs
#define um_e2fsb ufsmount_u.e2fs->s_es
+
struct vnode *um_quotas[MAXQUOTAS]; /* pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* quota file access cred */
u_long um_nindir; /* indirect ptrs per block */
@@ -69,7 +92,9 @@ struct ufsmount {
time_t um_itime[MAXQUOTAS]; /* inode quota time limit */
char um_qflags[MAXQUOTAS]; /* quota specific flags */
struct netexport um_export; /* export information */
+ int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */
};
+
/*
* Flags describing the state of quotas.
*/
@@ -83,8 +108,9 @@ struct ufsmount {
* Macros to access file system parameters in the ufsmount structure.
* Used by ufs_bmap.
*/
-#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
-#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
-#define MNINDIR(ump) ((ump)->um_nindir)
+#define MNINDIR(ump) ((ump)->um_nindir)
+#define blkptrtodb(ump, b) ((b) << (ump)->um_bptrtodb)
+#define is_sequential(ump, a, b) ((b) == (a) + ump->um_seqinc)
+#endif /* KERNEL */
#endif
diff --git a/sys/vm/vm.h b/sys/vm/vm.h
index 1fd2745..a87c435 100644
--- a/sys/vm/vm.h
+++ b/sys/vm/vm.h
@@ -70,4 +70,15 @@ struct vm_page;
typedef struct vm_page *vm_page_t;
#endif
+/*
+ * MACH VM locking type mappings to kernel types
+ */
+#include <sys/lock.h>
+typedef struct simplelock simple_lock_data_t;
+typedef struct simplelock *simple_lock_t;
+#if 0
+typedef struct lock lock_data_t;
+typedef struct lock *lock_t;
+#endif
+
#endif /* VM_H */
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
index fa734de..e9ecd30 100644
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -91,7 +91,7 @@ struct vmspace *vmspace_fork __P((struct vmspace *));
void vmspace_free __P((struct vmspace *));
void vnode_pager_setsize __P((struct vnode *, vm_ooffset_t));
void vnode_pager_umount __P((struct mount *));
-void vnode_pager_uncache __P((struct vnode *));
+void vnode_pager_uncache __P((struct vnode *, struct proc *));
void vslock __P((caddr_t, u_int));
void vsunlock __P((caddr_t, u_int, int));
void vm_object_print __P((/* db_expr_t */ int, boolean_t, /* db_expr_t */ int,
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 74fb29a..236e255 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -86,7 +86,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
@@ -146,6 +146,7 @@ vm_fault(map, vaddr, fault_type, change_wiring)
vm_page_t marray[VM_FAULT_READ];
int hardfault = 0;
struct vnode *vp = NULL;
+ struct proc *p = curproc; /* XXX */
cnt.v_vm_faults++; /* needs lock XXX */
/*
@@ -175,7 +176,7 @@ vm_fault(map, vaddr, fault_type, change_wiring)
vm_object_pip_wakeup(first_object); \
} \
UNLOCK_MAP; \
- if (vp != NULL) VOP_UNLOCK(vp); \
+ if (vp != NULL) VOP_UNLOCK(vp, 0, p); \
}
#define UNLOCK_AND_DEALLOCATE { \
diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c
index 25290e6..84197ea 100644
--- a/sys/vm/vm_glue.c
+++ b/sys/vm/vm_glue.c
@@ -79,7 +79,7 @@
#include <vm/vm_param.h>
#include <vm/vm_inherit.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_page.h>
@@ -424,9 +424,11 @@ retry:
vm_map_reference(&vm->vm_map);
/*
* do not swapout a process that is waiting for VM
- * datastructures there is a possible deadlock.
+ * data structures there is a possible deadlock.
*/
- if (!lock_try_write(&vm->vm_map.lock)) {
+ if (lockmgr(&vm->vm_map.lock,
+ LK_EXCLUSIVE | LK_NOWAIT,
+ (void *)0, curproc)) {
vm_map_deallocate(&vm->vm_map);
vmspace_free(vm);
continue;
diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c
index de14867..1d9b1f9 100644
--- a/sys/vm/vm_init.c
+++ b/sys/vm/vm_init.c
@@ -76,7 +76,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 5d8c00d..51d71b4 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -80,7 +80,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index bc3bea9..53fd164 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -80,7 +80,7 @@
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
#include <vm/vm_inherit.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_page.h>
@@ -283,9 +283,9 @@ vm_map_create(pmap, min, max, pageable)
if (kmem_map == NULL) {
result = kmap_free;
- kmap_free = (vm_map_t) result->header.next;
if (result == NULL)
panic("vm_map_create: out of maps");
+ kmap_free = (vm_map_t) result->header.next;
} else
MALLOC(result, vm_map_t, sizeof(struct vm_map),
M_VMMAP, M_WAITOK);
@@ -317,7 +317,8 @@ vm_map_init(map, min, max, pageable)
map->first_free = &map->header;
map->hint = &map->header;
map->timestamp = 0;
- lock_init(&map->lock, TRUE);
+ lockinit(&map->lock, PVM, "thrd_sleep", 0, 0);
+ simple_lock_init(&map->ref_lock);
}
/*
@@ -486,7 +487,7 @@ vm_map_deallocate(map)
* Lock the map, to wait out all other references to it.
*/
- vm_map_lock(map);
+ vm_map_lock_drain_interlock(map);
(void) vm_map_delete(map, map->min_offset, map->max_offset);
--map->ref_count;
if( map->ref_count != 0) {
@@ -495,6 +496,9 @@ vm_map_deallocate(map)
}
pmap_destroy(map->pmap);
+
+ vm_map_unlock(map);
+
FREE(map, M_VMMAP);
}
@@ -1367,7 +1371,7 @@ vm_map_user_pageable(map, start, end, new_pageable)
* becomes completely unwired, unwire its physical pages and
* mappings.
*/
- lock_set_recursive(&map->lock);
+ vm_map_set_recursive(map);
entry = start_entry;
while ((entry != &map->header) && (entry->start < end)) {
@@ -1381,7 +1385,7 @@ vm_map_user_pageable(map, start, end, new_pageable)
entry = entry->next;
}
vm_map_simplify_entry(map, start_entry);
- lock_clear_recursive(&map->lock);
+ vm_map_clear_recursive(map);
} else {
/*
@@ -1438,25 +1442,35 @@ vm_map_user_pageable(map, start, end, new_pageable)
entry->eflags |= MAP_ENTRY_USER_WIRED;
/* First we need to allow map modifications */
- lock_set_recursive(&map->lock);
- lock_write_to_read(&map->lock);
+ vm_map_set_recursive(map);
+ if (lockmgr(&map->lock, LK_EXCLUPGRADE,
+ (void *)0, curproc)) {
+ entry->wired_count--;
+ entry->eflags &= ~MAP_ENTRY_USER_WIRED;
+ vm_map_clear_recursive(map);
+ vm_map_unlock(map);
+
+ (void) vm_map_user_pageable(map, start, entry->start, TRUE);
+ return rv;
+ }
+
+
rv = vm_fault_user_wire(map, entry->start, entry->end);
if (rv) {
entry->wired_count--;
entry->eflags &= ~MAP_ENTRY_USER_WIRED;
- lock_clear_recursive(&map->lock);
+ vm_map_clear_recursive(map);
vm_map_unlock(map);
(void) vm_map_user_pageable(map, start, entry->start, TRUE);
return rv;
}
- lock_clear_recursive(&map->lock);
- vm_map_unlock(map);
- vm_map_lock(map);
+ vm_map_clear_recursive(map);
+ lockmgr(&map->lock, LK_DOWNGRADE, (void *)0, curproc);
goto rescan;
}
@@ -1536,7 +1550,7 @@ vm_map_pageable(map, start, end, new_pageable)
* becomes completely unwired, unwire its physical pages and
* mappings.
*/
- lock_set_recursive(&map->lock);
+ vm_map_set_recursive(map);
entry = start_entry;
while ((entry != &map->header) && (entry->start < end)) {
@@ -1549,7 +1563,7 @@ vm_map_pageable(map, start, end, new_pageable)
entry = entry->next;
}
vm_map_simplify_entry(map, start_entry);
- lock_clear_recursive(&map->lock);
+ vm_map_clear_recursive(map);
} else {
/*
* Wiring. We must do this in two passes:
@@ -1655,8 +1669,8 @@ vm_map_pageable(map, start, end, new_pageable)
if (vm_map_pmap(map) == kernel_pmap) {
vm_map_unlock(map); /* trust me ... */
} else {
- lock_set_recursive(&map->lock);
- lock_write_to_read(&map->lock);
+ vm_map_set_recursive(map);
+ lockmgr(&map->lock, LK_DOWNGRADE, (void*)0, curproc);
}
rv = 0;
@@ -1686,7 +1700,7 @@ vm_map_pageable(map, start, end, new_pageable)
if (vm_map_pmap(map) == kernel_pmap) {
vm_map_lock(map);
} else {
- lock_clear_recursive(&map->lock);
+ vm_map_clear_recursive(map);
}
if (rv) {
vm_map_unlock(map);
@@ -2379,7 +2393,8 @@ RetryLookup:;
* object.
*/
- if (lock_read_to_write(&share_map->lock)) {
+ if (lockmgr(&share_map->lock, LK_EXCLUPGRADE,
+ (void *)0, curproc)) {
if (share_map != map)
vm_map_unlock_read(map);
goto RetryLookup;
@@ -2391,7 +2406,8 @@ RetryLookup:;
entry->eflags &= ~MAP_ENTRY_NEEDS_COPY;
- lock_write_to_read(&share_map->lock);
+ lockmgr(&share_map->lock, LK_DOWNGRADE,
+ (void *)0, curproc);
} else {
/*
* We're attempting to read a copy-on-write page --
@@ -2406,7 +2422,8 @@ RetryLookup:;
*/
if (entry->object.vm_object == NULL) {
- if (lock_read_to_write(&share_map->lock)) {
+ if (lockmgr(&share_map->lock, LK_EXCLUPGRADE,
+ (void *)0, curproc)) {
if (share_map != map)
vm_map_unlock_read(map);
goto RetryLookup;
@@ -2414,7 +2431,7 @@ RetryLookup:;
entry->object.vm_object = vm_object_allocate(OBJT_DEFAULT,
OFF_TO_IDX(entry->end - entry->start));
entry->offset = 0;
- lock_write_to_read(&share_map->lock);
+ lockmgr(&share_map->lock, LK_DOWNGRADE, (void *)0, curproc);
}
if (entry->object.vm_object != NULL)
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index 8f46b8d..1c55c57 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * from: @(#)vm_map.h 8.3 (Berkeley) 3/15/94
+ * @(#)vm_map.h 8.9 (Berkeley) 5/17/95
*
*
* Copyright (c) 1987, 1990 Carnegie-Mellon University.
@@ -105,14 +105,6 @@ struct vm_map_entry {
union vm_map_object object; /* object I point to */
vm_ooffset_t offset; /* offset into object */
u_char eflags; /* map entry flags */
-#if 0
- u_char is_a_map:1, /* Is "object" a map? */
- is_sub_map:1, /* Is "object" a submap? */
- copy_on_write:1, /* is data copy-on-write */
- needs_copy:1, /* does object need to be copied */
- nofault:1, /* should never fault */
- user_wired:1; /* wired by user */
-#endif
/* Only in task maps: */
vm_prot_t protection; /* protection code */
vm_prot_t max_protection; /* maximum protection */
@@ -135,12 +127,13 @@ struct vm_map_entry {
*/
struct vm_map {
struct pmap *pmap; /* Physical map */
- lock_data_t lock; /* Lock for map data */
+ struct lock lock; /* Lock for map data */
struct vm_map_entry header; /* List of entries */
int nentries; /* Number of entries */
vm_size_t size; /* virtual size */
boolean_t is_main_map; /* Am I a main map? */
int ref_count; /* Reference count */
+ simple_lock_data_t ref_lock; /* Lock for ref_count field */
vm_map_entry_t hint; /* hint for quick lookups */
vm_map_entry_t first_free; /* First free space hint */
boolean_t entries_pageable; /* map entries pageable?? */
@@ -195,14 +188,42 @@ typedef struct {
* Perform locking on the data portion of a map.
*/
+#include <sys/proc.h> /* XXX for curproc and p_pid */
+
+#define vm_map_lock_drain_interlock(map) { \
+ lockmgr(&(map)->lock, LK_DRAIN|LK_INTERLOCK, \
+ &(map)->ref_lock, curproc); \
+ (map)->timestamp++; \
+}
+#ifdef DIAGNOSTIC
#define vm_map_lock(map) { \
- lock_write(&(map)->lock); \
+ if (lockmgr(&(map)->lock, LK_EXCLUSIVE, (void *)0, curproc) != 0) { \
+ panic("vm_map_lock: failed to get lock"); \
+ } \
(map)->timestamp++; \
}
-#define vm_map_unlock(map) lock_write_done(&(map)->lock)
-#define vm_map_lock_read(map) lock_read(&(map)->lock)
-#define vm_map_unlock_read(map) lock_read_done(&(map)->lock)
-
+#else
+#define vm_map_lock(map) { \
+ lockmgr(&(map)->lock, LK_EXCLUSIVE, (void *)0, curproc); \
+ (map)->timestamp++; \
+}
+#endif /* DIAGNOSTIC */
+#define vm_map_unlock(map) \
+ lockmgr(&(map)->lock, LK_RELEASE, (void *)0, curproc)
+#define vm_map_lock_read(map) \
+ lockmgr(&(map)->lock, LK_SHARED, (void *)0, curproc)
+#define vm_map_unlock_read(map) \
+ lockmgr(&(map)->lock, LK_RELEASE, (void *)0, curproc)
+#define vm_map_set_recursive(map) { \
+ simple_lock(&(map)->lock.lk_interlock); \
+ (map)->lock.lk_flags |= LK_CANRECURSE; \
+ simple_unlock(&(map)->lock.lk_interlock); \
+}
+#define vm_map_clear_recursive(map) { \
+ simple_lock(&(map)->lock.lk_interlock); \
+ (map)->lock.lk_flags &= ~LK_CANRECURSE; \
+ simple_unlock(&(map)->lock.lk_interlock); \
+}
/*
* Functions implemented as macros
*/
diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c
index f36e138..c511ae7 100644
--- a/sys/vm/vm_meter.c
+++ b/sys/vm/vm_meter.c
@@ -45,7 +45,7 @@
#include <vm/vm_extern.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index f751e14..d86feb2 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -65,7 +65,7 @@
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
#include <vm/vm_inherit.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index ebd29f1..e429711 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -81,7 +81,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
@@ -130,6 +130,7 @@ int vm_object_cache_max;
struct object_q vm_object_cached_list;
static int vm_object_cached;
struct object_q vm_object_list;
+struct simplelock vm_object_list_lock;
static long vm_object_count;
vm_object_t kernel_object;
vm_object_t kmem_object;
@@ -182,6 +183,7 @@ vm_object_init()
{
TAILQ_INIT(&vm_object_cached_list);
TAILQ_INIT(&vm_object_list);
+ simple_lock_init(&vm_object_list_lock);
vm_object_count = 0;
vm_object_cache_max = 84;
@@ -388,16 +390,18 @@ vm_object_terminate(object)
*/
if (object->type == OBJT_VNODE) {
struct vnode *vp = object->handle;
+ struct proc *p = curproc; /* XXX */
int waslocked;
waslocked = VOP_ISLOCKED(vp);
if (!waslocked)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
vm_object_page_clean(object, 0, 0, TRUE, FALSE);
vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
if (!waslocked)
- VOP_UNLOCK(vp);
- }
+ VOP_UNLOCK(vp, 0, p);
+ }
+
/*
* Now free the pages. For internal objects, this also removes them
* from paging queues.
@@ -415,8 +419,10 @@ vm_object_terminate(object)
*/
vm_pager_deallocate(object);
+ simple_lock(&vm_object_list_lock);
TAILQ_REMOVE(&vm_object_list, object, object_list);
vm_object_count--;
+ simple_unlock(&vm_object_list_lock);
wakeup(object);
@@ -458,6 +464,7 @@ vm_object_page_clean(object, start, end, syncio, lockflag)
vm_page_t maf[vm_pageout_page_count];
vm_page_t mab[vm_pageout_page_count];
vm_page_t ma[vm_pageout_page_count];
+ struct proc *pproc = curproc; /* XXX */
if (object->type != OBJT_VNODE ||
(object->flags & OBJ_MIGHTBEDIRTY) == 0)
@@ -466,7 +473,7 @@ vm_object_page_clean(object, start, end, syncio, lockflag)
vp = object->handle;
if (lockflag)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, pproc);
object->flags |= OBJ_CLEANING;
tstart = start;
@@ -584,7 +591,7 @@ rescan:
VOP_FSYNC(vp, NULL, syncio, curproc);
if (lockflag)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, pproc);
object->flags &= ~OBJ_CLEANING;
return;
}
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index d106301..41cf3a3 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -77,7 +77,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 2054471..d1f2537 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -87,7 +87,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
@@ -505,7 +505,7 @@ vm_pageout_map_deactivate_pages(map, desired)
vm_object_t obj, bigobj;
vm_map_reference(map);
- if (!lock_try_write(&map->lock)) {
+ if (lockmgr(&map->lock, LK_EXCLUSIVE | LK_NOWAIT, (void *)0, curproc)) {
vm_map_deallocate(map);
return;
}
@@ -669,7 +669,9 @@ rescan0:
if (object->type == OBJT_VNODE) {
vp = object->handle;
- if (VOP_ISLOCKED(vp) || vget(vp, 1)) {
+ if (VOP_ISLOCKED(vp) ||
+ vget(vp, LK_EXCLUSIVE | LK_INTERLOCK,
+ curproc)) {
if ((m->queue == PQ_INACTIVE) &&
(m->hold_count == 0) &&
(m->busy == 0) &&
diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c
index 4a69ee7..2d2372e 100644
--- a/sys/vm/vm_unix.c
+++ b/sys/vm/vm_unix.c
@@ -52,7 +52,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <vm/lock.h>
+#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/swap_pager.h>
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index bf6a1c9..12e2f8c 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -329,6 +329,7 @@ void
vnode_pager_umount(mp)
register struct mount *mp;
{
+ struct proc *p = curproc; /* XXX */
struct vnode *vp, *nvp;
loop:
@@ -347,9 +348,9 @@ loop:
nvp = vp->v_mntvnodes.le_next;
if (vp->v_object != NULL) {
- VOP_LOCK(vp);
- vnode_pager_uncache(vp);
- VOP_UNLOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ vnode_pager_uncache(vp, p);
+ VOP_UNLOCK(vp, 0, p);
}
}
}
@@ -364,8 +365,9 @@ loop:
* re-locking the vnode.
*/
void
-vnode_pager_uncache(vp)
+vnode_pager_uncache(vp, p)
struct vnode *vp;
+ struct proc *p;
{
vm_object_t object;
@@ -383,10 +385,10 @@ vnode_pager_uncache(vp)
* VBLK devices...
*/
if (vp->v_type != VBLK)
- VOP_UNLOCK(vp);
+ VOP_UNLOCK(vp, 0, p);
pager_cache(object, FALSE);
if (vp->v_type != VBLK)
- VOP_LOCK(vp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
return;
}
@@ -968,11 +970,13 @@ struct vnode *
vnode_pager_lock(object)
vm_object_t object;
{
+ struct proc *p = curproc; /* XXX */
+
for (; object != NULL; object = object->backing_object) {
if (object->type != OBJT_VNODE)
continue;
- VOP_LOCK(object->handle);
+ vn_lock(object->handle, LK_EXCLUSIVE | LK_RETRY, p);
return object->handle;
}
return NULL;
OpenPOWER on IntegriCloud