summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/mtree/BSD.include.dist14
-rw-r--r--include/Makefile6
-rw-r--r--sbin/mount_null/Makefile2
-rw-r--r--sbin/mount_null/mount_null.c2
-rw-r--r--sbin/mount_nullfs/Makefile2
-rw-r--r--sbin/mount_nullfs/mount_nullfs.c2
-rw-r--r--sbin/mount_portal/Makefile2
-rw-r--r--sbin/mount_portal/portald.h2
-rw-r--r--sbin/mount_portalfs/Makefile2
-rw-r--r--sbin/mount_portalfs/portald.h2
-rw-r--r--sbin/mount_umap/Makefile2
-rw-r--r--sbin/mount_umap/mount_umap.c2
-rw-r--r--sbin/mount_umapfs/Makefile2
-rw-r--r--sbin/mount_umapfs/mount_umapfs.c2
-rw-r--r--sbin/mount_union/Makefile2
-rw-r--r--sbin/mount_union/mount_union.c2
-rw-r--r--sbin/mount_unionfs/Makefile2
-rw-r--r--sbin/mount_unionfs/mount_unionfs.c2
-rw-r--r--sys/alpha/alpha/machdep.c2
-rw-r--r--sys/alpha/alpha/procfs_machdep.c2
-rw-r--r--sys/alpha/osf1/osf1_signal.c2
-rw-r--r--sys/conf/NOTES6
-rw-r--r--sys/conf/files70
-rw-r--r--sys/conf/options6
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c2
-rw-r--r--sys/fs/fdescfs/fdesc_vfsops.c2
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c2
-rw-r--r--sys/fs/fifofs/fifo_vnops.c2
-rw-r--r--sys/fs/nullfs/null_subr.c2
-rw-r--r--sys/fs/nullfs/null_vfsops.c2
-rw-r--r--sys/fs/nullfs/null_vnops.c2
-rw-r--r--sys/fs/portalfs/portal_vfsops.c2
-rw-r--r--sys/fs/portalfs/portal_vnops.c2
-rw-r--r--sys/fs/procfs/procfs_ctl.c2
-rw-r--r--sys/fs/procfs/procfs_dbregs.c2
-rw-r--r--sys/fs/procfs/procfs_fpregs.c2
-rw-r--r--sys/fs/procfs/procfs_map.c2
-rw-r--r--sys/fs/procfs/procfs_mem.c2
-rw-r--r--sys/fs/procfs/procfs_note.c2
-rw-r--r--sys/fs/procfs/procfs_regs.c2
-rw-r--r--sys/fs/procfs/procfs_rlimit.c2
-rw-r--r--sys/fs/procfs/procfs_status.c2
-rw-r--r--sys/fs/procfs/procfs_subr.c2
-rw-r--r--sys/fs/procfs/procfs_type.c2
-rw-r--r--sys/fs/procfs/procfs_vfsops.c2
-rw-r--r--sys/fs/procfs/procfs_vnops.c2
-rw-r--r--sys/fs/umapfs/umap_subr.c2
-rw-r--r--sys/fs/umapfs/umap_vfsops.c2
-rw-r--r--sys/fs/umapfs/umap_vnops.c4
-rw-r--r--sys/fs/unionfs/union_subr.c2
-rw-r--r--sys/fs/unionfs/union_vfsops.c2
-rw-r--r--sys/fs/unionfs/union_vnops.c2
-rw-r--r--sys/i386/conf/NOTES6
-rw-r--r--sys/i386/i386/procfs_machdep.c2
-rw-r--r--sys/ia64/ia64/machdep.c2
-rw-r--r--sys/ia64/ia64/procfs_machdep.c2
-rw-r--r--sys/isofs/cd9660/cd9660_vnops.c2
-rw-r--r--sys/kern/Make.tags.inc38
-rw-r--r--sys/kern/Makefile6
-rw-r--r--sys/kern/sys_process.c2
-rw-r--r--sys/kern/vfs_extattr.c1
-rw-r--r--sys/kern/vfs_syscalls.c1
-rw-r--r--sys/miscfs/deadfs/dead_vnops.c295
-rw-r--r--sys/miscfs/fdesc/fdesc.h69
-rw-r--r--sys/miscfs/fdesc/fdesc_vfsops.c226
-rw-r--r--sys/miscfs/fdesc/fdesc_vnops.c576
-rw-r--r--sys/miscfs/fifofs/fifo.h44
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c587
-rw-r--r--sys/miscfs/nullfs/null.h89
-rw-r--r--sys/miscfs/nullfs/null_subr.c345
-rw-r--r--sys/miscfs/nullfs/null_vfsops.c425
-rw-r--r--sys/miscfs/nullfs/null_vnops.c852
-rw-r--r--sys/miscfs/portal/portal.h71
-rw-r--r--sys/miscfs/portal/portal_vfsops.c257
-rw-r--r--sys/miscfs/portal/portal_vnops.c591
-rw-r--r--sys/miscfs/procfs/README113
-rw-r--r--sys/miscfs/procfs/procfs.h162
-rw-r--r--sys/miscfs/procfs/procfs_ctl.c364
-rw-r--r--sys/miscfs/procfs/procfs_dbregs.c107
-rw-r--r--sys/miscfs/procfs/procfs_fpregs.c104
-rw-r--r--sys/miscfs/procfs/procfs_map.c186
-rw-r--r--sys/miscfs/procfs/procfs_mem.c328
-rw-r--r--sys/miscfs/procfs/procfs_note.c67
-rw-r--r--sys/miscfs/procfs/procfs_regs.c105
-rw-r--r--sys/miscfs/procfs/procfs_rlimit.c128
-rw-r--r--sys/miscfs/procfs/procfs_status.c265
-rw-r--r--sys/miscfs/procfs/procfs_subr.c416
-rw-r--r--sys/miscfs/procfs/procfs_type.c85
-rw-r--r--sys/miscfs/procfs/procfs_vfsops.c177
-rw-r--r--sys/miscfs/procfs/procfs_vnops.c1022
-rw-r--r--sys/miscfs/specfs/spec_vnops.c838
-rw-r--r--sys/miscfs/umapfs/umap.h91
-rw-r--r--sys/miscfs/umapfs/umap_subr.c405
-rw-r--r--sys/miscfs/umapfs/umap_vfsops.c454
-rw-r--r--sys/miscfs/umapfs/umap_vnops.c519
-rw-r--r--sys/miscfs/union/union.h154
-rw-r--r--sys/miscfs/union/union_subr.c1360
-rw-r--r--sys/miscfs/union/union_vfsops.c485
-rw-r--r--sys/miscfs/union/union_vnops.c1966
-rw-r--r--sys/modules/Makefile6
-rw-r--r--sys/modules/fdesc/Makefile10
-rw-r--r--sys/modules/fdescfs/Makefile4
-rw-r--r--sys/modules/nullfs/Makefile2
-rw-r--r--sys/modules/portal/Makefile10
-rw-r--r--sys/modules/portalfs/Makefile4
-rw-r--r--sys/modules/procfs/Makefile2
-rw-r--r--sys/modules/umapfs/Makefile2
-rw-r--r--sys/modules/union/Makefile10
-rw-r--r--sys/modules/unionfs/Makefile4
-rw-r--r--sys/nfs/nfs_vnops.c2
-rw-r--r--sys/nfsclient/nfs_vnops.c2
-rw-r--r--sys/powerpc/powerpc/procfs_machdep.c2
-rw-r--r--sys/ufs/ufs/ufs_vnops.c2
-rw-r--r--usr.sbin/mount_portalfs/Makefile2
-rw-r--r--usr.sbin/mount_portalfs/portald.h2
-rw-r--r--usr.sbin/pstat/Makefile1
-rw-r--r--usr.sbin/pstat/pstat.c2
117 files changed, 156 insertions, 14501 deletions
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index 2f6eeea..05a2ed1 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -20,8 +20,22 @@
..
..
fs
+ fdescfs
+ ..
+ fifofs
+ ..
+ nullfs
+ ..
+ portalfs
+ ..
+ procfs
+ ..
smbfs
..
+ umapfs
+ ..
+ unionfs
+ ..
..
g++
std
diff --git a/include/Makefile b/include/Makefile
index 0bf4116..bdeef56 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -44,8 +44,10 @@ LDIRS= cam msdosfs net netatalk netatm netgraph netinet netinet6 \
sys vm
LNOHEADERDIRS= fs isofs ufs dev
-LSUBDIRS= fs/smbfs isofs/cd9660 ufs/ffs ufs/mfs ufs/ufs \
- cam/scsi dev/ppbus dev/usb dev/wi
+
+LSUBDIRS= cam/scsi dev/ppbus dev/usb dev/wi \
+ fs/fdesc fs/fifofs fs/nullfs fs/portal fs/procfs fs/smbfs \
+ fs/umapfs fs/union isofs/cd9660 ufs/ffs ufs/mfs ufs/ufs
# Define SHARED to indicate whether you want symbolic links to the system
# source (``symlinks''), or a separate copy (``copies''). ``symlinks'' is
diff --git a/sbin/mount_null/Makefile b/sbin/mount_null/Makefile
index 68b488d..3c50252 100644
--- a/sbin/mount_null/Makefile
+++ b/sbin/mount_null/Makefile
@@ -6,7 +6,7 @@ SRCS= mount_null.c getmntopts.c
MAN= mount_null.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_null/mount_null.c b/sbin/mount_null/mount_null.c
index d38e7e3..8e6b8f0 100644
--- a/sbin/mount_null/mount_null.c
+++ b/sbin/mount_null/mount_null.c
@@ -50,7 +50,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
-#include <miscfs/nullfs/null.h>
+#include <fs/nullfs/null.h>
#include <err.h>
#include <stdio.h>
diff --git a/sbin/mount_nullfs/Makefile b/sbin/mount_nullfs/Makefile
index 68b488d..3c50252 100644
--- a/sbin/mount_nullfs/Makefile
+++ b/sbin/mount_nullfs/Makefile
@@ -6,7 +6,7 @@ SRCS= mount_null.c getmntopts.c
MAN= mount_null.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_nullfs/mount_nullfs.c b/sbin/mount_nullfs/mount_nullfs.c
index d38e7e3..8e6b8f0 100644
--- a/sbin/mount_nullfs/mount_nullfs.c
+++ b/sbin/mount_nullfs/mount_nullfs.c
@@ -50,7 +50,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
-#include <miscfs/nullfs/null.h>
+#include <fs/nullfs/null.h>
#include <err.h>
#include <stdio.h>
diff --git a/sbin/mount_portal/Makefile b/sbin/mount_portal/Makefile
index 00b96dc..fc332ee 100644
--- a/sbin/mount_portal/Makefile
+++ b/sbin/mount_portal/Makefile
@@ -7,7 +7,7 @@ SRCS= mount_portal.c activate.c conf.c getmntopts.c pt_conf.c \
MAN= mount_portal.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_portal/portald.h b/sbin/mount_portal/portald.h
index 4131834..5837bd7 100644
--- a/sbin/mount_portal/portald.h
+++ b/sbin/mount_portal/portald.h
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-#include <miscfs/portal/portal.h>
+#include <fs/portalfs/portal.h>
/*
* Meta-chars in an RE. Paths in the config file containing
diff --git a/sbin/mount_portalfs/Makefile b/sbin/mount_portalfs/Makefile
index 00b96dc..fc332ee 100644
--- a/sbin/mount_portalfs/Makefile
+++ b/sbin/mount_portalfs/Makefile
@@ -7,7 +7,7 @@ SRCS= mount_portal.c activate.c conf.c getmntopts.c pt_conf.c \
MAN= mount_portal.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_portalfs/portald.h b/sbin/mount_portalfs/portald.h
index 4131834..5837bd7 100644
--- a/sbin/mount_portalfs/portald.h
+++ b/sbin/mount_portalfs/portald.h
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-#include <miscfs/portal/portal.h>
+#include <fs/portalfs/portal.h>
/*
* Meta-chars in an RE. Paths in the config file containing
diff --git a/sbin/mount_umap/Makefile b/sbin/mount_umap/Makefile
index 9ae6798..7dc1fc6b 100644
--- a/sbin/mount_umap/Makefile
+++ b/sbin/mount_umap/Makefile
@@ -6,7 +6,7 @@ SRCS= mount_umap.c getmntopts.c
MAN= mount_umap.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_umap/mount_umap.c b/sbin/mount_umap/mount_umap.c
index 0aa7b8c..14299fd 100644
--- a/sbin/mount_umap/mount_umap.c
+++ b/sbin/mount_umap/mount_umap.c
@@ -52,7 +52,7 @@ static const char rcsid[] =
#include <sys/mount.h>
#include <sys/stat.h>
-#include <miscfs/umapfs/umap.h>
+#include <fs/umapfs/umap.h>
#include <err.h>
#include <stdio.h>
diff --git a/sbin/mount_umapfs/Makefile b/sbin/mount_umapfs/Makefile
index 9ae6798..7dc1fc6b 100644
--- a/sbin/mount_umapfs/Makefile
+++ b/sbin/mount_umapfs/Makefile
@@ -6,7 +6,7 @@ SRCS= mount_umap.c getmntopts.c
MAN= mount_umap.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_umapfs/mount_umapfs.c b/sbin/mount_umapfs/mount_umapfs.c
index 0aa7b8c..14299fd 100644
--- a/sbin/mount_umapfs/mount_umapfs.c
+++ b/sbin/mount_umapfs/mount_umapfs.c
@@ -52,7 +52,7 @@ static const char rcsid[] =
#include <sys/mount.h>
#include <sys/stat.h>
-#include <miscfs/umapfs/umap.h>
+#include <fs/umapfs/umap.h>
#include <err.h>
#include <stdio.h>
diff --git a/sbin/mount_union/Makefile b/sbin/mount_union/Makefile
index 6b58c2d..7e0df33 100644
--- a/sbin/mount_union/Makefile
+++ b/sbin/mount_union/Makefile
@@ -6,7 +6,7 @@ SRCS= mount_union.c getmntopts.c
MAN= mount_union.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_union/mount_union.c b/sbin/mount_union/mount_union.c
index 1d5d3eb..d07f427 100644
--- a/sbin/mount_union/mount_union.c
+++ b/sbin/mount_union/mount_union.c
@@ -52,7 +52,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
-#include <miscfs/union/union.h>
+#include <fs/unionfs/union.h>
#include <err.h>
#include <stdio.h>
diff --git a/sbin/mount_unionfs/Makefile b/sbin/mount_unionfs/Makefile
index 6b58c2d..7e0df33 100644
--- a/sbin/mount_unionfs/Makefile
+++ b/sbin/mount_unionfs/Makefile
@@ -6,7 +6,7 @@ SRCS= mount_union.c getmntopts.c
MAN= mount_union.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/sbin/mount_unionfs/mount_unionfs.c b/sbin/mount_unionfs/mount_unionfs.c
index 1d5d3eb..d07f427 100644
--- a/sbin/mount_unionfs/mount_unionfs.c
+++ b/sbin/mount_unionfs/mount_unionfs.c
@@ -52,7 +52,7 @@ static const char rcsid[] =
#include <sys/param.h>
#include <sys/mount.h>
-#include <miscfs/union/union.h>
+#include <fs/unionfs/union.h>
#include <err.h>
#include <stdio.h>
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c
index ddedd8e..9e1a6ef 100644
--- a/sys/alpha/alpha/machdep.c
+++ b/sys/alpha/alpha/machdep.c
@@ -142,7 +142,7 @@
#include <ddb/ddb.h>
#include <alpha/alpha/db_instruction.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <machine/sigframe.h>
u_int64_t cycles_per_usec;
diff --git a/sys/alpha/alpha/procfs_machdep.c b/sys/alpha/alpha/procfs_machdep.c
index 06869b0..96fd0e5 100644
--- a/sys/alpha/alpha/procfs_machdep.c
+++ b/sys/alpha/alpha/procfs_machdep.c
@@ -75,7 +75,7 @@
#include <machine/md_var.h>
#include <machine/reg.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/alpha/osf1/osf1_signal.c b/sys/alpha/osf1/osf1_signal.c
index f84bd4a..4152521 100644
--- a/sys/alpha/osf1/osf1_signal.c
+++ b/sys/alpha/osf1/osf1_signal.c
@@ -75,7 +75,7 @@
#include <ddb/ddb.h>
#include <alpha/alpha/db_instruction.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <alpha/osf1/osf1_signal.h>
#include <alpha/osf1/osf1_proto.h>
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 14302b2..117c6fd 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -662,16 +662,16 @@ options NFS #Network File System
# The rest are optional:
#options NFS_NOSERVER #Disable the NFS-server code.
options CD9660 #ISO 9660 filesystem
-options FDESC #File descriptor filesystem
+options FDESCFS #File descriptor filesystem
options HPFS #OS/2 File system
options MSDOSFS #MS DOS File System (FAT, FAT32)
options NTFS #NT File System
options NULLFS #NULL filesystem
options NWFS #NetWare filesystem
-options PORTAL #Portal filesystem
+options PORTALFS #Portal filesystem
options PROCFS #Process filesystem
options UMAPFS #UID map filesystem
-options UNION #Union filesystem
+options UNIONFS #Union filesystem
# options NODEVFS #disable devices filesystem
# The xFS_ROOT options REQUIRE the associated ``options xFS''
options NFS_ROOT #NFS usable as root device
diff --git a/sys/conf/files b/sys/conf/files
index 5d7ae36..168abd7 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -585,15 +585,44 @@ dev/wds/wd7000.c optional wds isa
dev/wi/if_wi.c optional wi card
dev/wi/if_wi.c optional wi pccard
dev/xe/if_xe.c optional xe card
-fs/devfs/devfs_vnops.c standard
-fs/devfs/devfs_vfsops.c standard
+fs/deadfs/dead_vnops.c standard
fs/devfs/devfs_devs.c standard
-fs/hpfs/hpfs_vfsops.c optional hpfs
-fs/hpfs/hpfs_vnops.c optional hpfs
+fs/devfs/devfs_vfsops.c standard
+fs/devfs/devfs_vnops.c standard
+fs/fdescfs/fdesc_vfsops.c optional fdescfs
+fs/fdescfs/fdesc_vnops.c optional fdescfs
+fs/fifofs/fifo_vnops.c standard
+fs/hpfs/hpfs_alsubr.c optional hpfs
fs/hpfs/hpfs_hash.c optional hpfs
-fs/hpfs/hpfs_subr.c optional hpfs
fs/hpfs/hpfs_lookup.c optional hpfs
-fs/hpfs/hpfs_alsubr.c optional hpfs
+fs/hpfs/hpfs_subr.c optional hpfs
+fs/hpfs/hpfs_vfsops.c optional hpfs
+fs/hpfs/hpfs_vnops.c optional hpfs
+fs/nullfs/null_subr.c optional nullfs
+fs/nullfs/null_vfsops.c optional nullfs
+fs/nullfs/null_vnops.c optional nullfs
+fs/portalfs/portal_vfsops.c optional portalfs
+fs/portalfs/portal_vnops.c optional portalfs
+fs/procfs/procfs_ctl.c optional procfs
+fs/procfs/procfs_dbregs.c standard
+fs/procfs/procfs_fpregs.c standard
+fs/procfs/procfs_map.c optional procfs
+fs/procfs/procfs_mem.c standard
+fs/procfs/procfs_note.c optional procfs
+fs/procfs/procfs_regs.c standard
+fs/procfs/procfs_rlimit.c optional procfs
+fs/procfs/procfs_status.c optional procfs
+fs/procfs/procfs_subr.c optional procfs
+fs/procfs/procfs_type.c optional procfs
+fs/procfs/procfs_vfsops.c optional procfs
+fs/procfs/procfs_vnops.c optional procfs
+fs/specfs/spec_vnops.c standard
+fs/umapfs/umap_subr.c optional umapfs
+fs/umapfs/umap_vfsops.c optional umapfs
+fs/umapfs/umap_vnops.c optional umapfs
+fs/unionfs/union_subr.c optional unionfs
+fs/unionfs/union_vfsops.c optional unionfs
+fs/unionfs/union_vnops.c optional unionfs
gnu/ext2fs/ext2_alloc.c optional ext2fs
gnu/ext2fs/ext2_balloc.c optional ext2fs
gnu/ext2fs/ext2_inode.c optional ext2fs
@@ -803,35 +832,6 @@ libkern/strtol.c standard
libkern/strtoq.c standard
libkern/strtoul.c standard
libkern/strtouq.c standard
-miscfs/deadfs/dead_vnops.c standard
-miscfs/fdesc/fdesc_vfsops.c optional fdesc
-miscfs/fdesc/fdesc_vnops.c optional fdesc
-miscfs/fifofs/fifo_vnops.c standard
-miscfs/nullfs/null_subr.c optional nullfs
-miscfs/nullfs/null_vfsops.c optional nullfs
-miscfs/nullfs/null_vnops.c optional nullfs
-miscfs/portal/portal_vfsops.c optional portal
-miscfs/portal/portal_vnops.c optional portal
-miscfs/procfs/procfs_ctl.c optional procfs
-miscfs/procfs/procfs_dbregs.c standard
-miscfs/procfs/procfs_fpregs.c standard
-miscfs/procfs/procfs_map.c optional procfs
-miscfs/procfs/procfs_mem.c standard
-miscfs/procfs/procfs_note.c optional procfs
-miscfs/procfs/procfs_regs.c standard
-miscfs/procfs/procfs_rlimit.c optional procfs
-miscfs/procfs/procfs_status.c optional procfs
-miscfs/procfs/procfs_subr.c optional procfs
-miscfs/procfs/procfs_type.c optional procfs
-miscfs/procfs/procfs_vfsops.c optional procfs
-miscfs/procfs/procfs_vnops.c optional procfs
-miscfs/specfs/spec_vnops.c standard
-miscfs/umapfs/umap_subr.c optional umapfs
-miscfs/umapfs/umap_vfsops.c optional umapfs
-miscfs/umapfs/umap_vnops.c optional umapfs
-miscfs/union/union_subr.c optional union
-miscfs/union/union_vfsops.c optional union
-miscfs/union/union_vnops.c optional union
msdosfs/msdosfs_conv.c optional msdosfs
msdosfs/msdosfs_denode.c optional msdosfs
msdosfs/msdosfs_fat.c optional msdosfs
diff --git a/sys/conf/options b/sys/conf/options
index a4bb13e..f94d6a6 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -118,7 +118,7 @@ INCLUDE_CONFIG_FILE opt_config.h
CD9660 opt_dontuse.h
CODA opt_dontuse.h
EXT2FS opt_dontuse.h
-FDESC opt_dontuse.h
+FDESCFS opt_dontuse.h
FFS opt_dontuse.h
IFS opt_dontuse.h
LINPROCFS opt_dontuse.h
@@ -126,12 +126,12 @@ MFS opt_dontuse.h
MSDOSFS opt_dontuse.h
NULLFS opt_dontuse.h
NWFS opt_dontuse.h
-PORTAL opt_dontuse.h
+PORTALFS opt_dontuse.h
PROCFS opt_dontuse.h
UMAPFS opt_dontuse.h
NTFS opt_dontuse.h
HPFS opt_dontuse.h
-UNION opt_dontuse.h
+UNIONFS opt_dontuse.h
# These static filesystems has one slightly bogus static dependency in
# sys/i386/i386/autoconf.c. If any of these filesystems are
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index e8eb934..702823e 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -48,7 +48,7 @@
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
-#include <miscfs/fifofs/fifo.h>
+#include <fs/fifofs/fifo.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/unistd.h>
diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c
index a758bb8..1bb1f71 100644
--- a/sys/fs/fdescfs/fdesc_vfsops.c
+++ b/sys/fs/fdescfs/fdesc_vfsops.c
@@ -54,7 +54,7 @@
#include <sys/socket.h>
#include <sys/vnode.h>
-#include <miscfs/fdesc/fdesc.h>
+#include <fs/fdescfs/fdesc.h>
static MALLOC_DEFINE(M_FDESCMNT, "FDESC mount", "FDESC mount structure");
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index 065e0a8..cb90212 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -58,7 +58,7 @@
#include <sys/stat.h>
#include <sys/vnode.h>
-#include <miscfs/fdesc/fdesc.h>
+#include <fs/fdescfs/fdesc.h>
#define FDL_WANT 0x01
#define FDL_LOCKED 0x02
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index 3cd5425..2a3078f 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -49,7 +49,7 @@
#include <sys/event.h>
#include <sys/poll.h>
#include <sys/un.h>
-#include <miscfs/fifofs/fifo.h>
+#include <fs/fifofs/fifo.h>
/*
* This structure is associated with the FIFO vnode and stores
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 88f1584..97aa492 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -47,7 +47,7 @@
#include <sys/proc.h>
#include <sys/vnode.h>
-#include <miscfs/nullfs/null.h>
+#include <fs/nullfs/null.h>
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NNULLNODECACHE 16
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 8573398..e2287ef 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -54,7 +54,7 @@
#include <sys/proc.h>
#include <sys/vnode.h>
-#include <miscfs/nullfs/null.h>
+#include <fs/nullfs/null.h>
static MALLOC_DEFINE(M_NULLFSMNT, "NULLFS mount", "NULLFS mount structure");
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index d37ef73..32b9665 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -185,7 +185,7 @@
#include <sys/sysctl.h>
#include <sys/vnode.h>
-#include <miscfs/nullfs/null.h>
+#include <fs/nullfs/null.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c
index 423cd38..7178599 100644
--- a/sys/fs/portalfs/portal_vfsops.c
+++ b/sys/fs/portalfs/portal_vfsops.c
@@ -57,7 +57,7 @@
#include <sys/socketvar.h>
#include <sys/vnode.h>
-#include <miscfs/portal/portal.h>
+#include <fs/portalfs/portal.h>
static MALLOC_DEFINE(M_PORTALFSMNT, "PORTAL mount", "PORTAL mount structure");
diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c
index b53c4ca..726873e 100644
--- a/sys/fs/portalfs/portal_vnops.c
+++ b/sys/fs/portalfs/portal_vnops.c
@@ -61,7 +61,7 @@
#include <sys/socketvar.h>
#include <sys/un.h>
#include <sys/unpcb.h>
-#include <miscfs/portal/portal.h>
+#include <fs/portalfs/portal.h>
static int portal_fileid = PORTAL_ROOTFILEID+1;
diff --git a/sys/fs/procfs/procfs_ctl.c b/sys/fs/procfs/procfs_ctl.c
index 5818758..a507349 100644
--- a/sys/fs/procfs/procfs_ctl.c
+++ b/sys/fs/procfs/procfs_ctl.c
@@ -48,7 +48,7 @@
#include <sys/sx.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
diff --git a/sys/fs/procfs/procfs_dbregs.c b/sys/fs/procfs/procfs_dbregs.c
index d80e28c..cd64a34 100644
--- a/sys/fs/procfs/procfs_dbregs.c
+++ b/sys/fs/procfs/procfs_dbregs.c
@@ -52,7 +52,7 @@
#include <machine/reg.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
diff --git a/sys/fs/procfs/procfs_fpregs.c b/sys/fs/procfs/procfs_fpregs.c
index 7e2ff52..c71e444 100644
--- a/sys/fs/procfs/procfs_fpregs.c
+++ b/sys/fs/procfs/procfs_fpregs.c
@@ -49,7 +49,7 @@
#include <machine/reg.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c
index 5c21993..e974b04 100644
--- a/sys/fs/procfs/procfs_map.c
+++ b/sys/fs/procfs/procfs_map.c
@@ -46,7 +46,7 @@
#include <sys/proc.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/fs/procfs/procfs_mem.c b/sys/fs/procfs/procfs_mem.c
index 1e28870..b8c60d6 100644
--- a/sys/fs/procfs/procfs_mem.c
+++ b/sys/fs/procfs/procfs_mem.c
@@ -54,7 +54,7 @@
#include <sys/user.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
diff --git a/sys/fs/procfs/procfs_note.c b/sys/fs/procfs/procfs_note.c
index 273010b..c669654 100644
--- a/sys/fs/procfs/procfs_note.c
+++ b/sys/fs/procfs/procfs_note.c
@@ -41,7 +41,7 @@
#include <sys/param.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
int
procfs_donote(curp, p, pfs, uio)
diff --git a/sys/fs/procfs/procfs_regs.c b/sys/fs/procfs/procfs_regs.c
index ba58517..c7eeb1c 100644
--- a/sys/fs/procfs/procfs_regs.c
+++ b/sys/fs/procfs/procfs_regs.c
@@ -52,7 +52,7 @@
#include <vm/vm.h>
#include <vm/vm_extern.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
int
procfs_doregs(curp, p, pfs, uio)
diff --git a/sys/fs/procfs/procfs_rlimit.c b/sys/fs/procfs/procfs_rlimit.c
index 361f6f6..f74874d 100644
--- a/sys/fs/procfs/procfs_rlimit.c
+++ b/sys/fs/procfs/procfs_rlimit.c
@@ -52,7 +52,7 @@
#include <sys/resourcevar.h>
#include <sys/resource.h>
#include <sys/types.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
int
diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c
index b29b4a9..9620be5 100644
--- a/sys/fs/procfs/procfs_status.c
+++ b/sys/fs/procfs/procfs_status.c
@@ -56,7 +56,7 @@
#include <vm/pmap.h>
#include <vm/vm_param.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0)
int
diff --git a/sys/fs/procfs/procfs_subr.c b/sys/fs/procfs/procfs_subr.c
index 64adecb..36d366f 100644
--- a/sys/fs/procfs/procfs_subr.c
+++ b/sys/fs/procfs/procfs_subr.c
@@ -50,7 +50,7 @@
#include <sys/sysctl.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
static struct pfsnode *pfshead;
static int pfsvplock;
diff --git a/sys/fs/procfs/procfs_type.c b/sys/fs/procfs/procfs_type.c
index cb2a45f..3919c88 100644
--- a/sys/fs/procfs/procfs_type.c
+++ b/sys/fs/procfs/procfs_type.c
@@ -42,7 +42,7 @@
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
int
procfs_dotype(curp, p, pfs, uio)
diff --git a/sys/fs/procfs/procfs_vfsops.c b/sys/fs/procfs/procfs_vfsops.c
index 91daf9d..c0d7add 100644
--- a/sys/fs/procfs/procfs_vfsops.c
+++ b/sys/fs/procfs/procfs_vfsops.c
@@ -49,7 +49,7 @@
#include <sys/proc.h>
#include <sys/mount.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct proc *p));
diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c
index dbdafc8..a054eb9 100644
--- a/sys/fs/procfs/procfs_vnops.c
+++ b/sys/fs/procfs/procfs_vnops.c
@@ -66,7 +66,7 @@
#include <vm/vm_zone.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
static int procfs_access __P((struct vop_access_args *));
static int procfs_badop __P((void));
diff --git a/sys/fs/umapfs/umap_subr.c b/sys/fs/umapfs/umap_subr.c
index 1f94d50..afcaceb 100644
--- a/sys/fs/umapfs/umap_subr.c
+++ b/sys/fs/umapfs/umap_subr.c
@@ -45,7 +45,7 @@
#include <sys/proc.h>
#include <sys/vnode.h>
-#include <miscfs/umapfs/umap.h>
+#include <fs/umapfs/umap.h>
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NUMAPNODECACHE 16
diff --git a/sys/fs/umapfs/umap_vfsops.c b/sys/fs/umapfs/umap_vfsops.c
index 280ded9..b8dc4c9 100644
--- a/sys/fs/umapfs/umap_vfsops.c
+++ b/sys/fs/umapfs/umap_vfsops.c
@@ -53,7 +53,7 @@
#include <sys/namei.h>
#include <sys/vnode.h>
-#include <miscfs/umapfs/umap.h>
+#include <fs/umapfs/umap.h>
static MALLOC_DEFINE(M_UMAPFSMNT, "UMAP mount", "UMAP mount structure");
diff --git a/sys/fs/umapfs/umap_vnops.c b/sys/fs/umapfs/umap_vnops.c
index 5bf29c8..b73ff2c 100644
--- a/sys/fs/umapfs/umap_vnops.c
+++ b/sys/fs/umapfs/umap_vnops.c
@@ -51,8 +51,8 @@
#include <sys/sysctl.h>
#include <sys/vnode.h>
-#include <miscfs/umapfs/umap.h>
-#include <miscfs/nullfs/null.h>
+#include <fs/umapfs/umap.h>
+#include <fs/nullfs/null.h>
static int umap_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
SYSCTL_INT(_debug, OID_AUTO, umapfs_bug_bypass, CTLFLAG_RW,
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
index ce38e2d..52a5483 100644
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -58,7 +58,7 @@
#include <vm/vm_zone.h>
#include <vm/vm_object.h> /* for vm cache coherency */
-#include <miscfs/union/union.h>
+#include <fs/unionfs/union.h>
#include <sys/proc.h>
diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c
index d38f31e..5a5af5d 100644
--- a/sys/fs/unionfs/union_vfsops.c
+++ b/sys/fs/unionfs/union_vfsops.c
@@ -51,7 +51,7 @@
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/filedesc.h>
-#include <miscfs/union/union.h>
+#include <fs/unionfs/union.h>
static MALLOC_DEFINE(M_UNIONFSMNT, "UNION mount", "UNION mount structure");
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 3402825..b5abfa7 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -51,7 +51,7 @@
#include <sys/buf.h>
#include <sys/lock.h>
#include <sys/sysctl.h>
-#include <miscfs/union/union.h>
+#include <fs/unionfs/union.h>
#include <vm/vm.h>
#include <vm/vnode_pager.h>
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 14302b2..117c6fd 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -662,16 +662,16 @@ options NFS #Network File System
# The rest are optional:
#options NFS_NOSERVER #Disable the NFS-server code.
options CD9660 #ISO 9660 filesystem
-options FDESC #File descriptor filesystem
+options FDESCFS #File descriptor filesystem
options HPFS #OS/2 File system
options MSDOSFS #MS DOS File System (FAT, FAT32)
options NTFS #NT File System
options NULLFS #NULL filesystem
options NWFS #NetWare filesystem
-options PORTAL #Portal filesystem
+options PORTALFS #Portal filesystem
options PROCFS #Process filesystem
options UMAPFS #UID map filesystem
-options UNION #Union filesystem
+options UNIONFS #Union filesystem
# options NODEVFS #disable devices filesystem
# The xFS_ROOT options REQUIRE the associated ``options xFS''
options NFS_ROOT #NFS usable as root device
diff --git a/sys/i386/i386/procfs_machdep.c b/sys/i386/i386/procfs_machdep.c
index 44a5564..f951b0f 100644
--- a/sys/i386/i386/procfs_machdep.c
+++ b/sys/i386/i386/procfs_machdep.c
@@ -77,7 +77,7 @@
#include <machine/reg.h>
#include <machine/md_var.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index e2223a8..9dae762 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -75,7 +75,7 @@
#include <ddb/ddb.h>
#include <alpha/alpha/db_instruction.h>
#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <machine/sigframe.h>
u_int64_t cycles_per_usec;
diff --git a/sys/ia64/ia64/procfs_machdep.c b/sys/ia64/ia64/procfs_machdep.c
index 6deaafa..e623e49 100644
--- a/sys/ia64/ia64/procfs_machdep.c
+++ b/sys/ia64/ia64/procfs_machdep.c
@@ -73,7 +73,7 @@
#include <sys/vnode.h>
#include <machine/reg.h>
#include <machine/md_var.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c
index e8eb934..702823e 100644
--- a/sys/isofs/cd9660/cd9660_vnops.c
+++ b/sys/isofs/cd9660/cd9660_vnops.c
@@ -48,7 +48,7 @@
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
-#include <miscfs/fifofs/fifo.h>
+#include <fs/fifofs/fifo.h>
#include <sys/malloc.h>
#include <sys/dirent.h>
#include <sys/unistd.h>
diff --git a/sys/kern/Make.tags.inc b/sys/kern/Make.tags.inc
index 3f9f980..59dd7a7 100644
--- a/sys/kern/Make.tags.inc
+++ b/sys/kern/Make.tags.inc
@@ -28,17 +28,17 @@ COMM= ${SYS}/conf/*.[ch] \
${SYS}/dev/smbus/*.[ch] \
${SYS}/dev/vn/*.[ch] \
${SYS}/dev/vx/*.[ch] \
+ ${SYS}/fs/deadfs/*.[ch] \
+ ${SYS}/fs/fdescfs/*.[ch] \
+ ${SYS}/fs/fifofs/*.[ch] \
+ ${SYS}/fs/nullfs/*.[ch] \
+ ${SYS}/fs/portalfs/*.[ch] \
+ ${SYS}/fs/procfs/*.[ch] \
+ ${SYS}/fs/specfs/*.[ch] \
+ ${SYS}/fs/umapfs/*.[ch] \
+ ${SYS}/fs/unionfs/*.[ch] \
${SYS}/isofs/cd9660/*.[ch] \
${SYS}/kern/*.[ch] \
- ${SYS}/miscfs/deadfs/*.[ch] \
- ${SYS}/miscfs/fdesc/*.[ch] \
- ${SYS}/miscfs/fifofs/*.[ch] \
- ${SYS}/miscfs/nullfs/*.[ch] \
- ${SYS}/miscfs/portal/*.[ch] \
- ${SYS}/miscfs/procfs/*.[ch] \
- ${SYS}/miscfs/specfs/*.[ch] \
- ${SYS}/miscfs/umapfs/*.[ch] \
- ${SYS}/miscfs/union/*.[ch] \
${SYS}/msdosfs/*.[ch] \
${SYS}/net/*.[ch] \
${SYS}/netatalk/*.[ch] \
@@ -91,17 +91,17 @@ COMMDIR2= ${SYS}/dev/advansys \
${SYS}/dev/smbus \
${SYS}/dev/vn \
${SYS}/dev/vx \
+ ${SYS}/fs/deadfs \
+ ${SYS}/fs/devfs \
+ ${SYS}/fs/fdescfs \
+ ${SYS}/fs/fifofs \
+ ${SYS}/fs/nullfs \
+ ${SYS}/fs/portalfs \
+ ${SYS}/fs/procfs \
+ ${SYS}/fs/specfs \
+ ${SYS}/fs/umapfs \
+ ${SYS}/fs/unionfs \
${SYS}/isofs/cd9660 \
- ${SYS}/miscfs/deadfs \
- ${SYS}/miscfs/devfs \
- ${SYS}/miscfs/fdesc \
- ${SYS}/miscfs/fifofs \
- ${SYS}/miscfs/nullfs \
- ${SYS}/miscfs/portal \
- ${SYS}/miscfs/procfs \
- ${SYS}/miscfs/specfs \
- ${SYS}/miscfs/umapfs \
- ${SYS}/miscfs/union \
${SYS}/ufs/ffs \
${SYS}/ufs/mfs \
${SYS}/ufs/ufs
diff --git a/sys/kern/Makefile b/sys/kern/Makefile
index 37f03ab..5cc169d 100644
--- a/sys/kern/Makefile
+++ b/sys/kern/Makefile
@@ -33,11 +33,11 @@ SYSDIR=/sys
# Directories in which to place tags links (other than machine-dependent)
DGEN= conf \
dev dev/scsi \
+ fs fs/deadfs fs/fdescfs fs/fifofs \
+ fs/lofs fs/nullfs fs/portalfs fs/procfs \
+ fs/specfs fs/umapfs fs/unionfs \
hp hp/dev hp/hpux \
kern libkern \
- miscfs miscfs/deadfs miscfs/fdesc miscfs/fifofs \
- miscfs/lofs miscfs/nullfs miscfs/portal miscfs/procfs \
- miscfs/specfs miscfs/umapfs miscfs/union \
net netccitt netinet netiso netns nfs scripts sys \
ufs ufs/ffs ufs/lfs ufs/mfs ufs/ufs \
vm
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 03640cf..799608d 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -49,7 +49,7 @@
#include <vm/vm_map.h>
#include <vm/vm_page.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
/* use the equivalent procfs code */
#if 0
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 3f97551..e5ee6e7 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -68,7 +68,6 @@
#include <sys/jail.h>
#include <machine/limits.h>
-#include <miscfs/union/union.h>
#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 3f97551..e5ee6e7 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -68,7 +68,6 @@
#include <sys/jail.h>
#include <machine/limits.h>
-#include <miscfs/union/union.h>
#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
diff --git a/sys/miscfs/deadfs/dead_vnops.c b/sys/miscfs/deadfs/dead_vnops.c
deleted file mode 100644
index 9911453..0000000
--- a/sys/miscfs/deadfs/dead_vnops.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)dead_vnops.c 8.1 (Berkeley) 6/10/93
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/poll.h>
-#include <sys/vnode.h>
-
-static int chkvnlock __P((struct vnode *));
-/*
- * Prototypes for dead operations on vnodes.
- */
-static int dead_badop __P((void));
-static int dead_bmap __P((struct vop_bmap_args *));
-static int dead_ioctl __P((struct vop_ioctl_args *));
-static int dead_lock __P((struct vop_lock_args *));
-static int dead_lookup __P((struct vop_lookup_args *));
-static int dead_open __P((struct vop_open_args *));
-static int dead_poll __P((struct vop_poll_args *));
-static int dead_print __P((struct vop_print_args *));
-static int dead_read __P((struct vop_read_args *));
-static int dead_write __P((struct vop_write_args *));
-
-vop_t **dead_vnodeop_p;
-static struct vnodeopv_entry_desc dead_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) vop_ebadf },
- { &vop_advlock_desc, (vop_t *) vop_ebadf },
- { &vop_bmap_desc, (vop_t *) dead_bmap },
- { &vop_create_desc, (vop_t *) dead_badop },
- { &vop_getattr_desc, (vop_t *) vop_ebadf },
- { &vop_inactive_desc, (vop_t *) vop_null },
- { &vop_ioctl_desc, (vop_t *) dead_ioctl },
- { &vop_link_desc, (vop_t *) dead_badop },
- { &vop_lock_desc, (vop_t *) dead_lock },
- { &vop_lookup_desc, (vop_t *) dead_lookup },
- { &vop_mkdir_desc, (vop_t *) dead_badop },
- { &vop_mknod_desc, (vop_t *) dead_badop },
- { &vop_open_desc, (vop_t *) dead_open },
- { &vop_pathconf_desc, (vop_t *) vop_ebadf }, /* per pathconf(2) */
- { &vop_poll_desc, (vop_t *) dead_poll },
- { &vop_print_desc, (vop_t *) dead_print },
- { &vop_read_desc, (vop_t *) dead_read },
- { &vop_readdir_desc, (vop_t *) vop_ebadf },
- { &vop_readlink_desc, (vop_t *) vop_ebadf },
- { &vop_reclaim_desc, (vop_t *) vop_null },
- { &vop_remove_desc, (vop_t *) dead_badop },
- { &vop_rename_desc, (vop_t *) dead_badop },
- { &vop_rmdir_desc, (vop_t *) dead_badop },
- { &vop_setattr_desc, (vop_t *) vop_ebadf },
- { &vop_symlink_desc, (vop_t *) dead_badop },
- { &vop_write_desc, (vop_t *) dead_write },
- { NULL, NULL }
-};
-static struct vnodeopv_desc dead_vnodeop_opv_desc =
- { &dead_vnodeop_p, dead_vnodeop_entries };
-
-VNODEOP_SET(dead_vnodeop_opv_desc);
-
-/*
- * Trivial lookup routine that always fails.
- */
-/* ARGSUSED */
-static int
-dead_lookup(ap)
- struct vop_lookup_args /* {
- struct vnode * a_dvp;
- struct vnode ** a_vpp;
- struct componentname * a_cnp;
- } */ *ap;
-{
-
- *ap->a_vpp = NULL;
- return (ENOTDIR);
-}
-
-/*
- * Open always fails as if device did not exist.
- */
-/* ARGSUSED */
-static int
-dead_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
-
- return (ENXIO);
-}
-
-/*
- * Vnode op for read
- */
-/* ARGSUSED */
-static int
-dead_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
-
- if (chkvnlock(ap->a_vp))
- panic("dead_read: lock");
- /*
- * Return EOF for tty devices, EIO for others
- */
- if ((ap->a_vp->v_flag & VISTTY) == 0)
- return (EIO);
- return (0);
-}
-
-/*
- * Vnode op for write
- */
-/* ARGSUSED */
-static int
-dead_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
-
- if (chkvnlock(ap->a_vp))
- panic("dead_write: lock");
- return (EIO);
-}
-
-/*
- * Device ioctl operation.
- */
-/* ARGSUSED */
-static int
-dead_ioctl(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;
-{
-
- if (!chkvnlock(ap->a_vp))
- return (ENOTTY);
- return (VCALL(ap->a_vp, VOFFSET(vop_ioctl), ap));
-}
-
-
-/*
- * Wait until the vnode has finished changing state.
- */
-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;
-
- /*
- * Since we are not using the lock manager, we must clear
- * the interlock here.
- */
- if (ap->a_flags & LK_INTERLOCK) {
- mtx_unlock(&vp->v_interlock);
- ap->a_flags &= ~LK_INTERLOCK;
- }
- if (!chkvnlock(vp))
- return (0);
- return (VCALL(vp, VOFFSET(vop_lock), ap));
-}
-
-/*
- * Wait until the vnode has finished changing state.
- */
-static int
-dead_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;
- int *a_runb;
- } */ *ap;
-{
-
- if (!chkvnlock(ap->a_vp))
- return (EIO);
- return (VOP_BMAP(ap->a_vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp, ap->a_runb));
-}
-
-/*
- * Print out the contents of a dead vnode.
- */
-/* ARGSUSED */
-static int
-dead_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- printf("tag VT_NON, dead vnode\n");
- return (0);
-}
-
-/*
- * Empty vnode bad operation
- */
-static int
-dead_badop()
-{
-
- panic("dead_badop called");
- /* NOTREACHED */
-}
-
-/*
- * We have to wait during times when the vnode is
- * in a state of change.
- */
-int
-chkvnlock(vp)
- register struct vnode *vp;
-{
- int locked = 0;
-
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- (void) tsleep((caddr_t)vp, PINOD, "ckvnlk", 0);
- locked = 1;
- }
- return (locked);
-}
-
-/*
- * Trivial poll routine that always returns POLLHUP.
- * This is necessary so that a process which is polling a file
- * gets notified when that file is revoke()d.
- */
-static int
-dead_poll(ap)
- struct vop_poll_args *ap;
-{
- return (POLLHUP);
-}
diff --git a/sys/miscfs/fdesc/fdesc.h b/sys/miscfs/fdesc/fdesc.h
deleted file mode 100644
index b78d132..0000000
--- a/sys/miscfs/fdesc/fdesc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fdesc.h 8.5 (Berkeley) 1/21/94
- *
- * $FreeBSD$
- */
-
-#ifdef _KERNEL
-struct fdescmount {
- struct vnode *f_root; /* Root node */
-};
-
-#define FD_ROOT 1
-#define FD_DESC 3
-
-typedef enum {
- Froot,
- Fdesc
-} fdntype;
-
-struct fdescnode {
- 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 */
- int fd_ix; /* filesystem index */
-};
-
-#define VFSTOFDESC(mp) ((struct fdescmount *)((mp)->mnt_data))
-#define VTOFDESC(vp) ((struct fdescnode *)(vp)->v_data)
-
-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 **,
- struct proc *));
-#endif /* _KERNEL */
diff --git a/sys/miscfs/fdesc/fdesc_vfsops.c b/sys/miscfs/fdesc/fdesc_vfsops.c
deleted file mode 100644
index a758bb8..0000000
--- a/sys/miscfs/fdesc/fdesc_vfsops.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fdesc_vfsops.c 8.4 (Berkeley) 1/21/94
- *
- * $FreeBSD$
- */
-
-/*
- * /dev/fd Filesystem
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/filedesc.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/socket.h>
-#include <sys/vnode.h>
-
-#include <miscfs/fdesc/fdesc.h>
-
-static MALLOC_DEFINE(M_FDESCMNT, "FDESC mount", "FDESC mount structure");
-
-static int fdesc_mount __P((struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, struct proc *p));
-static int fdesc_unmount __P((struct mount *mp, int mntflags,
- struct proc *p));
-static int fdesc_statfs __P((struct mount *mp, struct statfs *sbp,
- struct proc *p));
-
-/*
- * Mount the per-process file descriptors (/dev/fd)
- */
-static int
-fdesc_mount(mp, path, data, ndp, p)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct proc *p;
-{
- int error = 0;
- struct fdescmount *fmp;
- struct vnode *rvp;
-
- /*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE)
- return (EOPNOTSUPP);
-
- error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp, p);
- if (error)
- return (error);
-
- MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount),
- M_FDESCMNT, M_WAITOK); /* XXX */
- rvp->v_type = VDIR;
- rvp->v_flag |= VROOT;
- fmp->f_root = rvp;
- /* XXX -- don't mark as local to work around fts() problems */
- /*mp->mnt_flag |= MNT_LOCAL;*/
- mp->mnt_data = (qaddr_t) fmp;
- vfs_getnewfsid(mp);
-
- bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
- bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc"));
- (void)fdesc_statfs(mp, &mp->mnt_stat, p);
- return (0);
-}
-
-static int
-fdesc_unmount(mp, mntflags, p)
- struct mount *mp;
- int mntflags;
- struct proc *p;
-{
- int error;
- int flags = 0;
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
-
- /*
- * Clear out buffer cache. I don't think we
- * ever get anything cached at this level at the
- * moment, but who knows...
- *
- * There is 1 extra root vnode reference corresponding
- * to f_root.
- */
- if ((error = vflush(mp, 1, flags)) != 0)
- return (error);
-
- /*
- * Finally, throw away the fdescmount structure
- */
- free(mp->mnt_data, M_FDESCMNT); /* XXX */
- mp->mnt_data = 0;
-
- return (0);
-}
-
-int
-fdesc_root(mp, vpp)
- struct mount *mp;
- struct vnode **vpp;
-{
- struct proc *p = curproc; /* XXX */
- struct vnode *vp;
-
- /*
- * Return locked reference to root.
- */
- vp = VFSTOFDESC(mp)->f_root;
- VREF(vp);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- *vpp = vp;
- return (0);
-}
-
-static int
-fdesc_statfs(mp, sbp, p)
- struct mount *mp;
- struct statfs *sbp;
- struct proc *p;
-{
- struct filedesc *fdp;
- int lim;
- int i;
- int last;
- int freefd;
-
- /*
- * Compute number of free file descriptors.
- * [ Strange results will ensue if the open file
- * limit is ever reduced below the current number
- * of open files... ]
- */
- lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
- fdp = p->p_fd;
- last = min(fdp->fd_nfiles, lim);
- freefd = 0;
- for (i = fdp->fd_freefile; i < last; i++)
- if (fdp->fd_ofiles[i] == NULL)
- freefd++;
-
- /*
- * Adjust for the fact that the fdesc array may not
- * have been fully allocated yet.
- */
- if (fdp->fd_nfiles < lim)
- freefd += (lim - fdp->fd_nfiles);
-
- sbp->f_flags = 0;
- sbp->f_bsize = DEV_BSIZE;
- sbp->f_iosize = DEV_BSIZE;
- sbp->f_blocks = 2; /* 1K to keep df happy */
- sbp->f_bfree = 0;
- sbp->f_bavail = 0;
- 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);
- }
- return (0);
-}
-
-static struct vfsops fdesc_vfsops = {
- fdesc_mount,
- vfs_stdstart,
- fdesc_unmount,
- fdesc_root,
- vfs_stdquotactl,
- fdesc_statfs,
- vfs_stdsync,
- vfs_stdvget,
- vfs_stdfhtovp,
- vfs_stdcheckexp,
- vfs_stdvptofh,
- fdesc_init,
- vfs_stduninit,
- vfs_stdextattrctl,
-};
-
-VFS_SET(fdesc_vfsops, fdesc, VFCF_SYNTHETIC);
diff --git a/sys/miscfs/fdesc/fdesc_vnops.c b/sys/miscfs/fdesc/fdesc_vnops.c
deleted file mode 100644
index 065e0a8..0000000
--- a/sys/miscfs/fdesc/fdesc_vnops.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fdesc_vnops.c 8.9 (Berkeley) 1/21/94
- *
- * $FreeBSD$
- */
-
-/*
- * /dev/fd Filesystem
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/dirent.h>
-#include <sys/filedesc.h>
-#include <sys/kernel.h> /* boottime */
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/file.h> /* Must come after sys/malloc.h */
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/vnode.h>
-
-#include <miscfs/fdesc/fdesc.h>
-
-#define FDL_WANT 0x01
-#define FDL_LOCKED 0x02
-static int fdcache_lock;
-
-static vop_t **fdesc_vnodeop_p;
-
-#define NFDCACHE 4
-#define FD_NHASH(ix) \
- (&fdhashtbl[(ix) & fdhash])
-static LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
-static u_long fdhash;
-
-static int fdesc_badop __P((void));
-static int fdesc_getattr __P((struct vop_getattr_args *ap));
-static int fdesc_inactive __P((struct vop_inactive_args *ap));
-static int fdesc_lookup __P((struct vop_lookup_args *ap));
-static int fdesc_open __P((struct vop_open_args *ap));
-static int fdesc_print __P((struct vop_print_args *ap));
-static int fdesc_readdir __P((struct vop_readdir_args *ap));
-static int fdesc_reclaim __P((struct vop_reclaim_args *ap));
-static int fdesc_poll __P((struct vop_poll_args *ap));
-static int fdesc_setattr __P((struct vop_setattr_args *ap));
-
-/*
- * Initialise cache headers
- */
-int
-fdesc_init(vfsp)
- struct vfsconf *vfsp;
-{
-
- fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
- return (0);
-}
-
-int
-fdesc_allocvp(ftype, ix, mp, vpp, p)
- fdntype ftype;
- int ix;
- struct mount *mp;
- struct vnode **vpp;
- struct proc *p;
-{
- struct fdhashhead *fc;
- struct fdescnode *fd;
- int error = 0;
-
- fc = FD_NHASH(ix);
-loop:
- LIST_FOREACH(fd, fc, fd_hash) {
- if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
- if (vget(fd->fd_vnode, 0, p))
- goto loop;
- *vpp = fd->fd_vnode;
- return (error);
- }
- }
-
- /*
- * otherwise lock the array while we call getnewvnode
- * since that can block.
- */
- if (fdcache_lock & FDL_LOCKED) {
- fdcache_lock |= FDL_WANT;
- (void) tsleep((caddr_t) &fdcache_lock, PINOD, "fdalvp", 0);
- goto loop;
- }
- fdcache_lock |= FDL_LOCKED;
-
- /*
- * 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(fd, struct fdescnode *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
-
- error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
- if (error) {
- FREE(fd, M_TEMP);
- goto out;
- }
- (*vpp)->v_data = fd;
- fd->fd_vnode = *vpp;
- fd->fd_type = ftype;
- fd->fd_fd = -1;
- fd->fd_ix = ix;
- LIST_INSERT_HEAD(fc, fd, fd_hash);
-
-out:
- fdcache_lock &= ~FDL_LOCKED;
-
- if (fdcache_lock & FDL_WANT) {
- fdcache_lock &= ~FDL_WANT;
- wakeup((caddr_t) &fdcache_lock);
- }
-
- return (error);
-}
-
-/*
- * vp is the current namei directory
- * ndp is the name to locate in that directory...
- */
-static int
-fdesc_lookup(ap)
- struct vop_lookup_args /* {
- struct vnode * a_dvp;
- struct vnode ** a_vpp;
- struct componentname * a_cnp;
- } */ *ap;
-{
- 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;
- int nlen = cnp->cn_namelen;
- int nfiles = p->p_fd->fd_nfiles;
- u_int fd;
- int error;
- struct vnode *fvp;
-
- if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) {
- error = EROFS;
- goto bad;
- }
-
- VOP_UNLOCK(dvp, 0, p);
- if (cnp->cn_namelen == 1 && *pname == '.') {
- *vpp = dvp;
- VREF(dvp);
- vn_lock(dvp, LK_SHARED | LK_RETRY, p);
- return (0);
- }
-
- if (VTOFDESC(dvp)->fd_type != Froot) {
- error = ENOTDIR;
- goto bad;
- }
-
- fd = 0;
- /* the only time a leading 0 is acceptable is if it's "0" */
- if (*pname == '0' && nlen != 1) {
- error = ENOENT;
- goto bad;
- }
- while (nlen--) {
- if (*pname < '0' || *pname > '9') {
- error = ENOENT;
- goto bad;
- }
- fd = 10 * fd + *pname++ - '0';
- }
-
- if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) {
- error = EBADF;
- goto bad;
- }
-
- error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp, p);
- 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);
-}
-
-static int
-fdesc_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- if (VTOFDESC(vp)->fd_type == Froot)
- return (0);
-
- /*
- * XXX Kludge: set p->p_dupfd to contain the value of the the file
- * descriptor being sought for duplication. The error return ensures
- * that the vnode for this device will be released by vn_open. Open
- * will detect this special error and take the actions in dupfdopen.
- * Other callers of vn_open or VOP_OPEN will simply report the
- * error.
- */
- ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */
- return (ENODEV);
-}
-
-static int
-fdesc_getattr(ap)
- struct vop_getattr_args /* {
- 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;
- struct filedesc *fdp = ap->a_p->p_fd;
- struct file *fp;
- struct stat stb;
- u_int fd;
- int error = 0;
-
- switch (VTOFDESC(vp)->fd_type) {
- case Froot:
- VATTR_NULL(vap);
-
- vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
- vap->va_type = VDIR;
- vap->va_nlink = 2;
- vap->va_size = DEV_BSIZE;
- vap->va_fileid = VTOFDESC(vp)->fd_ix;
- vap->va_uid = 0;
- vap->va_gid = 0;
- vap->va_blocksize = DEV_BSIZE;
- vap->va_atime.tv_sec = boottime.tv_sec;
- vap->va_atime.tv_nsec = 0;
- vap->va_mtime = vap->va_atime;
- vap->va_ctime = vap->va_mtime;
- vap->va_gen = 0;
- vap->va_flags = 0;
- vap->va_rdev = 0;
- vap->va_bytes = 0;
- break;
-
- case Fdesc:
- fd = VTOFDESC(vp)->fd_fd;
-
- if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
- return (EBADF);
-
- bzero(&stb, sizeof(stb));
- error = fo_stat(fp, &stb, ap->a_p);
- if (error == 0) {
- VATTR_NULL(vap);
- vap->va_type = IFTOVT(stb.st_mode);
- vap->va_mode = stb.st_mode;
-#define FDRX (VREAD|VEXEC)
- if (vap->va_type == VDIR)
- vap->va_mode &= ~((FDRX)|(FDRX>>3)|(FDRX>>6));
-#undef FDRX
- vap->va_nlink = 1;
- vap->va_flags = 0;
- vap->va_bytes = stb.st_blocks * stb.st_blksize;
- vap->va_fileid = VTOFDESC(vp)->fd_ix;
- vap->va_size = stb.st_size;
- vap->va_blocksize = stb.st_blksize;
- vap->va_rdev = stb.st_rdev;
-
- /*
- * If no time data is provided, use the current time.
- */
- if (stb.st_atimespec.tv_sec == 0 &&
- stb.st_atimespec.tv_nsec == 0)
- nanotime(&stb.st_atimespec);
-
- if (stb.st_ctimespec.tv_sec == 0 &&
- stb.st_ctimespec.tv_nsec == 0)
- nanotime(&stb.st_ctimespec);
-
- if (stb.st_mtimespec.tv_sec == 0 &&
- stb.st_mtimespec.tv_nsec == 0)
- nanotime(&stb.st_mtimespec);
-
- vap->va_atime = stb.st_atimespec;
- vap->va_mtime = stb.st_mtimespec;
- vap->va_ctime = stb.st_ctimespec;
- vap->va_uid = stb.st_uid;
- vap->va_gid = stb.st_gid;
- }
- break;
-
- default:
- panic("fdesc_getattr");
- break;
- }
-
- if (error == 0)
- vp->v_type = vap->va_type;
- return (error);
-}
-
-static int
-fdesc_setattr(ap)
- struct vop_setattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct vattr *vap = ap->a_vap;
- struct vnode *vp;
- struct mount *mp;
- struct file *fp;
- unsigned fd;
- int error;
-
- /*
- * Can't mess with the root vnode
- */
- if (VTOFDESC(ap->a_vp)->fd_type == Froot)
- return (EACCES);
-
- fd = VTOFDESC(ap->a_vp)->fd_fd;
-
- /*
- * Allow setattr where there is an underlying vnode.
- */
- error = getvnode(ap->a_p->p_fd, fd, &fp);
- if (error) {
- /*
- * getvnode() returns EINVAL if the file descriptor is not
- * backed by a vnode. Silently drop all changes except
- * chflags(2) in this case.
- */
- if (error == EINVAL) {
- if (vap->va_flags != VNOVAL)
- error = EOPNOTSUPP;
- else
- error = 0;
- }
- return (error);
- }
- vp = (struct vnode *)fp->f_data;
- if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
- return (error);
- error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p);
- vn_finished_write(mp);
- return (error);
-}
-
-#define UIO_MX 16
-
-static int
-fdesc_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;
-{
- struct uio *uio = ap->a_uio;
- struct filedesc *fdp;
- struct dirent d;
- struct dirent *dp = &d;
- int error, i, off, fcnt;
-
- /*
- * We don't allow exporting fdesc mounts, and currently local
- * requests do not need cookies.
- */
- if (ap->a_ncookies)
- panic("fdesc_readdir: not hungry");
-
- if (VTOFDESC(ap->a_vp)->fd_type != Froot)
- panic("fdesc_readdir: not dir");
-
- off = (int)uio->uio_offset;
- if (off != uio->uio_offset || off < 0 || (u_int)off % UIO_MX != 0 ||
- uio->uio_resid < UIO_MX)
- return (EINVAL);
- i = (u_int)off / UIO_MX;
- fdp = uio->uio_procp->p_fd;
- error = 0;
-
- fcnt = i - 2; /* The first two nodes are `.' and `..' */
-
- while (i < fdp->fd_nfiles + 2 && uio->uio_resid >= UIO_MX) {
- switch (i) {
- case 0: /* `.' */
- case 1: /* `..' */
- bzero((caddr_t)dp, UIO_MX);
-
- dp->d_fileno = i + FD_ROOT;
- dp->d_namlen = i + 1;
- dp->d_reclen = UIO_MX;
- bcopy("..", dp->d_name, dp->d_namlen);
- dp->d_name[i + 1] = '\0';
- dp->d_type = DT_DIR;
- break;
- default:
- if (fdp->fd_ofiles[fcnt] == NULL)
- goto done;
-
- bzero((caddr_t) dp, UIO_MX);
- dp->d_namlen = sprintf(dp->d_name, "%d", fcnt);
- dp->d_reclen = UIO_MX;
- dp->d_type = DT_UNKNOWN;
- dp->d_fileno = i + FD_DESC;
- break;
- }
- /*
- * And ship to userland
- */
- error = uiomove((caddr_t) dp, UIO_MX, uio);
- if (error)
- break;
- i++;
- fcnt++;
- }
-
-done:
- uio->uio_offset = i * UIO_MX;
- return (error);
-}
-
-static int
-fdesc_poll(ap)
- struct vop_poll_args /* {
- struct vnode *a_vp;
- int a_events;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- return seltrue(0, ap->a_events, ap->a_p);
-}
-
-static int
-fdesc_inactive(ap)
- struct vop_inactive_args /* {
- struct vnode *a_vp;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- /*
- * 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);
-}
-
-static int
-fdesc_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct fdescnode *fd = VTOFDESC(vp);
-
- LIST_REMOVE(fd, fd_hash);
- FREE(vp->v_data, M_TEMP);
- vp->v_data = 0;
-
- return (0);
-}
-
-/*
- * Print out the contents of a /dev/fd vnode.
- */
-/* ARGSUSED */
-static int
-fdesc_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- printf("tag VT_NON, fdesc vnode\n");
- return (0);
-}
-
-/*
- * /dev/fd "should never get here" operation
- */
-static int
-fdesc_badop()
-{
-
- panic("fdesc: bad op");
- /* NOTREACHED */
-}
-
-static struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) vop_null },
- { &vop_getattr_desc, (vop_t *) fdesc_getattr },
- { &vop_inactive_desc, (vop_t *) fdesc_inactive },
- { &vop_lookup_desc, (vop_t *) fdesc_lookup },
- { &vop_open_desc, (vop_t *) fdesc_open },
- { &vop_pathconf_desc, (vop_t *) vop_stdpathconf },
- { &vop_poll_desc, (vop_t *) fdesc_poll },
- { &vop_print_desc, (vop_t *) fdesc_print },
- { &vop_readdir_desc, (vop_t *) fdesc_readdir },
- { &vop_reclaim_desc, (vop_t *) fdesc_reclaim },
- { &vop_setattr_desc, (vop_t *) fdesc_setattr },
- { NULL, NULL }
-};
-static struct vnodeopv_desc fdesc_vnodeop_opv_desc =
- { &fdesc_vnodeop_p, fdesc_vnodeop_entries };
-
-VNODEOP_SET(fdesc_vnodeop_opv_desc);
diff --git a/sys/miscfs/fifofs/fifo.h b/sys/miscfs/fifofs/fifo.h
deleted file mode 100644
index e630207..0000000
--- a/sys/miscfs/fifofs/fifo.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fifo.h 8.6 (Berkeley) 5/21/95
- * $FreeBSD$
- */
-
-extern vop_t **fifo_vnodeop_p;
-
-/*
- * Prototypes for fifo operations on vnodes.
- */
-int fifo_vnoperate __P((struct vop_generic_args *));
-int fifo_printinfo __P((struct vnode *));
-
diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
deleted file mode 100644
index 3cd5425..0000000
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * 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
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)fifo_vnops.c 8.10 (Berkeley) 5/27/95
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/unistd.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/vnode.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/filio.h>
-#include <sys/fcntl.h>
-#include <sys/file.h>
-#include <sys/event.h>
-#include <sys/poll.h>
-#include <sys/un.h>
-#include <miscfs/fifofs/fifo.h>
-
-/*
- * This structure is associated with the FIFO vnode and stores
- * the state associated with the FIFO.
- */
-struct fifoinfo {
- struct socket *fi_readsock;
- struct socket *fi_writesock;
- long fi_readers;
- long fi_writers;
-};
-
-static int fifo_badop __P((void));
-static int fifo_print __P((struct vop_print_args *));
-static int fifo_lookup __P((struct vop_lookup_args *));
-static int fifo_open __P((struct vop_open_args *));
-static int fifo_close __P((struct vop_close_args *));
-static int fifo_read __P((struct vop_read_args *));
-static int fifo_write __P((struct vop_write_args *));
-static int fifo_ioctl __P((struct vop_ioctl_args *));
-static int fifo_poll __P((struct vop_poll_args *));
-static int fifo_kqfilter __P((struct vop_kqfilter_args *));
-static int fifo_pathconf __P((struct vop_pathconf_args *));
-static int fifo_advlock __P((struct vop_advlock_args *));
-
-static void filt_fifordetach(struct knote *kn);
-static int filt_fiforead(struct knote *kn, long hint);
-static void filt_fifowdetach(struct knote *kn);
-static int filt_fifowrite(struct knote *kn, long hint);
-
-static struct filterops fiforead_filtops =
- { 1, NULL, filt_fifordetach, filt_fiforead };
-static struct filterops fifowrite_filtops =
- { 1, NULL, filt_fifowdetach, filt_fifowrite };
-
-vop_t **fifo_vnodeop_p;
-static struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) vop_ebadf },
- { &vop_advlock_desc, (vop_t *) fifo_advlock },
- { &vop_close_desc, (vop_t *) fifo_close },
- { &vop_create_desc, (vop_t *) fifo_badop },
- { &vop_getattr_desc, (vop_t *) vop_ebadf },
- { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
- { &vop_ioctl_desc, (vop_t *) fifo_ioctl },
- { &vop_lease_desc, (vop_t *) vop_null },
- { &vop_link_desc, (vop_t *) fifo_badop },
- { &vop_lookup_desc, (vop_t *) fifo_lookup },
- { &vop_mkdir_desc, (vop_t *) fifo_badop },
- { &vop_mknod_desc, (vop_t *) fifo_badop },
- { &vop_open_desc, (vop_t *) fifo_open },
- { &vop_pathconf_desc, (vop_t *) fifo_pathconf },
- { &vop_poll_desc, (vop_t *) fifo_poll },
- { &vop_kqfilter_desc, (vop_t *) fifo_kqfilter },
- { &vop_print_desc, (vop_t *) fifo_print },
- { &vop_read_desc, (vop_t *) fifo_read },
- { &vop_readdir_desc, (vop_t *) fifo_badop },
- { &vop_readlink_desc, (vop_t *) fifo_badop },
- { &vop_reallocblks_desc, (vop_t *) fifo_badop },
- { &vop_reclaim_desc, (vop_t *) vop_null },
- { &vop_remove_desc, (vop_t *) fifo_badop },
- { &vop_rename_desc, (vop_t *) fifo_badop },
- { &vop_rmdir_desc, (vop_t *) fifo_badop },
- { &vop_setattr_desc, (vop_t *) vop_ebadf },
- { &vop_symlink_desc, (vop_t *) fifo_badop },
- { &vop_write_desc, (vop_t *) fifo_write },
- { NULL, NULL }
-};
-static struct vnodeopv_desc fifo_vnodeop_opv_desc =
- { &fifo_vnodeop_p, fifo_vnodeop_entries };
-
-VNODEOP_SET(fifo_vnodeop_opv_desc);
-
-int
-fifo_vnoperate(ap)
- struct vop_generic_args /* {
- struct vnodeop_desc *a_desc;
- <other random data follows, presumably>
- } */ *ap;
-{
- return (VOCALL(fifo_vnodeop_p, ap->a_desc->vdesc_offset, ap));
-}
-
-/*
- * Trivial lookup routine that always fails.
- */
-/* ARGSUSED */
-static int
-fifo_lookup(ap)
- struct vop_lookup_args /* {
- struct vnode * a_dvp;
- struct vnode ** a_vpp;
- struct componentname * a_cnp;
- } */ *ap;
-{
-
- *ap->a_vpp = NULL;
- return (ENOTDIR);
-}
-
-/*
- * Open called to set up a new instance of a fifo or
- * to find an active instance of a fifo.
- */
-/* ARGSUSED */
-static int
-fifo_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct fifoinfo *fip;
- struct proc *p = ap->a_p;
- struct socket *rso, *wso;
- int error;
-
- if ((fip = vp->v_fifoinfo) == NULL) {
- MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
- vp->v_fifoinfo = fip;
- 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_LOCAL, &wso, SOCK_STREAM, 0, ap->a_p);
- if (error) {
- (void)soclose(rso);
- free(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- return (error);
- }
- fip->fi_writesock = wso;
- error = unp_connect2(wso, rso);
- if (error) {
- (void)soclose(wso);
- (void)soclose(rso);
- free(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- return (error);
- }
- fip->fi_readers = fip->fi_writers = 0;
- wso->so_snd.sb_lowat = PIPE_BUF;
- rso->so_state |= SS_CANTRCVMORE;
- }
- 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 & 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);
- }
- }
- 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, "fifoor", 0);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (error)
- goto bad;
- }
- }
- 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, 0, p);
- error = tsleep((caddr_t)&fip->fi_writers,
- PCATCH | PSOCK, "fifoow", 0);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (error)
- goto bad;
- }
- }
- }
- return (0);
-bad:
- VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p);
- return (error);
-}
-
-/*
- * Vnode op for read
- */
-/* ARGSUSED */
-static int
-fifo_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- 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
- if (uio->uio_rw != UIO_READ)
- panic("fifo_read mode");
-#endif
- if (uio->uio_resid == 0)
- return (0);
- if (ap->a_ioflag & IO_NDELAY)
- rso->so_state |= SS_NBIO;
- startresid = uio->uio_resid;
- VOP_UNLOCK(ap->a_vp, 0, p);
- error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0,
- (struct mbuf **)0, (int *)0);
- vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (ap->a_ioflag & IO_NDELAY)
- rso->so_state &= ~SS_NBIO;
- return (error);
-}
-
-/*
- * Vnode op for write
- */
-/* ARGSUSED */
-static int
-fifo_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock;
- struct proc *p = ap->a_uio->uio_procp;
- int error;
-
-#ifdef DIAGNOSTIC
- if (ap->a_uio->uio_rw != UIO_WRITE)
- panic("fifo_write mode");
-#endif
- if (ap->a_ioflag & IO_NDELAY)
- wso->so_state |= SS_NBIO;
- VOP_UNLOCK(ap->a_vp, 0, p);
- error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0,
- (struct mbuf *)0, 0, p);
- vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (ap->a_ioflag & IO_NDELAY)
- wso->so_state &= ~SS_NBIO;
- return (error);
-}
-
-/*
- * Device ioctl operation.
- */
-/* ARGSUSED */
-static int
-fifo_ioctl(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;
-{
- struct file filetmp;
- int error;
-
- if (ap->a_command == FIONBIO)
- return (0);
- if (ap->a_fflag & FREAD) {
- filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- 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;
- error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p);
- if (error)
- return (error);
- }
- return (0);
-}
-
-/* ARGSUSED */
-static int
-fifo_kqfilter(ap)
- struct vop_kqfilter_args /* {
- struct vnode *a_vp;
- struct knote *a_kn;
- } */ *ap;
-{
- struct socket *so = (struct socket *)ap->a_vp->v_fifoinfo->fi_readsock;
- struct sockbuf *sb;
-
- switch (ap->a_kn->kn_filter) {
- case EVFILT_READ:
- ap->a_kn->kn_fop = &fiforead_filtops;
- sb = &so->so_rcv;
- break;
- case EVFILT_WRITE:
- ap->a_kn->kn_fop = &fifowrite_filtops;
- sb = &so->so_snd;
- break;
- default:
- return (1);
- }
-
- ap->a_kn->kn_hook = (caddr_t)so;
-
- SLIST_INSERT_HEAD(&sb->sb_sel.si_note, ap->a_kn, kn_selnext);
- sb->sb_flags |= SB_KNOTE;
-
- return (0);
-}
-
-static void
-filt_fifordetach(struct knote *kn)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext);
- if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note))
- so->so_rcv.sb_flags &= ~SB_KNOTE;
-}
-
-static int
-filt_fiforead(struct knote *kn, long hint)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- kn->kn_data = so->so_rcv.sb_cc;
- if (so->so_state & SS_CANTRCVMORE) {
- kn->kn_flags |= EV_EOF;
- return (1);
- }
- kn->kn_flags &= ~EV_EOF;
- return (kn->kn_data > 0);
-}
-
-static void
-filt_fifowdetach(struct knote *kn)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext);
- if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note))
- so->so_snd.sb_flags &= ~SB_KNOTE;
-}
-
-static int
-filt_fifowrite(struct knote *kn, long hint)
-{
- struct socket *so = (struct socket *)kn->kn_hook;
-
- kn->kn_data = sbspace(&so->so_snd);
- if (so->so_state & SS_CANTSENDMORE) {
- kn->kn_flags |= EV_EOF;
- return (1);
- }
- kn->kn_flags &= ~EV_EOF;
- return (kn->kn_data >= so->so_snd.sb_lowat);
-}
-
-/* ARGSUSED */
-static int
-fifo_poll(ap)
- struct vop_poll_args /* {
- struct vnode *a_vp;
- int a_events;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct file filetmp;
- int revents = 0;
-
- if (ap->a_events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
- filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock;
- if (filetmp.f_data)
- revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
- ap->a_p);
- }
- if (ap->a_events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
- filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock;
- if (filetmp.f_data)
- revents |= soo_poll(&filetmp, ap->a_events, ap->a_cred,
- ap->a_p);
- }
- return (revents);
-}
-
-/*
- * Device close routine
- */
-/* ARGSUSED */
-static int
-fifo_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct fifoinfo *fip = vp->v_fifoinfo;
- int error1, error2;
-
- 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);
- error2 = soclose(fip->fi_writesock);
- FREE(fip, M_VNODE);
- vp->v_fifoinfo = NULL;
- if (error1)
- return (error1);
- return (error2);
-}
-
-
-/*
- * Print out internal contents of a fifo vnode.
- */
-int
-fifo_printinfo(vp)
- struct vnode *vp;
-{
- register struct fifoinfo *fip = vp->v_fifoinfo;
-
- printf(", fifo with %ld readers and %ld writers",
- fip->fi_readers, fip->fi_writers);
- return (0);
-}
-
-/*
- * Print out the contents of a fifo vnode.
- */
-static int
-fifo_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- printf("tag VT_NON");
- fifo_printinfo(ap->a_vp);
- printf("\n");
- return (0);
-}
-
-/*
- * Return POSIX pathconf information applicable to fifo's.
- */
-int
-fifo_pathconf(ap)
- struct vop_pathconf_args /* {
- struct vnode *a_vp;
- int a_name;
- int *a_retval;
- } */ *ap;
-{
-
- switch (ap->a_name) {
- case _PC_LINK_MAX:
- *ap->a_retval = LINK_MAX;
- return (0);
- case _PC_PIPE_BUF:
- *ap->a_retval = PIPE_BUF;
- return (0);
- case _PC_CHOWN_RESTRICTED:
- *ap->a_retval = 1;
- return (0);
- default:
- return (EINVAL);
- }
- /* NOTREACHED */
-}
-
-/*
- * Fifo advisory byte-level locks.
- */
-/* ARGSUSED */
-static int
-fifo_advlock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
-{
-
- return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
-}
-
-/*
- * Fifo bad operation
- */
-static int
-fifo_badop()
-{
-
- panic("fifo_badop called");
- /* NOTREACHED */
-}
diff --git a/sys/miscfs/nullfs/null.h b/sys/miscfs/nullfs/null.h
deleted file mode 100644
index a5ebf87..0000000
--- a/sys/miscfs/nullfs/null.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)null.h 8.3 (Berkeley) 8/20/94
- *
- * $FreeBSD$
- */
-
-struct null_args {
- char *target; /* Target of loopback */
-};
-
-struct null_mount {
- struct mount *nullm_vfs;
- struct vnode *nullm_rootvp; /* Reference to root null_node */
-};
-
-#ifdef _KERNEL
-/*
- * A cache of vnode references
- */
-struct null_node {
- LIST_ENTRY(null_node) null_hash; /* Hash list */
- struct vnode *null_lowervp; /* VREFed once */
- struct vnode *null_vnode; /* Back pointer */
-};
-
-#define MOUNTTONULLMOUNT(mp) ((struct null_mount *)((mp)->mnt_data))
-#define VTONULL(vp) ((struct null_node *)(vp)->v_data)
-#define NULLTOV(xp) ((xp)->null_vnode)
-
-int nullfs_init(struct vfsconf *vfsp);
-int nullfs_uninit(struct vfsconf *vfsp);
-int null_node_create(struct mount *mp, struct vnode *target, struct vnode **vpp);
-int null_bypass(struct vop_generic_args *ap);
-
-#ifdef DIAGNOSTIC
-struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);
-#define NULLVPTOLOWERVP(vp) null_checkvp((vp), __FILE__, __LINE__)
-#else
-#define NULLVPTOLOWERVP(vp) (VTONULL(vp)->null_lowervp)
-#endif
-
-extern vop_t **null_vnodeop_p;
-extern struct lock null_hashlock;
-
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_NULLFSNODE);
-#endif
-
-#ifdef NULLFS_DEBUG
-#define NULLFSDEBUG(format, args...) printf(format ,## args)
-#else
-#define NULLFSDEBUG(format, args...)
-#endif /* NULLFS_DEBUG */
-
-#endif /* _KERNEL */
diff --git a/sys/miscfs/nullfs/null_subr.c b/sys/miscfs/nullfs/null_subr.c
deleted file mode 100644
index 88f1584..0000000
--- a/sys/miscfs/nullfs/null_subr.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)null_subr.c 8.7 (Berkeley) 5/14/95
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-
-#include <miscfs/nullfs/null.h>
-
-#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
-#define NNULLNODECACHE 16
-
-/*
- * Null layer cache:
- * Each cache entry holds a reference to the lower vnode
- * along with a pointer to the alias vnode. When an
- * entry is added the lower vnode is VREF'd. When the
- * alias is removed the lower vnode is vrele'd.
- */
-
-#define NULL_NHASH(vp) \
- (&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
-
-static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
-static u_long null_node_hash;
-struct lock null_hashlock;
-
-static MALLOC_DEFINE(M_NULLFSHASH, "NULLFS hash", "NULLFS hash table");
-MALLOC_DEFINE(M_NULLFSNODE, "NULLFS node", "NULLFS vnode private part");
-
-static int null_node_alloc(struct mount *mp, struct vnode *lowervp,
- struct vnode **vpp);
-static struct vnode *
- null_node_find(struct mount *mp, struct vnode *lowervp);
-
-/*
- * Initialise cache headers
- */
-int
-nullfs_init(vfsp)
- struct vfsconf *vfsp;
-{
-
- NULLFSDEBUG("nullfs_init\n"); /* printed during system boot */
- null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, &null_node_hash);
- lockinit(&null_hashlock, PVFS, "nullhs", 0, 0);
- return (0);
-}
-
-int
-nullfs_uninit(vfsp)
- struct vfsconf *vfsp;
-{
-
- if (null_node_hashtbl) {
- lockdestroy(&null_hashlock);
- free(null_node_hashtbl, M_NULLFSHASH);
- }
- return (0);
-}
-
-/*
- * Return a VREF'ed alias for lower vnode if already exists, else 0.
- * Lower vnode should be locked on entry and will be left locked on exit.
- */
-static struct vnode *
-null_node_find(mp, lowervp)
- struct mount *mp;
- struct vnode *lowervp;
-{
- struct proc *p = curproc; /* XXX */
- struct null_node_hashhead *hd;
- struct null_node *a;
- struct vnode *vp;
-
- /*
- * Find hash base, and then search the (two-way) linked
- * list looking for a null_node structure which is referencing
- * the lower vnode. If found, the increment the null_node
- * reference count (but NOT the lower vnode's VREF counter).
- */
- hd = NULL_NHASH(lowervp);
-loop:
- lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
- LIST_FOREACH(a, hd, null_hash) {
- if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
- vp = NULLTOV(a);
- lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
- /*
- * We need vget for the VXLOCK
- * stuff, but we don't want to lock
- * the lower node.
- */
- if (vget(vp, LK_EXCLUSIVE | LK_CANRECURSE, p)) {
- printf ("null_node_find: vget failed.\n");
- goto loop;
- };
- /*
- * Now we got both vnodes locked, so release the
- * lower one.
- */
- VOP_UNLOCK(lowervp, 0, p);
- return (vp);
- }
- }
- lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
-
- return NULLVP;
-}
-
-
-/*
- * Make a new null_node node.
- * Vp is the alias vnode, lofsvp is the lower vnode.
- * Maintain a reference to (lowervp).
- */
-static int
-null_node_alloc(mp, lowervp, vpp)
- struct mount *mp;
- struct vnode *lowervp;
- struct vnode **vpp;
-{
- struct proc *p = curproc; /* XXX */
- struct null_node_hashhead *hd;
- struct null_node *xp;
- struct vnode *othervp, *vp;
- int error;
-
- /*
- * 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(xp, struct null_node *, sizeof(struct null_node),
- M_NULLFSNODE, M_WAITOK);
-
- error = getnewvnode(VT_NULL, mp, null_vnodeop_p, vpp);
- if (error) {
- FREE(xp, M_NULLFSNODE);
- return (error);
- }
- vp = *vpp;
-
- vp->v_type = lowervp->v_type;
- xp->null_vnode = vp;
- vp->v_data = xp;
- xp->null_lowervp = lowervp;
- /*
- * Before we insert our new node onto the hash chains,
- * check to see if someone else has beaten us to it.
- * (We could have slept in MALLOC.)
- */
- othervp = null_node_find(mp, lowervp);
- if (othervp) {
- vp->v_data = NULL;
- FREE(xp, M_NULLFSNODE);
- vp->v_type = VBAD; /* node is discarded */
- vrele(vp);
- *vpp = othervp;
- return 0;
- };
-
- /*
- * From NetBSD:
- * Now lock the new node. We rely on the fact that we were passed
- * a locked vnode. If the lower node is exporting a struct lock
- * (v_vnlock != NULL) then we just set the upper v_vnlock to the
- * lower one, and both are now locked. If the lower node is exporting
- * NULL, then we copy that up and manually lock the new vnode.
- */
-
- lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
- vp->v_vnlock = lowervp->v_vnlock;
- error = VOP_LOCK(vp, LK_EXCLUSIVE | LK_THISLAYER, p);
- if (error)
- panic("null_node_alloc: can't lock new vnode\n");
-
- VREF(lowervp);
- hd = NULL_NHASH(lowervp);
- LIST_INSERT_HEAD(hd, xp, null_hash);
- lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
- return 0;
-}
-
-
-/*
- * Try to find an existing null_node vnode refering to the given underlying
- * vnode (which should be locked). If no vnode found, create a new null_node
- * vnode which contains a reference to the lower vnode.
- */
-int
-null_node_create(mp, lowervp, newvpp)
- struct mount *mp;
- struct vnode *lowervp;
- struct vnode **newvpp;
-{
- struct vnode *aliasvp;
-
- aliasvp = null_node_find(mp, lowervp);
- if (aliasvp) {
- /*
- * null_node_find has taken another reference
- * to the alias vnode.
- */
- vrele(lowervp);
-#ifdef NULLFS_DEBUG
- vprint("null_node_create: exists", aliasvp);
-#endif
- } else {
- int error;
-
- /*
- * Get new vnode.
- */
- NULLFSDEBUG("null_node_create: create new alias vnode\n");
-
- /*
- * Make new vnode reference the null_node.
- */
- error = null_node_alloc(mp, lowervp, &aliasvp);
- if (error)
- return error;
-
- /*
- * aliasvp is already VREF'd by getnewvnode()
- */
- }
-
-#ifdef DIAGNOSTIC
- if (lowervp->v_usecount < 1) {
- /* Should never happen... */
- vprint ("null_node_create: alias ", aliasvp);
- vprint ("null_node_create: lower ", lowervp);
- panic ("null_node_create: lower has 0 usecount.");
- };
-#endif
-
-#ifdef NULLFS_DEBUG
- vprint("null_node_create: alias", aliasvp);
- vprint("null_node_create: lower", lowervp);
-#endif
-
- *newvpp = aliasvp;
- return (0);
-}
-
-#ifdef DIAGNOSTIC
-#include "opt_ddb.h"
-
-#ifdef DDB
-#define null_checkvp_barrier 1
-#else
-#define null_checkvp_barrier 0
-#endif
-
-struct vnode *
-null_checkvp(vp, fil, lno)
- struct vnode *vp;
- char *fil;
- int lno;
-{
- struct null_node *a = VTONULL(vp);
-#ifdef notyet
- /*
- * Can't do this check because vop_reclaim runs
- * with a funny vop vector.
- */
- if (vp->v_op != null_vnodeop_p) {
- printf ("null_checkvp: on non-null-node\n");
- while (null_checkvp_barrier) /*WAIT*/ ;
- panic("null_checkvp");
- };
-#endif
- if (a->null_lowervp == NULLVP) {
- /* Should never happen */
- int i; u_long *p;
- printf("vp = %p, ZERO ptr\n", (void *)vp);
- for (p = (u_long *) a, i = 0; i < 8; i++)
- printf(" %lx", p[i]);
- printf("\n");
- /* wait for debugger */
- while (null_checkvp_barrier) /*WAIT*/ ;
- panic("null_checkvp");
- }
- if (a->null_lowervp->v_usecount < 1) {
- int i; u_long *p;
- printf("vp = %p, unref'ed lowervp\n", (void *)vp);
- for (p = (u_long *) a, i = 0; i < 8; i++)
- printf(" %lx", p[i]);
- printf("\n");
- /* wait for debugger */
- while (null_checkvp_barrier) /*WAIT*/ ;
- panic ("null with unref'ed lowervp");
- };
-#ifdef notyet
- printf("null %x/%d -> %x/%d [%s, %d]\n",
- NULLTOV(a), NULLTOV(a)->v_usecount,
- a->null_lowervp, a->null_lowervp->v_usecount,
- fil, lno);
-#endif
- return a->null_lowervp;
-}
-#endif
diff --git a/sys/miscfs/nullfs/null_vfsops.c b/sys/miscfs/nullfs/null_vfsops.c
deleted file mode 100644
index 8573398..0000000
--- a/sys/miscfs/nullfs/null_vfsops.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * 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
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)null_vfsops.c 8.2 (Berkeley) 1/21/94
- *
- * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92
- * $FreeBSD$
- */
-
-/*
- * Null Layer
- * (See null_vnops.c for a description of what this does.)
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-
-#include <miscfs/nullfs/null.h>
-
-static MALLOC_DEFINE(M_NULLFSMNT, "NULLFS mount", "NULLFS mount structure");
-
-static int nullfs_fhtovp(struct mount *mp, struct fid *fidp,
- struct vnode **vpp);
-static int nullfs_checkexp(struct mount *mp, struct sockaddr *nam,
- int *extflagsp, struct ucred **credanonp);
-static int nullfs_mount(struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, struct proc *p);
-static int nullfs_quotactl(struct mount *mp, int cmd, uid_t uid,
- caddr_t arg, struct proc *p);
-static int nullfs_root(struct mount *mp, struct vnode **vpp);
-static int nullfs_start(struct mount *mp, int flags, struct proc *p);
-static int nullfs_statfs(struct mount *mp, struct statfs *sbp,
- struct proc *p);
-static int nullfs_sync(struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p);
-static int nullfs_unmount(struct mount *mp, int mntflags, struct proc *p);
-static int nullfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp);
-static int nullfs_vptofh(struct vnode *vp, struct fid *fhp);
-static int nullfs_extattrctl(struct mount *mp, int cmd,
- struct vnode *filename_vp,
- int namespace, const char *attrname,
- struct proc *p);
-
-/*
- * Mount null layer
- */
-static int
-nullfs_mount(mp, path, data, ndp, p)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct proc *p;
-{
- int error = 0;
- struct null_args args;
- struct vnode *lowerrootvp, *vp;
- struct vnode *nullm_rootvp;
- struct null_mount *xmp;
- u_int size;
- int isvnunlocked = 0;
-
- NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
-
- /*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- return (EOPNOTSUPP);
- /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, path, data, ndp, p);*/
- }
-
- /*
- * Get argument
- */
- error = copyin(data, (caddr_t)&args, sizeof(struct null_args));
- if (error)
- return (error);
-
- /*
- * Unlock lower node to avoid deadlock.
- * (XXX) VOP_ISLOCKED is needed?
- */
- if ((mp->mnt_vnodecovered->v_op == null_vnodeop_p) &&
- VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) {
- VOP_UNLOCK(mp->mnt_vnodecovered, 0, p);
- isvnunlocked = 1;
- }
- /*
- * Find lower node
- */
- NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
- UIO_USERSPACE, args.target, p);
- error = namei(ndp);
- /*
- * Re-lock vnode.
- */
- if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered, NULL))
- vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, p);
-
- if (error)
- return (error);
- NDFREE(ndp, NDF_ONLY_PNBUF);
-
- /*
- * Sanity check on lower vnode
- */
- lowerrootvp = ndp->ni_vp;
-
- vrele(ndp->ni_dvp);
- ndp->ni_dvp = NULLVP;
-
- /*
- * Check multi null mount to avoid `lock against myself' panic.
- */
- if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
- NULLFSDEBUG("nullfs_mount: multi null mount?\n");
- vput(lowerrootvp);
- return (EDEADLK);
- }
-
- xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
- M_NULLFSMNT, M_WAITOK); /* XXX */
-
- /*
- * Save reference to underlying FS
- */
- xmp->nullm_vfs = lowerrootvp->v_mount;
-
- /*
- * Save reference. Each mount also holds
- * a reference on the root vnode.
- */
- error = null_node_create(mp, lowerrootvp, &vp);
- /*
- * Unlock the node (either the lower or the alias)
- */
- VOP_UNLOCK(vp, 0, p);
- /*
- * Make sure the node alias worked
- */
- if (error) {
- vrele(lowerrootvp);
- free(xmp, M_NULLFSMNT); /* XXX */
- return (error);
- }
-
- /*
- * Keep a held reference to the root vnode.
- * It is vrele'd in nullfs_unmount.
- */
- nullm_rootvp = vp;
- nullm_rootvp->v_flag |= VROOT;
- xmp->nullm_rootvp = nullm_rootvp;
- if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
- mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_data = (qaddr_t) xmp;
- vfs_getnewfsid(mp);
-
- (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
- &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
- (void)nullfs_statfs(mp, &mp->mnt_stat, p);
- NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
- mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
- return (0);
-}
-
-/*
- * VFS start. Nothing needed here - the start routine
- * on the underlying filesystem will have been called
- * when that filesystem was mounted.
- */
-static int
-nullfs_start(mp, flags, p)
- struct mount *mp;
- int flags;
- struct proc *p;
-{
- return (0);
- /* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, p); */
-}
-
-/*
- * Free reference to null layer
- */
-static int
-nullfs_unmount(mp, mntflags, p)
- struct mount *mp;
- int mntflags;
- struct proc *p;
-{
- void *mntdata;
- int error;
- int flags = 0;
-
- NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp);
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
-
- /* There is 1 extra root vnode reference (nullm_rootvp). */
- error = vflush(mp, 1, flags);
- if (error)
- return (error);
-
- /*
- * Finally, throw away the null_mount structure
- */
- mntdata = mp->mnt_data;
- mp->mnt_data = 0;
- free(mntdata, M_NULLFSMNT);
- return 0;
-}
-
-static int
-nullfs_root(mp, vpp)
- struct mount *mp;
- struct vnode **vpp;
-{
- struct proc *p = curproc; /* XXX */
- struct vnode *vp;
-
- NULLFSDEBUG("nullfs_root(mp = %p, vp = %p->%p)\n", (void *)mp,
- (void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
- (void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
-
- /*
- * Return locked reference to root.
- */
- vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
- VREF(vp);
-
-#ifdef NULLFS_DEBUG
- if (VOP_ISLOCKED(vp, NULL)) {
- Debugger("root vnode is locked.\n");
- vrele(vp);
- return (EDEADLK);
- }
-#endif
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- *vpp = vp;
- return 0;
-}
-
-static int
-nullfs_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
- return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg, p);
-}
-
-static int
-nullfs_statfs(mp, sbp, p)
- struct mount *mp;
- struct statfs *sbp;
- struct proc *p;
-{
- int error;
- struct statfs mstat;
-
- NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
- (void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
- (void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
-
- bzero(&mstat, sizeof(mstat));
-
- error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, &mstat, p);
- if (error)
- return (error);
-
- /* now copy across the "interesting" information and fake the rest */
- sbp->f_type = mstat.f_type;
- sbp->f_flags = mstat.f_flags;
- sbp->f_bsize = mstat.f_bsize;
- sbp->f_iosize = mstat.f_iosize;
- sbp->f_blocks = mstat.f_blocks;
- sbp->f_bfree = mstat.f_bfree;
- sbp->f_bavail = mstat.f_bavail;
- sbp->f_files = mstat.f_files;
- sbp->f_ffree = mstat.f_ffree;
- if (sbp != &mp->mnt_stat) {
- bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
- bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
- bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
- }
- return (0);
-}
-
-static int
-nullfs_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
- /*
- * XXX - Assumes no data cached at null layer.
- */
- return (0);
-}
-
-static int
-nullfs_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
- int error;
- error = VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp);
- if (error)
- return (error);
-
- return (null_node_create(mp, *vpp, vpp));
-}
-
-static int
-nullfs_fhtovp(mp, fidp, vpp)
- struct mount *mp;
- struct fid *fidp;
- struct vnode **vpp;
-{
- int error;
- error = VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, vpp);
- if (error)
- return (error);
-
- return (null_node_create(mp, *vpp, vpp));
-}
-
-static int
-nullfs_checkexp(mp, nam, extflagsp, credanonp)
- struct mount *mp;
- struct sockaddr *nam;
- int *extflagsp;
- struct ucred **credanonp;
-{
-
- return VFS_CHECKEXP(MOUNTTONULLMOUNT(mp)->nullm_vfs, nam,
- extflagsp, credanonp);
-}
-
-static int
-nullfs_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
- return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhp);
-}
-
-static int
-nullfs_extattrctl(mp, cmd, filename_vp, namespace, attrname, p)
- struct mount *mp;
- int cmd;
- struct vnode *filename_vp;
- int namespace;
- const char *attrname;
- struct proc *p;
-{
- return VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, filename_vp,
- namespace, attrname, p);
-}
-
-
-static struct vfsops null_vfsops = {
- nullfs_mount,
- nullfs_start,
- nullfs_unmount,
- nullfs_root,
- nullfs_quotactl,
- nullfs_statfs,
- nullfs_sync,
- nullfs_vget,
- nullfs_fhtovp,
- nullfs_checkexp,
- nullfs_vptofh,
- nullfs_init,
- nullfs_uninit,
- nullfs_extattrctl,
-};
-
-VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK);
diff --git a/sys/miscfs/nullfs/null_vnops.c b/sys/miscfs/nullfs/null_vnops.c
deleted file mode 100644
index d37ef73..0000000
--- a/sys/miscfs/nullfs/null_vnops.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * John Heidemann of the UCLA Ficus project.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95
- *
- * Ancestors:
- * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
- * ...and...
- * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
- *
- * $FreeBSD$
- */
-
-/*
- * Null Layer
- *
- * (See mount_null(8) for more information.)
- *
- * The null layer duplicates a portion of the file system
- * name space under a new name. In this respect, it is
- * similar to the loopback file system. It differs from
- * the loopback fs in two respects: it is implemented using
- * a stackable layers techniques, and its "null-node"s stack above
- * all lower-layer vnodes, not just over directory vnodes.
- *
- * The null layer has two purposes. First, it serves as a demonstration
- * of layering by proving a layer which does nothing. (It actually
- * does everything the loopback file system does, which is slightly
- * more than nothing.) Second, the null layer can serve as a prototype
- * layer. Since it provides all necessary layer framework,
- * new file system layers can be created very easily be starting
- * with a null layer.
- *
- * The remainder of this man page examines the null layer as a basis
- * for constructing new layers.
- *
- *
- * INSTANTIATING NEW NULL LAYERS
- *
- * New null layers are created with mount_null(8).
- * Mount_null(8) takes two arguments, the pathname
- * of the lower vfs (target-pn) and the pathname where the null
- * layer will appear in the namespace (alias-pn). After
- * the null layer is put into place, the contents
- * of target-pn subtree will be aliased under alias-pn.
- *
- *
- * OPERATION OF A NULL LAYER
- *
- * The null layer is the minimum file system layer,
- * simply bypassing all possible operations to the lower layer
- * for processing there. The majority of its activity centers
- * on the bypass routine, through which nearly all vnode operations
- * pass.
- *
- * The bypass routine accepts arbitrary vnode operations for
- * handling by the lower layer. It begins by examing vnode
- * operation arguments and replacing any null-nodes by their
- * lower-layer equivlants. It then invokes the operation
- * on the lower layer. Finally, it replaces the null-nodes
- * 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, 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.
- * 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
- *
- * Mounting associates the null layer with a lower layer,
- * effect stacking two VFSes. Vnode stacks are instead
- * created on demand as files are accessed.
- *
- * The initial mount creates a single vnode stack for the
- * root of the new null layer. All other vnode stacks
- * are created as a result of vnode operations on
- * this or other null vnode stacks.
- *
- * New vnode stacks come into existance as a result of
- * an operation which returns a vnode.
- * The bypass routine stacks a null-node above the new
- * vnode before returning it to the caller.
- *
- * For example, imagine mounting a null layer with
- * "mount_null /usr/include /dev/layer/null".
- * Changing directory to /dev/layer/null will assign
- * the root null-node (which was created when the null layer was mounted).
- * Now consider opening "sys". A vop_lookup would be
- * done on the root null-node. This operation would bypass through
- * to the lower layer which would return a vnode representing
- * the UFS "sys". Null_bypass then builds a null-node
- * aliasing the UFS "sys" and returns this to the caller.
- * Later operations on the null-node "sys" will repeat this
- * process when constructing other vnode stacks.
- *
- *
- * CREATING OTHER FILE SYSTEM LAYERS
- *
- * One of the easiest ways to construct new file system layers is to make
- * a copy of the null layer, rename all files and variables, and
- * then begin modifing the copy. Sed can be used to easily rename
- * all variables.
- *
- * The umap layer is an example of a layer descended from the
- * null layer.
- *
- *
- * INVOKING OPERATIONS ON LOWER LAYERS
- *
- * There are two techniques to invoke operations on a lower layer
- * when the operation cannot be completely bypassed. Each method
- * is appropriate in different situations. In both cases,
- * it is the responsibility of the aliasing layer to make
- * the operation arguments "correct" for the lower layer
- * by mapping an vnode arguments to the lower layer.
- *
- * The first approach is to call the aliasing layer's bypass routine.
- * This method is most suitable when you wish to invoke the operation
- * currently being handled on the lower layer. It has the advantage
- * that the bypass routine already must do argument mapping.
- * An example of this is null_getattrs in the null layer.
- *
- * A second approach is to directly invoke vnode operations on
- * the lower layer with the VOP_OPERATIONNAME interface.
- * The advantage of this method is that it is easy to invoke
- * arbitrary operations on the lower layer. The disadvantage
- * is that vnode arguments must be manualy mapped.
- *
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-
-#include <miscfs/nullfs/null.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_object.h>
-#include <vm/vnode_pager.h>
-
-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_access(struct vop_access_args *ap);
-static int null_createvobject(struct vop_createvobject_args *ap);
-static int null_destroyvobject(struct vop_destroyvobject_args *ap);
-static int null_getattr(struct vop_getattr_args *ap);
-static int null_getvobject(struct vop_getvobject_args *ap);
-static int null_inactive(struct vop_inactive_args *ap);
-static int null_islocked(struct vop_islocked_args *ap);
-static int null_lock(struct vop_lock_args *ap);
-static int null_lookup(struct vop_lookup_args *ap);
-static int null_open(struct vop_open_args *ap);
-static int null_print(struct vop_print_args *ap);
-static int null_reclaim(struct vop_reclaim_args *ap);
-static int null_rename(struct vop_rename_args *ap);
-static int null_setattr(struct vop_setattr_args *ap);
-static int null_unlock(struct vop_unlock_args *ap);
-
-/*
- * This is the 10-Apr-92 bypass routine.
- * This version has been optimized for speed, throwing away some
- * safety checks. It should still always work, but it's not as
- * robust to programmer errors.
- *
- * In general, we map all vnodes going down and unmap them on the way back.
- * As an exception to this, vnodes can be marked "unmapped" by setting
- * the Nth bit in operation's vdesc_flags.
- *
- * Also, some BSD vnode operations have the side effect of vrele'ing
- * their arguments. With stacking, the reference counts are held
- * by the upper node, not the lower one, so we must handle these
- * side-effects here. This is not of concern in Sun-derived systems
- * since there are no such side-effects.
- *
- * This makes the following assumptions:
- * - only one returned vpp
- * - no INOUT vpp's (Sun's vop_open has one of these)
- * - the vnode operation vector of the first vnode should be used
- * to determine what implementation of the op should be invoked
- * - all mapped vnodes are of our vnode-type (NEEDSWORK:
- * problems on rmdir'ing mount points and renaming?)
- */
-int
-null_bypass(ap)
- struct vop_generic_args /* {
- struct vnodeop_desc *a_desc;
- <other random data follows, presumably>
- } */ *ap;
-{
- register struct vnode **this_vp_p;
- int error;
- struct vnode *old_vps[VDESC_MAX_VPS];
- struct vnode **vps_p[VDESC_MAX_VPS];
- struct vnode ***vppp;
- struct vnodeop_desc *descp = ap->a_desc;
- int reles, i;
-
- if (null_bug_bypass)
- printf ("null_bypass: %s\n", descp->vdesc_name);
-
-#ifdef DIAGNOSTIC
- /*
- * We require at least one vp.
- */
- if (descp->vdesc_vp_offsets == NULL ||
- descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
- panic ("null_bypass: no vp's in map");
-#endif
-
- /*
- * Map the vnodes going in.
- * Later, we'll invoke the operation based on
- * the first mapped vnode's operation vector.
- */
- reles = descp->vdesc_flags;
- for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
- if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
- break; /* bail out at end of list */
- vps_p[i] = this_vp_p =
- VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[i],ap);
- /*
- * We're not guaranteed that any but the first vnode
- * are of our type. Check for and don't map any
- * that aren't. (We must always map first vp or vclean fails.)
- */
- if (i && (*this_vp_p == NULLVP ||
- (*this_vp_p)->v_op != null_vnodeop_p)) {
- old_vps[i] = NULLVP;
- } else {
- old_vps[i] = *this_vp_p;
- *(vps_p[i]) = NULLVPTOLOWERVP(*this_vp_p);
- /*
- * XXX - Several operations have the side effect
- * of vrele'ing their vp's. We must account for
- * that. (This should go away in the future.)
- */
- if (reles & VDESC_VP0_WILLRELE)
- VREF(*this_vp_p);
- }
-
- }
-
- /*
- * Call the operation on the lower layer
- * with the modified argument structure.
- */
- if (vps_p[0] && *vps_p[0])
- error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
- else {
- printf("null_bypass: no map for %s\n", descp->vdesc_name);
- error = EINVAL;
- }
-
- /*
- * Maintain the illusion of call-by-value
- * by restoring vnodes in the argument structure
- * to their original value.
- */
- reles = descp->vdesc_flags;
- for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
- if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
- break; /* bail out at end of list */
- if (old_vps[i]) {
- *(vps_p[i]) = old_vps[i];
-#if 0
- if (reles & VDESC_VP0_WILLUNLOCK)
- VOP_UNLOCK(*(vps_p[i]), LK_THISLAYER, curproc);
-#endif
- if (reles & VDESC_VP0_WILLRELE)
- vrele(*(vps_p[i]));
- }
- }
-
- /*
- * Map the possible out-going vpp
- * (Assumes that the lower layer always returns
- * a VREF'ed vpp unless it gets an error.)
- */
- if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
- !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
- !error) {
- /*
- * XXX - even though some ops have vpp returned vp's,
- * several ops actually vrele this before returning.
- * We must avoid these ops.
- * (This should go away when these ops are regularized.)
- */
- if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
- goto out;
- vppp = VOPARG_OFFSETTO(struct vnode***,
- descp->vdesc_vpp_offset,ap);
- if (*vppp)
- error = null_node_create(old_vps[0]->v_mount, **vppp, *vppp);
- }
-
- out:
- 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 vnode *dvp = ap->a_dvp;
- struct proc *p = cnp->cn_proc;
- int flags = cnp->cn_flags;
- struct vnode *vp, *ldvp, *lvp;
- int error;
-
- if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
- (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
- return (EROFS);
- /*
- * Although it is possible to call null_bypass(), we'll do
- * a direct call to reduce overhead
- */
- ldvp = NULLVPTOLOWERVP(dvp);
- vp = lvp = NULL;
- error = VOP_LOOKUP(ldvp, &lvp, cnp);
- if (error == EJUSTRETURN && (flags & ISLASTCN) &&
- (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
- (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
- error = EROFS;
-
- /*
- * Rely only on the PDIRUNLOCK flag which should be carefully
- * tracked by underlying filesystem.
- */
- if (cnp->cn_flags & PDIRUNLOCK)
- VOP_UNLOCK(dvp, LK_THISLAYER, p);
- if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {
- if (ldvp == lvp) {
- *ap->a_vpp = dvp;
- VREF(dvp);
- vrele(lvp);
- } else {
- error = null_node_create(dvp->v_mount, lvp, &vp);
- if (error == 0)
- *ap->a_vpp = vp;
- }
- }
- 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.tv_sec != VNOVAL ||
- vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
- (vp->v_mount->mnt_flag & MNT_RDONLY))
- return (EROFS);
- if (vap->va_size != VNOVAL) {
- switch (vp->v_type) {
- case VDIR:
- return (EISDIR);
- case VCHR:
- case VBLK:
- case VSOCK:
- case VFIFO:
- if (vap->va_flags != VNOVAL)
- return (EOPNOTSUPP);
- 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((struct vop_generic_args *)ap));
-}
-
-/*
- * We handle getattr only to change the fsid.
- */
-static int
-null_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- int error;
-
- if ((error = null_bypass((struct vop_generic_args *)ap)) != 0)
- return (error);
-
- ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
- return (0);
-}
-
-/*
- * Handle to disallow write access if mounted read-only.
- */
-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;
- default:
- break;
- }
- }
- return (null_bypass((struct vop_generic_args *)ap));
-}
-
-/*
- * We must handle open to be able to catch MNT_NODEV and friends.
- */
-static int
-null_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *lvp = NULLVPTOLOWERVP(ap->a_vp);
-
- if ((vp->v_mount->mnt_flag & MNT_NODEV) &&
- (lvp->v_type == VBLK || lvp->v_type == VCHR))
- return ENXIO;
-
- return (null_bypass((struct vop_generic_args *)ap));
-}
-
-/*
- * We handle this to eliminate null FS to lower FS
- * file moving. Don't know why we don't allow this,
- * possibly we should.
- */
-static int
-null_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
-{
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *fvp = ap->a_fvp;
- struct vnode *fdvp = ap->a_fdvp;
- struct vnode *tvp = ap->a_tvp;
-
- /* Check for cross-device rename. */
- if ((fvp->v_mount != tdvp->v_mount) ||
- (tvp && (fvp->v_mount != tvp->v_mount))) {
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return (EXDEV);
- }
-
- return (null_bypass((struct vop_generic_args *)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.
- */
-static int
-null_lock(ap)
- struct vop_lock_args /* {
- struct vnode *a_vp;
- int a_flags;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- int flags = ap->a_flags;
- struct proc *p = ap->a_p;
- struct vnode *lvp;
- int error;
-
- if (flags & LK_THISLAYER) {
- if (vp->v_vnlock != NULL)
- return 0; /* lock is shared across layers */
- error = lockmgr(&vp->v_lock, flags & ~LK_THISLAYER,
- &vp->v_interlock, p);
- return (error);
- }
-
- if (vp->v_vnlock != NULL) {
- /*
- * The lower level has exported a struct lock to us. Use
- * it so that all vnodes in the stack lock and unlock
- * simultaneously. Note: we don't DRAIN the lock as DRAIN
- * decommissions the lock - just because our vnode is
- * going away doesn't mean the struct lock below us is.
- * LK_EXCLUSIVE is fine.
- */
- if ((flags & LK_TYPE_MASK) == LK_DRAIN) {
- NULLFSDEBUG("null_lock: avoiding LK_DRAIN\n");
- return(lockmgr(vp->v_vnlock,
- (flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE,
- &vp->v_interlock, p));
- }
- return(lockmgr(vp->v_vnlock, flags, &vp->v_interlock, p));
- } else {
- /*
- * To prevent race conditions involving doing a lookup
- * on "..", we have to lock the lower node, then lock our
- * node. Most of the time it won't matter that we lock our
- * node (as any locking would need the lower one locked
- * first). But we can LK_DRAIN the upper lock as a step
- * towards decomissioning it.
- */
- lvp = NULLVPTOLOWERVP(vp);
- if (lvp == NULL)
- return (lockmgr(&vp->v_lock, flags, &vp->v_interlock, p));
- if (flags & LK_INTERLOCK) {
- mtx_unlock(&vp->v_interlock);
- flags &= ~LK_INTERLOCK;
- }
- if ((flags & LK_TYPE_MASK) == LK_DRAIN) {
- error = VOP_LOCK(lvp,
- (flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE, p);
- } else
- error = VOP_LOCK(lvp, flags, p);
- if (error)
- return (error);
- error = lockmgr(&vp->v_lock, flags, &vp->v_interlock, p);
- if (error)
- VOP_UNLOCK(lvp, 0, p);
- return (error);
- }
-}
-
-/*
- * 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.
- */
-static 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;
- int flags = ap->a_flags;
- struct proc *p = ap->a_p;
- struct vnode *lvp;
-
- if (vp->v_vnlock != NULL) {
- if (flags & LK_THISLAYER)
- return 0; /* the lock is shared across layers */
- flags &= ~LK_THISLAYER;
- return (lockmgr(vp->v_vnlock, flags | LK_RELEASE,
- &vp->v_interlock, p));
- }
- lvp = NULLVPTOLOWERVP(vp);
- if (lvp == NULL)
- return (lockmgr(&vp->v_lock, flags | LK_RELEASE, &vp->v_interlock, p));
- if ((flags & LK_THISLAYER) == 0) {
- if (flags & LK_INTERLOCK) {
- mtx_unlock(&vp->v_interlock);
- flags &= ~LK_INTERLOCK;
- }
- VOP_UNLOCK(lvp, flags & ~LK_INTERLOCK, p);
- } else
- flags &= ~LK_THISLAYER;
- return (lockmgr(&vp->v_lock, flags | LK_RELEASE, &vp->v_interlock, p));
-}
-
-static int
-null_islocked(ap)
- struct vop_islocked_args /* {
- struct vnode *a_vp;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct proc *p = ap->a_p;
-
- if (vp->v_vnlock != NULL)
- return (lockstatus(vp->v_vnlock, p));
- return (lockstatus(&vp->v_lock, p));
-}
-
-/*
- * There is no way to tell that someone issued remove/rmdir operation
- * on the underlying filesystem. For now we just have to release lowevrp
- * as soon as possible.
- */
-static int
-null_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 null_node *xp = VTONULL(vp);
- struct vnode *lowervp = xp->null_lowervp;
-
- lockmgr(&null_hashlock, LK_EXCLUSIVE, NULL, p);
- LIST_REMOVE(xp, null_hash);
- lockmgr(&null_hashlock, LK_RELEASE, NULL, p);
-
- xp->null_lowervp = NULLVP;
- if (vp->v_vnlock != NULL) {
- vp->v_vnlock = &vp->v_lock; /* we no longer share the lock */
- } else
- VOP_UNLOCK(vp, LK_THISLAYER, p);
-
- vput(lowervp);
- /*
- * Now it is safe to drop references to the lower vnode.
- * VOP_INACTIVE() will be called by vrele() if necessary.
- */
- vrele (lowervp);
-
- return (0);
-}
-
-/*
- * We can free memory in null_inactive, but we do this
- * here. (Possible to guard vp->v_data to point somewhere)
- */
-static int
-null_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- void *vdata = vp->v_data;
-
- vp->v_data = NULL;
- FREE(vdata, M_NULLFSNODE);
-
- return (0);
-}
-
-static int
-null_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- printf ("\ttag VT_NULLFS, vp=%p, lowervp=%p\n", vp, NULLVPTOLOWERVP(vp));
- return (0);
-}
-
-/*
- * Let an underlying filesystem do the work
- */
-static int
-null_createvobject(ap)
- struct vop_createvobject_args /* {
- struct vnode *vp;
- struct ucred *cred;
- struct proc *p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *lowervp = VTONULL(vp) ? NULLVPTOLOWERVP(vp) : NULL;
- int error;
-
- if (vp->v_type == VNON || lowervp == NULL)
- return 0;
- error = VOP_CREATEVOBJECT(lowervp, ap->a_cred, ap->a_p);
- if (error)
- return (error);
- vp->v_flag |= VOBJBUF;
- return (0);
-}
-
-/*
- * We have nothing to destroy and this operation shouldn't be bypassed.
- */
-static int
-null_destroyvobject(ap)
- struct vop_destroyvobject_args /* {
- struct vnode *vp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- vp->v_flag &= ~VOBJBUF;
- return (0);
-}
-
-static int
-null_getvobject(ap)
- struct vop_getvobject_args /* {
- struct vnode *vp;
- struct vm_object **objpp;
- } */ *ap;
-{
- struct vnode *lvp = NULLVPTOLOWERVP(ap->a_vp);
-
- if (lvp == NULL)
- return EINVAL;
- return (VOP_GETVOBJECT(lvp, ap->a_objpp));
-}
-
-/*
- * Global vfs data structures
- */
-vop_t **null_vnodeop_p;
-static struct vnodeopv_entry_desc null_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) null_bypass },
-
- { &vop_access_desc, (vop_t *) null_access },
- { &vop_bmap_desc, (vop_t *) vop_eopnotsupp },
- { &vop_createvobject_desc, (vop_t *) null_createvobject },
- { &vop_destroyvobject_desc, (vop_t *) null_destroyvobject },
- { &vop_getattr_desc, (vop_t *) null_getattr },
- { &vop_getvobject_desc, (vop_t *) null_getvobject },
- { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount},
- { &vop_inactive_desc, (vop_t *) null_inactive },
- { &vop_islocked_desc, (vop_t *) null_islocked },
- { &vop_lock_desc, (vop_t *) null_lock },
- { &vop_lookup_desc, (vop_t *) null_lookup },
- { &vop_open_desc, (vop_t *) null_open },
- { &vop_print_desc, (vop_t *) null_print },
- { &vop_reclaim_desc, (vop_t *) null_reclaim },
- { &vop_rename_desc, (vop_t *) null_rename },
- { &vop_setattr_desc, (vop_t *) null_setattr },
- { &vop_strategy_desc, (vop_t *) vop_eopnotsupp },
- { &vop_unlock_desc, (vop_t *) null_unlock },
- { NULL, NULL }
-};
-static struct vnodeopv_desc null_vnodeop_opv_desc =
- { &null_vnodeop_p, null_vnodeop_entries };
-
-VNODEOP_SET(null_vnodeop_opv_desc);
diff --git a/sys/miscfs/portal/portal.h b/sys/miscfs/portal/portal.h
deleted file mode 100644
index ec46662..0000000
--- a/sys/miscfs/portal/portal.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)portal.h 8.4 (Berkeley) 1/21/94
- *
- * $FreeBSD$
- */
-
-struct portal_args {
- char *pa_config; /* Config file */
- int pa_socket; /* Socket to server */
-};
-
-struct portal_cred {
- int pcr_flag; /* File open mode */
- uid_t pcr_uid; /* From ucred */
- short pcr_ngroups; /* From ucred */
- gid_t pcr_groups[NGROUPS]; /* From ucred */
-};
-
-#ifdef _KERNEL
-struct portalmount {
- struct vnode *pm_root; /* Root node */
- struct file *pm_server; /* Held reference to server socket */
-};
-
-struct portalnode {
- int pt_size; /* Length of Arg */
- char *pt_arg; /* Arg to send to server */
- int pt_fileid; /* cookie */
-};
-
-#define VFSTOPORTAL(mp) ((struct portalmount *)((mp)->mnt_data))
-#define VTOPORTAL(vp) ((struct portalnode *)(vp)->v_data)
-
-#define PORTAL_ROOTFILEID 2
-
-extern vop_t **portal_vnodeop_p;
-#endif /* _KERNEL */
diff --git a/sys/miscfs/portal/portal_vfsops.c b/sys/miscfs/portal/portal_vfsops.c
deleted file mode 100644
index 423cd38..0000000
--- a/sys/miscfs/portal/portal_vfsops.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95
- *
- * $FreeBSD$
- */
-
-/*
- * Portal Filesystem
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/domain.h>
-#include <sys/filedesc.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/file.h> /* Must come after sys/malloc.h */
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/vnode.h>
-
-#include <miscfs/portal/portal.h>
-
-static MALLOC_DEFINE(M_PORTALFSMNT, "PORTAL mount", "PORTAL mount structure");
-
-static int portal_mount __P((struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, 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_statfs __P((struct mount *mp, struct statfs *sbp,
- struct proc *p));
-
-/*
- * Mount the per-process file descriptors (/dev/fd)
- */
-static int
-portal_mount(mp, path, data, ndp, p)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct proc *p;
-{
- struct file *fp;
- struct portal_args args;
- struct portalmount *fmp;
- struct socket *so;
- struct vnode *rvp;
- struct portalnode *pn;
- u_int size;
- int error;
-
- /*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE)
- return (EOPNOTSUPP);
-
- error = copyin(data, (caddr_t) &args, sizeof(struct portal_args));
- if (error)
- return (error);
-
- error = holdsock(p->p_fd, args.pa_socket, &fp);
- if (error)
- return (error);
- so = (struct socket *) fp->f_data;
- if (so->so_proto->pr_domain->dom_family != AF_UNIX) {
- fdrop(fp, p);
- return (ESOCKTNOSUPPORT);
- }
-
- MALLOC(pn, struct portalnode *, sizeof(struct portalnode),
- M_TEMP, M_WAITOK);
-
- MALLOC(fmp, struct portalmount *, sizeof(struct portalmount),
- M_PORTALFSMNT, M_WAITOK); /* XXX */
-
- error = getnewvnode(VT_PORTAL, mp, portal_vnodeop_p, &rvp); /* XXX */
- if (error) {
- FREE(fmp, M_PORTALFSMNT);
- FREE(pn, M_TEMP);
- fdrop(fp, p);
- return (error);
- }
-
- rvp->v_data = pn;
- rvp->v_type = VDIR;
- rvp->v_flag |= VROOT;
- VTOPORTAL(rvp)->pt_arg = 0;
- VTOPORTAL(rvp)->pt_size = 0;
- VTOPORTAL(rvp)->pt_fileid = PORTAL_ROOTFILEID;
- fmp->pm_root = rvp;
- fmp->pm_server = fp; fp->f_count++;
-
- mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_data = (qaddr_t) fmp;
- vfs_getnewfsid(mp);
-
- (void)copyinstr(args.pa_config,
- mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
-
-#ifdef notdef
- bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
- bcopy("portal", mp->mnt_stat.f_mntfromname, sizeof("portal"));
-#endif
-
- (void)portal_statfs(mp, &mp->mnt_stat, p);
- fdrop(fp, p);
- return (0);
-}
-
-static int
-portal_unmount(mp, mntflags, p)
- struct mount *mp;
- int mntflags;
- struct proc *p;
-{
- int error, flags = 0;
-
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
-
- /*
- * Clear out buffer cache. I don't think we
- * ever get anything cached at this level at the
- * moment, but who knows...
- */
-#ifdef notyet
- mntflushbuf(mp, 0);
- if (mntinvalbuf(mp, 1))
- return (EBUSY);
-#endif
- /* There is 1 extra root vnode reference (pm_root). */
- error = vflush(mp, 1, flags);
- if (error)
- return (error);
-
- /*
- * Shutdown the socket. This will cause the select in the
- * daemon to wake up, and then the accept will get ECONNABORTED
- * which it interprets as a request to go and bury itself.
- */
- soshutdown((struct socket *) VFSTOPORTAL(mp)->pm_server->f_data, 2);
- /*
- * Discard reference to underlying file. Must call closef because
- * this may be the last reference.
- */
- closef(VFSTOPORTAL(mp)->pm_server, (struct proc *) 0);
- /*
- * Finally, throw away the portalmount structure
- */
- free(mp->mnt_data, M_PORTALFSMNT); /* XXX */
- mp->mnt_data = 0;
- return (0);
-}
-
-static int
-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);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- *vpp = vp;
- return (0);
-}
-
-static int
-portal_statfs(mp, sbp, p)
- struct mount *mp;
- struct statfs *sbp;
- struct proc *p;
-{
-
- sbp->f_flags = 0;
- sbp->f_bsize = DEV_BSIZE;
- sbp->f_iosize = DEV_BSIZE;
- sbp->f_blocks = 2; /* 1K to keep df happy */
- sbp->f_bfree = 0;
- sbp->f_bavail = 0;
- 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);
- }
- return (0);
-}
-
-static struct vfsops portal_vfsops = {
- portal_mount,
- vfs_stdstart,
- portal_unmount,
- portal_root,
- vfs_stdquotactl,
- portal_statfs,
- vfs_stdsync,
- vfs_stdvget,
- vfs_stdfhtovp,
- vfs_stdcheckexp,
- vfs_stdvptofh,
- vfs_stdinit,
- vfs_stduninit,
- vfs_stdextattrctl,
-};
-
-VFS_SET(portal_vfsops, portal, VFCF_SYNTHETIC);
diff --git a/sys/miscfs/portal/portal_vnops.c b/sys/miscfs/portal/portal_vnops.c
deleted file mode 100644
index b53c4ca..0000000
--- a/sys/miscfs/portal/portal_vnops.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
- *
- * $FreeBSD$
- */
-
-/*
- * Portal Filesystem
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/kernel.h>
-#include <sys/time.h>
-#include <sys/proc.h>
-#include <sys/filedesc.h>
-#include <sys/vnode.h>
-#include <sys/fcntl.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/mount.h>
-#include <sys/malloc.h>
-#include <sys/namei.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/un.h>
-#include <sys/unpcb.h>
-#include <miscfs/portal/portal.h>
-
-static int portal_fileid = PORTAL_ROOTFILEID+1;
-
-static int portal_badop __P((void));
-static void portal_closefd __P((struct proc *p, int fd));
-static int portal_connect __P((struct socket *so, struct socket *so2));
-static int portal_getattr __P((struct vop_getattr_args *ap));
-static int portal_lookup __P((struct vop_lookup_args *ap));
-static int portal_open __P((struct vop_open_args *ap));
-static int portal_print __P((struct vop_print_args *ap));
-static int portal_readdir __P((struct vop_readdir_args *ap));
-static int portal_reclaim __P((struct vop_reclaim_args *ap));
-static int portal_setattr __P((struct vop_setattr_args *ap));
-
-static void
-portal_closefd(p, fd)
- struct proc *p;
- int fd;
-{
- int error;
- struct close_args ua;
-
- ua.fd = fd;
- error = close(p, &ua);
- /*
- * We should never get an error, and there isn't anything
- * we could do if we got one, so just print a message.
- */
- if (error)
- printf("portal_closefd: error = %d\n", error);
-}
-
-/*
- * vp is the current namei directory
- * cnp is the name to locate in that directory...
- */
-static int
-portal_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 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;
-
- *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);
- }
-
- /*
- * 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(pt, struct portalnode *, sizeof(struct portalnode),
- M_TEMP, M_WAITOK);
-
- error = getnewvnode(VT_PORTAL, dvp->v_mount, portal_vnodeop_p, &fvp);
- if (error) {
- FREE(pt, M_TEMP);
- goto bad;
- }
- fvp->v_type = VREG;
- fvp->v_data = pt;
- /*
- * Save all of the remaining pathname and
- * advance the namei next pointer to the end
- * of the string.
- */
- for (size = 0, path = pname; *path; path++)
- size++;
- 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++;
-
- *vpp = fvp;
- /*VOP_LOCK(fvp);*/
- return (0);
-
-bad:;
- if (fvp)
- vrele(fvp);
- return (error);
-}
-
-static int
-portal_connect(so, so2)
- struct socket *so;
- struct socket *so2;
-{
- /* from unp_connect, bypassing the namei stuff... */
- struct socket *so3;
- struct unpcb *unp2;
- struct unpcb *unp3;
-
- if (so2 == 0)
- return (ECONNREFUSED);
-
- if (so->so_type != so2->so_type)
- return (EPROTOTYPE);
-
- if ((so2->so_options & SO_ACCEPTCONN) == 0)
- return (ECONNREFUSED);
-
- if ((so3 = sonewconn(so2, 0)) == 0)
- return (ECONNREFUSED);
-
- unp2 = sotounpcb(so2);
- unp3 = sotounpcb(so3);
- if (unp2->unp_addr)
- unp3->unp_addr = (struct sockaddr_un *)
- dup_sockaddr((struct sockaddr *)unp2->unp_addr, 0);
- so2 = so3;
-
- return (unp_connect2(so, so2));
-}
-
-static int
-portal_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct socket *so = 0;
- struct portalnode *pt;
- struct proc *p = ap->a_p;
- struct vnode *vp = ap->a_vp;
- int s;
- struct uio auio;
- struct iovec aiov[2];
- int res;
- struct mbuf *cm = 0;
- struct cmsghdr *cmsg;
- int newfds;
- int *ip;
- int fd;
- int error;
- int len;
- struct portalmount *fmp;
- struct file *fp;
- struct portal_cred pcred;
-
- /*
- * Nothing to do when opening the root node.
- */
- if (vp->v_flag & VROOT)
- return (0);
-
- /*
- * Can't be opened unless the caller is set up
- * to deal with the side effects. Check for this
- * by testing whether the p_dupfd has been set.
- */
- if (p->p_dupfd >= 0)
- return (ENODEV);
-
- pt = VTOPORTAL(vp);
- fmp = VFSTOPORTAL(vp->v_mount);
-
- /*
- * Create a new socket.
- */
- error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, ap->a_p);
- if (error)
- goto bad;
-
- /*
- * Reserve some buffer space
- */
- res = pt->pt_size + sizeof(pcred) + 512; /* XXX */
- error = soreserve(so, res, res);
- if (error)
- goto bad;
-
- /*
- * Kick off connection
- */
- error = portal_connect(so, (struct socket *)fmp->pm_server->f_data);
- if (error)
- goto bad;
-
- /*
- * Wait for connection to complete
- */
- /*
- * XXX: Since the mount point is holding a reference on the
- * underlying server socket, it is not easy to find out whether
- * the server process is still running. To handle this problem
- * we loop waiting for the new socket to be connected (something
- * which will only happen if the server is still running) or for
- * the reference count on the server socket to drop to 1, which
- * will happen if the server dies. Sleep for 5 second intervals
- * and keep polling the reference count. XXX.
- */
- s = splnet();
- while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
- if (fmp->pm_server->f_count == 1) {
- error = ECONNREFUSED;
- splx(s);
- goto bad;
- }
- (void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz);
- }
- splx(s);
-
- if (so->so_error) {
- error = so->so_error;
- goto bad;
- }
-
- /*
- * Set miscellaneous flags
- */
- so->so_rcv.sb_timeo = 0;
- so->so_snd.sb_timeo = 0;
- so->so_rcv.sb_flags |= SB_NOINTR;
- so->so_snd.sb_flags |= SB_NOINTR;
-
-
- pcred.pcr_flag = ap->a_mode;
- pcred.pcr_uid = ap->a_cred->cr_uid;
- pcred.pcr_ngroups = ap->a_cred->cr_ngroups;
- bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t));
- aiov[0].iov_base = (caddr_t) &pcred;
- aiov[0].iov_len = sizeof(pcred);
- aiov[1].iov_base = pt->pt_arg;
- aiov[1].iov_len = pt->pt_size;
- auio.uio_iov = aiov;
- auio.uio_iovcnt = 2;
- auio.uio_rw = UIO_WRITE;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_procp = p;
- auio.uio_offset = 0;
- auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len;
-
- error = sosend(so, (struct sockaddr *) 0, &auio,
- (struct mbuf *) 0, (struct mbuf *) 0, 0, p);
- if (error)
- goto bad;
-
- len = auio.uio_resid = sizeof(int);
- do {
- struct mbuf *m = 0;
- int flags = MSG_WAITALL;
- error = soreceive(so, (struct sockaddr **) 0, &auio,
- &m, &cm, &flags);
- if (error)
- goto bad;
-
- /*
- * Grab an error code from the mbuf.
- */
- if (m) {
- m = m_pullup(m, sizeof(int)); /* Needed? */
- if (m) {
- error = *(mtod(m, int *));
- m_freem(m);
- } else {
- error = EINVAL;
- }
- } else {
- if (cm == 0) {
- error = ECONNRESET; /* XXX */
-#ifdef notdef
- break;
-#endif
- }
- }
- } while (cm == 0 && auio.uio_resid == len && !error);
-
- if (cm == 0)
- goto bad;
-
- if (auio.uio_resid) {
- error = 0;
-#ifdef notdef
- error = EMSGSIZE;
- goto bad;
-#endif
- }
-
- /*
- * XXX: Break apart the control message, and retrieve the
- * received file descriptor. Note that more than one descriptor
- * may have been received, or that the rights chain may have more
- * than a single mbuf in it. What to do?
- */
- cmsg = mtod(cm, struct cmsghdr *);
- newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int);
- if (newfds == 0) {
- error = ECONNREFUSED;
- goto bad;
- }
- /*
- * At this point the rights message consists of a control message
- * header, followed by a data region containing a vector of
- * integer file descriptors. The fds were allocated by the action
- * of receiving the control message.
- */
- ip = (int *) (cmsg + 1);
- fd = *ip++;
- if (newfds > 1) {
- /*
- * Close extra fds.
- */
- int i;
- printf("portal_open: %d extra fds\n", newfds - 1);
- for (i = 1; i < newfds; i++) {
- portal_closefd(p, *ip);
- ip++;
- }
- }
-
- /*
- * Check that the mode the file is being opened for is a subset
- * of the mode of the existing descriptor.
- */
- fp = p->p_fd->fd_ofiles[fd];
- if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
- portal_closefd(p, fd);
- error = EACCES;
- goto bad;
- }
-
- /*
- * Save the dup fd in the proc structure then return the
- * special error code (ENXIO) which causes magic things to
- * happen in vn_open. The whole concept is, well, hmmm.
- */
- p->p_dupfd = fd;
- error = ENXIO;
-
-bad:;
- /*
- * And discard the control message.
- */
- if (cm) {
- m_freem(cm);
- }
-
- if (so) {
- soshutdown(so, 2);
- soclose(so);
- }
- return (error);
-}
-
-static int
-portal_getattr(ap)
- struct vop_getattr_args /* {
- 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;
-
- bzero(vap, sizeof(*vap));
- vattr_null(vap);
- vap->va_uid = 0;
- vap->va_gid = 0;
- vap->va_size = DEV_BSIZE;
- vap->va_blocksize = DEV_BSIZE;
- nanotime(&vap->va_atime);
- vap->va_mtime = vap->va_atime;
- vap->va_ctime = vap->va_mtime;
- vap->va_gen = 0;
- vap->va_flags = 0;
- vap->va_rdev = 0;
- /* vap->va_qbytes = 0; */
- vap->va_bytes = 0;
- /* vap->va_qsize = 0; */
- if (vp->v_flag & VROOT) {
- vap->va_type = VDIR;
- vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR|
- S_IRGRP|S_IWGRP|S_IXGRP|
- S_IROTH|S_IWOTH|S_IXOTH;
- vap->va_nlink = 2;
- vap->va_fileid = 2;
- } else {
- vap->va_type = VREG;
- vap->va_mode = S_IRUSR|S_IWUSR|
- S_IRGRP|S_IWGRP|
- S_IROTH|S_IWOTH;
- vap->va_nlink = 1;
- vap->va_fileid = VTOPORTAL(vp)->pt_fileid;
- }
- return (0);
-}
-
-static int
-portal_setattr(ap)
- struct vop_setattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
-
- /*
- * Can't mess with the root vnode
- */
- if (ap->a_vp->v_flag & VROOT)
- return (EACCES);
-
- if (ap->a_vap->va_flags != VNOVAL)
- return (EOPNOTSUPP);
-
- return (0);
-}
-
-/*
- * Fake readdir, just return empty directory.
- * It is hard to deal with '.' and '..' so don't bother.
- */
-static int
-portal_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;
-{
-
- /*
- * 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);
-}
-
-static int
-portal_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct portalnode *pt = VTOPORTAL(ap->a_vp);
-
- if (pt->pt_arg) {
- free((caddr_t) pt->pt_arg, M_TEMP);
- pt->pt_arg = 0;
- }
- FREE(ap->a_vp->v_data, M_TEMP);
- ap->a_vp->v_data = 0;
-
- return (0);
-}
-
-
-/*
- * Print out the contents of a Portal vnode.
- */
-/* ARGSUSED */
-static int
-portal_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- printf("tag VT_PORTAL, portal vnode\n");
- return (0);
-}
-
-
-/*
- * Portal "should never get here" operation
- */
-static int
-portal_badop()
-{
-
- panic("portal: bad op");
- /* NOTREACHED */
-}
-
-vop_t **portal_vnodeop_p;
-static struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) vop_null },
- { &vop_getattr_desc, (vop_t *) portal_getattr },
- { &vop_lookup_desc, (vop_t *) portal_lookup },
- { &vop_open_desc, (vop_t *) portal_open },
- { &vop_pathconf_desc, (vop_t *) vop_stdpathconf },
- { &vop_print_desc, (vop_t *) portal_print },
- { &vop_readdir_desc, (vop_t *) portal_readdir },
- { &vop_reclaim_desc, (vop_t *) portal_reclaim },
- { &vop_setattr_desc, (vop_t *) portal_setattr },
- { NULL, NULL }
-};
-static struct vnodeopv_desc portal_vnodeop_opv_desc =
- { &portal_vnodeop_p, portal_vnodeop_entries };
-
-VNODEOP_SET(portal_vnodeop_opv_desc);
diff --git a/sys/miscfs/procfs/README b/sys/miscfs/procfs/README
deleted file mode 100644
index f816b32..0000000
--- a/sys/miscfs/procfs/README
+++ /dev/null
@@ -1,113 +0,0 @@
-saute procfs lyonnais
-
-procfs supports two levels of directory. the filesystem root
-directory contains a representation of the system process table.
-this consists of an entry for each active and zombie process, and
-an additional entry "curproc" which always represents the process
-making the lookup request.
-
-each of the sub-directories contains several files. these files
-are used to control and interrogate processes. the files implemented
-are:
-
- file - xxx. the exec'ed file.
-
- status - r/o. returns process status.
-
- ctl - w/o. sends a control message to the process.
- for example:
- echo hup > /proc/curproc/note
- will send a SIGHUP to the shell.
- whereas
- echo attach > /proc/1293/ctl
- would set up process 1293 for debugging.
- see below for more details.
-
- mem - r/w. virtual memory image of the process.
- parts of the address space are readable
- only if they exist in the target process.
- a more reasonable alternative might be
- to return zero pages instead of an error.
- comments?
-
- note - w/o. writing a string here sends the
- equivalent note to the process.
- [ not implemented. ]
-
- notepg - w/o. the same as note, but sends to all
- members of the process group.
- [ not implemented. ]
-
- regs - r/w. process register set. this can be read
- or written any time even if the process
- is not stopped. since the bsd kernel
- is single-processor, this implementation
- will get the "right" register values.
- a multi-proc kernel would need to do some
- synchronisation.
-
-this then looks like:
-
-% ls -li /proc
-total 0
- 9 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 0
- 17 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 1
- 89 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 10
- 25 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 2
-2065 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 257
-2481 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 309
- 265 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 32
-3129 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 390
-3209 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 400
-3217 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 401
-3273 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 408
- 393 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 48
- 409 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 50
- 465 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 57
- 481 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 59
- 537 dr-xr-xr-x 2 root kmem 0 Sep 21 15:06 66
- 545 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 67
- 657 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 81
- 665 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 82
- 673 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 83
- 681 dr-xr-xr-x 2 root wheel 0 Sep 21 15:06 84
-3273 dr-xr-xr-x 2 jsp staff 0 Sep 21 15:06 curproc
-% ls -li /proc/curproc
-total 408
-3341 --w------- 1 jsp staff 0 Sep 21 15:06 ctl
-1554 -r-xr-xr-x 1 bin bin 90112 Mar 29 04:52 file
-3339 -rw------- 1 jsp staff 118784 Sep 21 15:06 mem
-3343 --w------- 1 jsp staff 0 Sep 21 15:06 note
-3344 --w------- 1 jsp staff 0 Sep 21 15:06 notepg
-3340 -rw------- 1 jsp staff 0 Sep 21 15:06 regs
-3342 -r--r--r-- 1 jsp staff 0 Sep 21 15:06 status
-% df /proc/curproc /proc/curproc/file
-Filesystem 512-blocks Used Avail Capacity Mounted on
-proc 2 2 0 100% /proc
-/dev/wd0a 16186 13548 1018 93% /
-% cat /proc/curproc/status
-cat 446 439 400 81 12,0 ctty 748620684 270000 0 0 0 20000 nochan 11 20 20 20 0 21 117
-
-
-
-the basic sequence of commands written to "ctl" would be
-
- attach - this stops the target process and
- arranges for the sending process
- to become the debug control process
- wait - wait for the target process to come to
- a steady state ready for debugging.
- step - single step, with no signal delivery.
- run - continue running, with no signal delivery,
- until next trap or breakpoint.
- <signame> - deliver signal <signame> and continue running.
- detach - continue execution of the target process
- and remove it from control by the debug process
-
-in a normal debugging environment, where the target is fork/exec'd by
-the debugger, the debugger should fork and the child should stop itself
-(with a self-inflicted SIGSTOP). the parent should do a "wait" then an
-"attach". as before, the child will hit a breakpoint on the first
-instruction in any newly exec'd image.
-
-$FreeBSD$
diff --git a/sys/miscfs/procfs/procfs.h b/sys/miscfs/procfs/procfs.h
deleted file mode 100644
index 1c8e5e1..0000000
--- a/sys/miscfs/procfs/procfs.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs.h 8.9 (Berkeley) 5/14/95
- *
- * From:
- * $FreeBSD$
- */
-
-/*
- * The different types of node in a procfs filesystem
- */
-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 */
- Pregs, /* the process's register set */
- Pfpregs, /* the process's FP register set */
- Pdbregs, /* the process's debug register set */
- Pctl, /* process control */
- Pstatus, /* process status */
- Pnote, /* process notifier */
- Pnotepg, /* process group notifier */
- Pmap, /* memory map */
- Ptype, /* executable type */
- Pcmdline, /* command line */
- Prlimit /* resource limits */
-} pfstype;
-
-/*
- * control data for the proc file system.
- */
-struct pfsnode {
- struct pfsnode *pfs_next; /* next on list */
- struct vnode *pfs_vnode; /* vnode associated with this pfsnode */
- pfstype pfs_type; /* type of procfs node */
- pid_t pfs_pid; /* associated process */
- u_short pfs_mode; /* mode bits for stat() */
- u_long pfs_flags; /* open flags */
- u_long pfs_fileno; /* unique file id */
- pid_t pfs_lockowner; /* pfs lock owner */
-};
-
-#define PROCFS_NOTELEN 64 /* max length of a note (/proc/$pid/note) */
-#define PROCFS_CTLLEN 8 /* max length of a ctl msg (/proc/$pid/ctl */
-#define PROCFS_NAMELEN 8 /* max length of a filename component */
-
-/*
- * Kernel stuff follows
- */
-#ifdef _KERNEL
-#define CNEQ(cnp, s, len) \
- ((cnp)->cn_namelen == (len) && \
- (bcmp((s), (cnp)->cn_nameptr, (len)) == 0))
-
-#define KMEM_GROUP 2
-
-#define PROCFS_FILENO(pid, type) \
- (((type) < Pproc) ? \
- ((type) + 2) : \
- ((((pid)+1) << 4) + ((int) (type))))
-
-/*
- * Convert between pfsnode vnode
- */
-#define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data)
-#define PFSTOV(pfs) ((pfs)->pfs_vnode)
-
-typedef struct vfs_namemap vfs_namemap_t;
-struct vfs_namemap {
- const char *nm_name;
- int nm_val;
-};
-
-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;
-struct dbreg;
-
-#define PFIND(pid) (pfind(pid))
-
-void procfs_exit __P((struct proc *));
-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_read_dbregs __P((struct proc *, struct dbreg *));
-int procfs_write_dbregs __P((struct proc *, struct dbreg *));
-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_dodbregs __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));
-int procfs_docmdline __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-int procfs_dorlimit __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio));
-
-/* Return 1 if process has special kernel digging privileges */
-int procfs_kmemaccess __P((struct proc *));
-
-/* 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 *));
-int procfs_validdbregs __P((struct proc *));
-int procfs_validmap __P((struct proc *));
-int procfs_validtype __P((struct proc *));
-
-#define PROCFS_LOCKED 0x01
-#define PROCFS_WANT 0x02
-
-extern vop_t **procfs_vnodeop_p;
-
-int procfs_root __P((struct mount *, struct vnode **));
-int procfs_rw __P((struct vop_read_args *));
-#endif /* _KERNEL */
diff --git a/sys/miscfs/procfs/procfs_ctl.c b/sys/miscfs/procfs/procfs_ctl.c
deleted file mode 100644
index 5818758..0000000
--- a/sys/miscfs/procfs/procfs_ctl.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_ctl.c 8.4 (Berkeley) 6/15/94
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/ptrace.h>
-#include <sys/signalvar.h>
-#include <sys/sx.h>
-#include <sys/vnode.h>
-
-#include <miscfs/procfs/procfs.h>
-
-#include <vm/vm.h>
-
-#ifndef FIX_SSTEP
-#define FIX_SSTEP(p)
-#endif
-
-/*
- * True iff process (p) is in trace wait state
- * relative to process (curp)
- */
-#define TRACE_WAIT_P(curp, p) \
- ((p)->p_stat == SSTOP && \
- (p)->p_pptr == (curp) && \
- ((p)->p_flag & P_TRACED))
-
-#define PROCFS_CTL_ATTACH 1
-#define PROCFS_CTL_DETACH 2
-#define PROCFS_CTL_STEP 3
-#define PROCFS_CTL_RUN 4
-#define PROCFS_CTL_WAIT 5
-
-static vfs_namemap_t ctlnames[] = {
- /* special /proc commands */
- { "attach", PROCFS_CTL_ATTACH },
- { "detach", PROCFS_CTL_DETACH },
- { "step", PROCFS_CTL_STEP },
- { "run", PROCFS_CTL_RUN },
- { "wait", PROCFS_CTL_WAIT },
- { 0 },
-};
-
-static vfs_namemap_t signames[] = {
- /* regular signal names */
- { "hup", SIGHUP }, { "int", SIGINT },
- { "quit", SIGQUIT }, { "ill", SIGILL },
- { "trap", SIGTRAP }, { "abrt", SIGABRT },
- { "iot", SIGIOT }, { "emt", SIGEMT },
- { "fpe", SIGFPE }, { "kill", SIGKILL },
- { "bus", SIGBUS }, { "segv", SIGSEGV },
- { "sys", SIGSYS }, { "pipe", SIGPIPE },
- { "alrm", SIGALRM }, { "term", SIGTERM },
- { "urg", SIGURG }, { "stop", SIGSTOP },
- { "tstp", SIGTSTP }, { "cont", SIGCONT },
- { "chld", SIGCHLD }, { "ttin", SIGTTIN },
- { "ttou", SIGTTOU }, { "io", SIGIO },
- { "xcpu", SIGXCPU }, { "xfsz", SIGXFSZ },
- { "vtalrm", SIGVTALRM }, { "prof", SIGPROF },
- { "winch", SIGWINCH }, { "info", SIGINFO },
- { "usr1", SIGUSR1 }, { "usr2", SIGUSR2 },
- { 0 },
-};
-
-static int procfs_control __P((struct proc *curp, struct proc *p, int op));
-
-static int
-procfs_control(curp, p, op)
- struct proc *curp;
- struct proc *p;
- int op;
-{
- int error = 0;
-
- /*
- * Authorization check: rely on normal debugging protection, except
- * allow processes to disengage debugging on a process onto which
- * they have previously attached, but no longer have permission to
- * debug.
- */
- if (op != PROCFS_CTL_DETACH &&
- ((error = p_can(curp, p, P_CAN_DEBUG, NULL))))
- return (error);
-
- /*
- * Attach - attaches the target process for debugging
- * by the calling process.
- */
- if (op == PROCFS_CTL_ATTACH) {
- sx_xlock(&proctree_lock);
- PROC_LOCK(p);
- if (p->p_flag & P_TRACED) {
- error = EBUSY;
- goto out;
- }
-
- /* Can't trace yourself! */
- if (p->p_pid == curp->p_pid) {
- error = EINVAL;
- goto out;
- }
-
- /*
- * Go ahead and set the trace flag.
- * Save the old parent (it's reset in
- * _DETACH, and also in kern_exit.c:wait4()
- * Reparent the process so that the tracing
- * proc gets to see all the action.
- * Stop the target.
- */
- p->p_flag |= P_TRACED;
- faultin(p);
- p->p_xstat = 0; /* XXX ? */
- if (p->p_pptr != curp) {
- p->p_oppid = p->p_pptr->p_pid;
- proc_reparent(p, curp);
- }
- psignal(p, SIGSTOP);
-out:
- PROC_UNLOCK(p);
- sx_xunlock(&proctree_lock);
- return (error);
- }
-
- /*
- * Target process must be stopped, owned by (curp) and
- * be set up for tracing (P_TRACED flag set).
- * Allow DETACH to take place at any time for sanity.
- * Allow WAIT any time, of course.
- */
- switch (op) {
- case PROCFS_CTL_DETACH:
- case PROCFS_CTL_WAIT:
- break;
-
- default:
- PROC_LOCK(p);
- mtx_lock_spin(&sched_lock);
- if (!TRACE_WAIT_P(curp, p)) {
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
- return (EBUSY);
- }
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
- }
-
-
-#ifdef FIX_SSTEP
- /*
- * do single-step fixup if needed
- */
- FIX_SSTEP(p);
-#endif
-
- /*
- * Don't deliver any signal by default.
- * To continue with a signal, just send
- * the signal name to the ctl file
- */
- PROC_LOCK(p);
- p->p_xstat = 0;
-
- switch (op) {
- /*
- * Detach. Cleans up the target process, reparent it if possible
- * and set it running once more.
- */
- case PROCFS_CTL_DETACH:
- /* if not being traced, then this is a painless no-op */
- if ((p->p_flag & P_TRACED) == 0) {
- PROC_UNLOCK(p);
- return (0);
- }
-
- /* not being traced any more */
- p->p_flag &= ~P_TRACED;
-
- /* remove pending SIGTRAP, else the process will die */
- SIGDELSET(p->p_siglist, SIGTRAP);
- PROC_UNLOCK(p);
-
- /* give process back to original parent */
- sx_xlock(&proctree_lock);
- if (p->p_oppid != p->p_pptr->p_pid) {
- struct proc *pp;
-
- pp = pfind(p->p_oppid);
- PROC_LOCK(p);
- if (pp)
- proc_reparent(p, pp);
- } else
- PROC_LOCK(p);
- p->p_oppid = 0;
- p->p_flag &= ~P_WAITED; /* XXX ? */
- PROC_UNLOCK(p);
- sx_xunlock(&proctree_lock);
-
- wakeup((caddr_t) curp); /* XXX for CTL_WAIT below ? */
-
- break;
-
- /*
- * Step. Let the target process execute a single instruction.
- */
- case PROCFS_CTL_STEP:
- _PHOLD(p);
- PROC_UNLOCK(p);
- error = procfs_sstep(p);
- PRELE(p);
- if (error)
- return (error);
- break;
-
- /*
- * Run. Let the target process continue running until a breakpoint
- * or some other trap.
- */
- case PROCFS_CTL_RUN:
- PROC_UNLOCK(p);
- break;
-
- /*
- * Wait for the target process to stop.
- * If the target is not being traced then just wait
- * to enter
- */
- case PROCFS_CTL_WAIT:
- if (p->p_flag & P_TRACED) {
- mtx_lock_spin(&sched_lock);
- while (error == 0 &&
- (p->p_stat != SSTOP) &&
- (p->p_flag & P_TRACED) &&
- (p->p_pptr == curp)) {
- mtx_unlock_spin(&sched_lock);
- error = msleep((caddr_t) p, &p->p_mtx,
- PWAIT|PCATCH, "procfsx", 0);
- mtx_lock_spin(&sched_lock);
- }
- if (error == 0 && !TRACE_WAIT_P(curp, p))
- error = EBUSY;
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
- } else {
- PROC_UNLOCK(p);
- mtx_lock_spin(&sched_lock);
- while (error == 0 && p->p_stat != SSTOP) {
- mtx_unlock_spin(&sched_lock);
- error = tsleep((caddr_t) p,
- PWAIT|PCATCH, "procfs", 0);
- mtx_lock_spin(&sched_lock);
- }
- mtx_unlock_spin(&sched_lock);
- }
- return (error);
-
- default:
- panic("procfs_control");
- }
-
- mtx_lock_spin(&sched_lock);
- if (p->p_stat == SSTOP)
- setrunnable(p);
- mtx_unlock_spin(&sched_lock);
- return (0);
-}
-
-int
-procfs_doctl(curp, p, pfs, uio)
- struct proc *curp;
- struct pfsnode *pfs;
- struct uio *uio;
- struct proc *p;
-{
- int xlen;
- int error;
- char msg[PROCFS_CTLLEN+1];
- vfs_namemap_t *nm;
-
- if (uio->uio_rw != UIO_WRITE)
- return (EOPNOTSUPP);
-
- xlen = PROCFS_CTLLEN;
- error = vfs_getuserstr(uio, msg, &xlen);
- if (error)
- return (error);
-
- /*
- * Map signal names into signal generation
- * or debug control. Unknown commands and/or signals
- * return EOPNOTSUPP.
- *
- * Sending a signal while the process is being debugged
- * also has the side effect of letting the target continue
- * to run. There is no way to single-step a signal delivery.
- */
- error = EOPNOTSUPP;
-
- nm = vfs_findname(ctlnames, msg, xlen);
- if (nm) {
- error = procfs_control(curp, p, nm->nm_val);
- } else {
- nm = vfs_findname(signames, msg, xlen);
- if (nm) {
- PROC_LOCK(p);
- mtx_lock_spin(&sched_lock);
- if (TRACE_WAIT_P(curp, p)) {
- p->p_xstat = nm->nm_val;
-#ifdef FIX_SSTEP
- FIX_SSTEP(p);
-#endif
- setrunnable(p);
- mtx_unlock_spin(&sched_lock);
- } else {
- mtx_unlock_spin(&sched_lock);
- psignal(p, nm->nm_val);
- }
- PROC_UNLOCK(p);
- error = 0;
- }
- }
-
- return (error);
-}
diff --git a/sys/miscfs/procfs/procfs_dbregs.c b/sys/miscfs/procfs/procfs_dbregs.c
deleted file mode 100644
index d80e28c..0000000
--- a/sys/miscfs/procfs/procfs_dbregs.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- * Copyright (c) 1999 Brian Scott Dean, brdean@unx.sas.com.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry under the following copyrights and conditions:
- *
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-
-#include <machine/reg.h>
-
-#include <miscfs/procfs/procfs.h>
-
-#include <vm/vm.h>
-
-int
-procfs_dodbregs(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- int error;
- struct dbreg r;
- char *kv;
- int kl;
-
- if (p_can(curp, p, P_CAN_DEBUG, NULL))
- return (EPERM);
- kl = sizeof(r);
- kv = (char *) &r;
-
- kv += uio->uio_offset;
- kl -= uio->uio_offset;
- if (kl > uio->uio_resid)
- kl = uio->uio_resid;
-
- PHOLD(p);
-
- if (kl < 0)
- error = EINVAL;
- else
- error = procfs_read_dbregs(p, &r);
- if (error == 0)
- error = uiomove(kv, kl, uio);
- if (error == 0 && uio->uio_rw == UIO_WRITE) {
- if (p->p_stat != SSTOP)
- error = EBUSY;
- else
- error = procfs_write_dbregs(p, &r);
- }
- PRELE(p);
-
- uio->uio_offset = 0;
- return (error);
-}
-
-int
-procfs_validdbregs(p)
- struct proc *p;
-{
-
- return ((p->p_flag & P_SYSTEM) == 0);
-}
diff --git a/sys/miscfs/procfs/procfs_fpregs.c b/sys/miscfs/procfs/procfs_fpregs.c
deleted file mode 100644
index 7e2ff52..0000000
--- a/sys/miscfs/procfs/procfs_fpregs.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_fpregs.c 8.2 (Berkeley) 6/15/94
- *
- * From:
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-
-#include <machine/reg.h>
-
-#include <miscfs/procfs/procfs.h>
-
-#include <vm/vm.h>
-
-int
-procfs_dofpregs(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- int error;
- struct fpreg r;
- char *kv;
- int kl;
-
- if (p_can(curp, p, P_CAN_DEBUG, NULL))
- return EPERM;
- kl = sizeof(r);
- kv = (char *) &r;
-
- kv += uio->uio_offset;
- kl -= uio->uio_offset;
- if (kl > uio->uio_resid)
- kl = uio->uio_resid;
-
- PHOLD(p);
-
- if (kl < 0)
- error = EINVAL;
- else
- error = procfs_read_fpregs(p, &r);
- if (error == 0)
- error = uiomove(kv, kl, uio);
- if (error == 0 && uio->uio_rw == UIO_WRITE) {
- if (p->p_stat != SSTOP)
- error = EBUSY;
- else
- error = procfs_write_fpregs(p, &r);
- }
- PRELE(p);
-
- uio->uio_offset = 0;
- return (error);
-}
-
-int
-procfs_validfpregs(p)
- struct proc *p;
-{
-
- return ((p->p_flag & P_SYSTEM) == 0);
-}
diff --git a/sys/miscfs/procfs/procfs_map.c b/sys/miscfs/procfs/procfs_map.c
deleted file mode 100644
index 5c21993..0000000
--- a/sys/miscfs/procfs/procfs_map.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-
-#include <miscfs/procfs/procfs.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_map.h>
-#include <vm/vm_page.h>
-#include <vm/vm_object.h>
-
-
-#define MEBUFFERSIZE 256
-
-/*
- * The map entries can *almost* be read with programs like cat. However,
- * large maps need special programs to read. It is not easy to implement
- * a program that can sense the required size of the buffer, and then
- * subsequently do a read with the appropriate size. This operation cannot
- * be atomic. The best that we can do is to allow the program to do a read
- * with an arbitrarily large buffer, and return as much as we can. We can
- * return an error code if the buffer is too small (EFBIG), then the program
- * can try a bigger buffer.
- */
-int
-procfs_domap(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- int len;
- int error;
- vm_map_t map = &p->p_vmspace->vm_map;
- pmap_t pmap = vmspace_pmap(p->p_vmspace);
- vm_map_entry_t entry;
- char mebuffer[MEBUFFERSIZE];
-
- if (uio->uio_rw != UIO_READ)
- return (EOPNOTSUPP);
-
- if (uio->uio_offset != 0)
- return (0);
-
- error = 0;
- if (map != &curproc->p_vmspace->vm_map)
- vm_map_lock_read(map);
- for (entry = map->header.next;
- ((uio->uio_resid > 0) && (entry != &map->header));
- entry = entry->next) {
- vm_object_t obj, tobj, lobj;
- int ref_count, shadow_count, flags;
- vm_offset_t addr;
- int resident, privateresident;
- char *type;
-
- if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
- continue;
-
- obj = entry->object.vm_object;
- if (obj && (obj->shadow_count == 1))
- privateresident = obj->resident_page_count;
- else
- privateresident = 0;
-
- resident = 0;
- addr = entry->start;
- while (addr < entry->end) {
- if (pmap_extract( pmap, addr))
- resident++;
- addr += PAGE_SIZE;
- }
-
- for( lobj = tobj = obj; tobj; tobj = tobj->backing_object)
- lobj = tobj;
-
- if (lobj) {
- switch(lobj->type) {
-
-default:
-case OBJT_DEFAULT:
- type = "default";
- break;
-case OBJT_VNODE:
- type = "vnode";
- break;
-case OBJT_SWAP:
- type = "swap";
- break;
-case OBJT_DEVICE:
- type = "device";
- break;
- }
-
- flags = obj->flags;
- ref_count = obj->ref_count;
- shadow_count = obj->shadow_count;
- } else {
- type = "none";
- flags = 0;
- ref_count = 0;
- shadow_count = 0;
- }
-
-
- /*
- * format:
- * start, end, resident, private resident, cow, access, type.
- */
- snprintf(mebuffer, sizeof(mebuffer),
- "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s\n",
- (u_long)entry->start, (u_long)entry->end,
- resident, privateresident, obj,
- (entry->protection & VM_PROT_READ)?"r":"-",
- (entry->protection & VM_PROT_WRITE)?"w":"-",
- (entry->protection & VM_PROT_EXECUTE)?"x":"-",
- ref_count, shadow_count, flags,
- (entry->eflags & MAP_ENTRY_COW)?"COW":"NCOW",
- (entry->eflags & MAP_ENTRY_NEEDS_COPY)?"NC":"NNC",
- type);
-
- len = strlen(mebuffer);
- if (len > uio->uio_resid) {
- error = EFBIG;
- break;
- }
- error = uiomove(mebuffer, len, uio);
- if (error)
- break;
- }
- if (map != &curproc->p_vmspace->vm_map)
- vm_map_unlock_read(map);
- return error;
-}
-
-int
-procfs_validmap(p)
- struct proc *p;
-{
- return ((p->p_flag & P_SYSTEM) == 0);
-}
diff --git a/sys/miscfs/procfs/procfs_mem.c b/sys/miscfs/procfs/procfs_mem.c
deleted file mode 100644
index 1e28870..0000000
--- a/sys/miscfs/procfs/procfs_mem.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993 Sean Eric Fagan
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry and Sean Eric Fagan.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
- *
- * $FreeBSD$
- */
-
-/*
- * This is a lightly hacked and merged version
- * of sef's pread/pwrite functions
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/ptrace.h>
-#include <sys/user.h>
-#include <sys/vnode.h>
-
-#include <miscfs/procfs/procfs.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_map.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-
-static int procfs_rwmem __P((struct proc *curp,
- struct proc *p, struct uio *uio));
-
-static int
-procfs_rwmem(curp, p, uio)
- struct proc *curp;
- struct proc *p;
- struct uio *uio;
-{
- int error;
- int writing;
- struct vmspace *vm;
- vm_map_t map;
- vm_object_t object = NULL;
- vm_offset_t pageno = 0; /* page number */
- vm_prot_t reqprot;
- vm_offset_t kva;
-
- /*
- * if the vmspace is in the midst of being deallocated or the
- * process is exiting, don't try to grab anything. The page table
- * usage in that process can be messed up.
- */
- vm = p->p_vmspace;
- if ((p->p_flag & P_WEXIT))
- return EFAULT;
-
- mtx_lock(&vm_mtx);
- if (vm->vm_refcnt < 1) {
- mtx_unlock(&vm_mtx);
- return EFAULT;
- }
- ++vm->vm_refcnt;
- /*
- * The map we want...
- */
- map = &vm->vm_map;
-
- writing = uio->uio_rw == UIO_WRITE;
- reqprot = writing ? (VM_PROT_WRITE | VM_PROT_OVERRIDE_WRITE) : VM_PROT_READ;
-
- kva = kmem_alloc_pageable(kernel_map, PAGE_SIZE);
-
- /*
- * Only map in one page at a time. We don't have to, but it
- * makes things easier. This way is trivial - right?
- */
- do {
- vm_map_t tmap;
- vm_offset_t uva;
- int page_offset; /* offset into page */
- vm_map_entry_t out_entry;
- vm_prot_t out_prot;
- boolean_t wired;
- vm_pindex_t pindex;
- u_int len;
- vm_page_t m;
-
- object = NULL;
-
- uva = (vm_offset_t) uio->uio_offset;
-
- /*
- * Get the page number of this segment.
- */
- pageno = trunc_page(uva);
- page_offset = uva - pageno;
-
- /*
- * How many bytes to copy
- */
- len = min(PAGE_SIZE - page_offset, uio->uio_resid);
-
- /*
- * Fault the page on behalf of the process
- */
- error = vm_fault(map, pageno, reqprot, VM_FAULT_NORMAL);
- if (error) {
- error = EFAULT;
- break;
- }
-
- /*
- * Now we need to get the page. out_entry, out_prot, wired,
- * and single_use aren't used. One would think the vm code
- * would be a *bit* nicer... We use tmap because
- * vm_map_lookup() can change the map argument.
- */
- tmap = map;
- error = vm_map_lookup(&tmap, pageno, reqprot,
- &out_entry, &object, &pindex, &out_prot,
- &wired);
-
- if (error) {
- error = EFAULT;
-
- /*
- * Make sure that there is no residue in 'object' from
- * an error return on vm_map_lookup.
- */
- object = NULL;
-
- break;
- }
-
- m = vm_page_lookup(object, pindex);
-
- /* Allow fallback to backing objects if we are reading */
-
- while (m == NULL && !writing && object->backing_object) {
-
- pindex += OFF_TO_IDX(object->backing_object_offset);
- object = object->backing_object;
-
- m = vm_page_lookup(object, pindex);
- }
-
- if (m == NULL) {
- error = EFAULT;
-
- /*
- * Make sure that there is no residue in 'object' from
- * an error return on vm_map_lookup.
- */
- object = NULL;
-
- vm_map_lookup_done(tmap, out_entry);
-
- break;
- }
-
- /*
- * Wire the page into memory
- */
- vm_page_wire(m);
-
- /*
- * We're done with tmap now.
- * But reference the object first, so that we won't loose
- * it.
- */
- vm_object_reference(object);
- vm_map_lookup_done(tmap, out_entry);
-
- pmap_kenter(kva, VM_PAGE_TO_PHYS(m));
-
- /*
- * Now do the i/o move.
- */
- mtx_unlock(&vm_mtx);
- error = uiomove((caddr_t)(kva + page_offset), len, uio);
- mtx_lock(&vm_mtx);
-
- pmap_kremove(kva);
-
- /*
- * release the page and the object
- */
- vm_page_unwire(m, 1);
- vm_object_deallocate(object);
-
- object = NULL;
-
- } while (error == 0 && uio->uio_resid > 0);
-
- if (object)
- vm_object_deallocate(object);
-
- kmem_free(kernel_map, kva, PAGE_SIZE);
- vmspace_free(vm);
- mtx_unlock(&vm_mtx);
- return (error);
-}
-
-/*
- * Copy data in and out of the target process.
- * We do this by mapping the process's page into
- * the kernel and then doing a uiomove direct
- * from the kernel address space.
- */
-int
-procfs_domem(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
-
- if (uio->uio_resid == 0)
- return (0);
-
- /*
- * XXX
- * We need to check for KMEM_GROUP because ps is sgid kmem;
- * not allowing it here causes ps to not work properly. Arguably,
- * this is a bug with what ps does. We only need to do this
- * for Pmem nodes, and only if it's reading. This is still not
- * good, as it may still be possible to grab illicit data if
- * a process somehow gets to be KMEM_GROUP. Note that this also
- * means that KMEM_GROUP can't change without editing procfs.h!
- * All in all, quite yucky.
- */
-
- if (p_can(curp, p, P_CAN_DEBUG, NULL) &&
- !(uio->uio_rw == UIO_READ &&
- procfs_kmemaccess(curp)))
- return EPERM;
-
- return (procfs_rwmem(curp, p, uio));
-}
-
-/*
- * Given process (p), find the vnode from which
- * its text segment is being executed.
- *
- * It would be nice to grab this information from
- * the VM system, however, there is no sure-fire
- * way of doing that. Instead, fork(), exec() and
- * wait() all maintain the p_textvp field in the
- * process proc structure which contains a held
- * reference to the exec'ed vnode.
- *
- * XXX - Currently, this is not not used, as the
- * /proc/pid/file object exposes an information leak
- * that shouldn't happen. Using a mount option would
- * make it configurable on a per-system (or, at least,
- * per-mount) basis; however, that's not really best.
- * The best way to do it, I think, would be as an
- * ioctl; this would restrict it to the uid running
- * program, or root, which seems a reasonable compromise.
- * However, the number of applications for this is
- * minimal, if it can't be seen in the filesytem space,
- * and doint it as an ioctl makes it somewhat less
- * useful due to the, well, inelegance.
- *
- */
-struct vnode *
-procfs_findtextvp(p)
- struct proc *p;
-{
-
- return (p->p_textvp);
-}
-
-int procfs_kmemaccess(curp)
- struct proc *curp;
-{
- int i;
- struct ucred *cred;
-
- cred = curp->p_ucred;
- if (suser(curp))
- return 1;
-
- /* XXX: Why isn't this done with file-perms ??? */
- for (i = 0; i < cred->cr_ngroups; i++)
- if (cred->cr_groups[i] == KMEM_GROUP)
- return 1;
-
- return 0;
-}
diff --git a/sys/miscfs/procfs/procfs_note.c b/sys/miscfs/procfs/procfs_note.c
deleted file mode 100644
index 273010b..0000000
--- a/sys/miscfs/procfs/procfs_note.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_note.c 8.2 (Berkeley) 1/21/94
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
-
-int
-procfs_donote(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- int xlen;
- int error;
- char note[PROCFS_NOTELEN+1];
-
- if (uio->uio_rw != UIO_WRITE)
- return (EINVAL);
-
- xlen = PROCFS_NOTELEN;
- error = vfs_getuserstr(uio, note, &xlen);
- if (error)
- return (error);
-
- /* send to process's notify function */
- return (EOPNOTSUPP);
-}
diff --git a/sys/miscfs/procfs/procfs_regs.c b/sys/miscfs/procfs/procfs_regs.c
deleted file mode 100644
index ba58517..0000000
--- a/sys/miscfs/procfs/procfs_regs.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_regs.c 8.4 (Berkeley) 6/15/94
- *
- * From:
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-
-#include <machine/reg.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-#include <miscfs/procfs/procfs.h>
-
-int
-procfs_doregs(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- int error;
- struct reg r;
- char *kv;
- int kl;
-
- if (p_can(curp, p, P_CAN_DEBUG, NULL))
- return EPERM;
- kl = sizeof(r);
- kv = (char *) &r;
-
- kv += uio->uio_offset;
- kl -= uio->uio_offset;
- if (kl > uio->uio_resid)
- kl = uio->uio_resid;
-
- PHOLD(p);
-
- if (kl < 0)
- error = EINVAL;
- else
- error = procfs_read_regs(p, &r);
- if (error == 0)
- error = uiomove(kv, kl, uio);
- if (error == 0 && uio->uio_rw == UIO_WRITE) {
- if (p->p_stat != SSTOP)
- error = EBUSY;
- else
- error = procfs_write_regs(p, &r);
- }
- PRELE(p);
-
- uio->uio_offset = 0;
- return (error);
-}
-
-int
-procfs_validregs(p)
- struct proc *p;
-{
-
- return ((p->p_flag & P_SYSTEM) == 0);
-}
diff --git a/sys/miscfs/procfs/procfs_rlimit.c b/sys/miscfs/procfs/procfs_rlimit.c
deleted file mode 100644
index 361f6f6..0000000
--- a/sys/miscfs/procfs/procfs_rlimit.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 1999 Adrian Chadd
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
- *
- * $FreeBSD$
- */
-
-/*
- * To get resource.h to include our rlimit_ident[] array of rlimit identifiers
- */
-
-#define _RLIMIT_IDENT
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/resourcevar.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <miscfs/procfs/procfs.h>
-
-
-int
-procfs_dorlimit(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- char *ps;
- int i;
- int xlen;
- int error;
- char psbuf[512]; /* XXX - conservative */
-
- if (uio->uio_rw != UIO_READ)
- return (EOPNOTSUPP);
-
-
- ps = psbuf;
-
- for (i = 0; i < RLIM_NLIMITS; i++) {
-
- /*
- * Add the rlimit ident
- */
-
- ps += sprintf(ps, "%s ", rlimit_ident[i]);
-
- /*
- * Replace RLIM_INFINITY with -1 in the string
- */
-
- /*
- * current limit
- */
-
- if (p->p_rlimit[i].rlim_cur == RLIM_INFINITY) {
- ps += sprintf(ps, "-1 ");
- } else {
- ps += sprintf(ps, "%llu ",
- (unsigned long long)p->p_rlimit[i].rlim_cur);
- }
-
- /*
- * maximum limit
- */
-
- if (p->p_rlimit[i].rlim_max == RLIM_INFINITY) {
- ps += sprintf(ps, "-1\n");
- } else {
- ps += sprintf(ps, "%llu\n",
- (unsigned long long)p->p_rlimit[i].rlim_max);
- }
- }
-
- /*
- * This logic is rather tasty - but its from procfs_status.c, so
- * I guess I'll use it here.
- */
-
- xlen = ps - psbuf;
- xlen -= uio->uio_offset;
- ps = psbuf + uio->uio_offset;
- xlen = imin(xlen, uio->uio_resid);
- if (xlen <= 0)
- error = 0;
- else
- error = uiomove(ps, xlen, uio);
-
- return (error);
-}
-
diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c
deleted file mode 100644
index b29b4a9..0000000
--- a/sys/miscfs/procfs/procfs_status.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
- *
- * From:
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/exec.h>
-#include <sys/jail.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/resourcevar.h>
-#include <sys/tty.h>
-#include <sys/vnode.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_param.h>
-
-#include <miscfs/procfs/procfs.h>
-
-#define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0)
-int
-procfs_dostatus(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- struct session *sess;
- struct tty *tp;
- struct ucred *cr;
- char *ps;
- char *sep;
- int pid, ppid, pgid, sid;
- int i;
- int xlen;
- int error;
- char psbuf[256]; /* XXX - conservative */
-
- if (uio->uio_rw != UIO_READ)
- return (EOPNOTSUPP);
-
- pid = p->p_pid;
- PROC_LOCK(p);
- ppid = p->p_pptr ? p->p_pptr->p_pid : 0;
- PROC_UNLOCK(p);
- pgid = p->p_pgrp->pg_id;
- sess = p->p_pgrp->pg_session;
- sid = sess->s_leader ? sess->s_leader->p_pid : 0;
-
-/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg
- euid ruid rgid,egid,groups[1 .. NGROUPS]
-*/
- KASSERT(sizeof(psbuf) > MAXCOMLEN,
- ("Too short buffer for new MAXCOMLEN"));
-
- ps = psbuf;
- bcopy(p->p_comm, ps, MAXCOMLEN);
- ps[MAXCOMLEN] = '\0';
- ps += strlen(ps);
- DOCHECK();
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- " %d %d %d %d ", pid, ppid, pgid, sid);
- DOCHECK();
- if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp))
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- "%d,%d ", major(tp->t_dev), minor(tp->t_dev));
- else
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- "%d,%d ", -1, -1);
- DOCHECK();
-
- sep = "";
- if (sess->s_ttyvp) {
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%sctty", sep);
- sep = ",";
- DOCHECK();
- }
- if (SESS_LEADER(p)) {
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "%ssldr", sep);
- sep = ",";
- DOCHECK();
- }
- if (*sep != ',') {
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "noflags");
- DOCHECK();
- }
-
- mtx_lock_spin(&sched_lock);
- if (p->p_sflag & PS_INMEM) {
- struct timeval ut, st;
-
- calcru(p, &ut, &st, (struct timeval *) NULL);
- mtx_unlock_spin(&sched_lock);
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- " %ld,%ld %ld,%ld %ld,%ld",
- p->p_stats->p_start.tv_sec,
- p->p_stats->p_start.tv_usec,
- ut.tv_sec, ut.tv_usec,
- st.tv_sec, st.tv_usec);
- } else {
- mtx_unlock_spin(&sched_lock);
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- " -1,-1 -1,-1 -1,-1");
- }
- DOCHECK();
-
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %s",
- (p->p_wchan && p->p_wmesg) ? p->p_wmesg : "nochan");
- DOCHECK();
-
- cr = p->p_ucred;
-
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " %lu %lu %lu",
- (u_long)cr->cr_uid,
- (u_long)p->p_cred->p_ruid,
- (u_long)p->p_cred->p_rgid);
- DOCHECK();
-
- /* egid (p->p_cred->p_svgid) is equal to cr_ngroups[0]
- see also getegid(2) in /sys/kern/kern_prot.c */
-
- for (i = 0; i < cr->cr_ngroups; i++) {
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- ",%lu", (u_long)cr->cr_groups[i]);
- DOCHECK();
- }
-
- if (jailed(p->p_ucred))
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
- " %s", p->p_ucred->cr_prison->pr_host);
- else
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -");
- DOCHECK();
- ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\n");
- DOCHECK();
-
- xlen = ps - psbuf;
- xlen -= uio->uio_offset;
- ps = psbuf + uio->uio_offset;
- xlen = imin(xlen, uio->uio_resid);
- if (xlen <= 0)
- error = 0;
- else
- error = uiomove(ps, xlen, uio);
-
- return (error);
-
-bailout:
- return (ENOMEM);
-}
-
-int
-procfs_docmdline(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- char *ps;
- int xlen;
- int error;
- char *buf, *bp;
- int buflen;
- struct ps_strings pstr;
- int i;
- size_t bytes_left, done;
-
- if (uio->uio_rw != UIO_READ)
- return (EOPNOTSUPP);
-
- /*
- * If we are using the ps/cmdline caching, use that. Otherwise
- * revert back to the old way which only implements full cmdline
- * for the currept process and just p->p_comm for all other
- * processes.
- * Note that if the argv is no longer available, we deliberately
- * don't fall back on p->p_comm or return an error: the authentic
- * Linux behaviour is to return zero-length in this case.
- */
-
- if (p->p_args && (ps_argsopen || !p_can(curp, p, P_CAN_SEE, NULL))) {
- bp = p->p_args->ar_args;
- buflen = p->p_args->ar_length;
- buf = 0;
- } else if (p != curp) {
- bp = p->p_comm;
- buflen = MAXCOMLEN;
- buf = 0;
- } else {
- buflen = 256;
- MALLOC(buf, char *, buflen + 1, M_TEMP, M_WAITOK);
- bp = buf;
- ps = buf;
- error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr));
- if (error) {
- FREE(buf, M_TEMP);
- return (error);
- }
- bytes_left = buflen;
- for (i = 0; bytes_left && (i < pstr.ps_nargvstr); i++) {
- error = copyinstr(pstr.ps_argvstr[i], ps,
- bytes_left, &done);
- /* If too long or malformed, just truncate */
- if (error) {
- error = 0;
- break;
- }
- ps += done;
- bytes_left -= done;
- }
- buflen = ps - buf;
- }
-
- buflen -= uio->uio_offset;
- ps = bp + uio->uio_offset;
- xlen = min(buflen, uio->uio_resid);
- if (xlen <= 0)
- error = 0;
- else
- error = uiomove(ps, xlen, uio);
- if (buf)
- FREE(buf, M_TEMP);
- return (error);
-}
diff --git a/sys/miscfs/procfs/procfs_subr.c b/sys/miscfs/procfs/procfs_subr.c
deleted file mode 100644
index 64adecb..0000000
--- a/sys/miscfs/procfs/procfs_subr.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-
-#include <miscfs/procfs/procfs.h>
-
-static struct pfsnode *pfshead;
-static int pfsvplock;
-
-/*
- * allocate a pfsnode/vnode pair. the vnode is
- * referenced, but not locked.
- *
- * the pid, pfs_type, and mount point uniquely
- * identify a pfsnode. the mount point is needed
- * because someone might mount this filesystem
- * twice.
- *
- * all pfsnodes are maintained on a singly-linked
- * list. new nodes are only allocated when they cannot
- * be found on this list. entries on the list are
- * removed when the vfs reclaim entry is called.
- *
- * a single lock is kept for the entire list. this is
- * needed because the getnewvnode() function can block
- * waiting for a vnode to become free, in which case there
- * may be more than one process trying to get the same
- * vnode. this lock is only taken if we are going to
- * call getnewvnode, since the kernel itself is single-threaded.
- *
- * if an entry is found on the list, then call vget() to
- * take a reference. this is done because there may be
- * zero references to it and so it needs to removed from
- * the vnode free list.
- */
-int
-procfs_allocvp(mp, vpp, pid, pfs_type)
- struct mount *mp;
- struct vnode **vpp;
- long pid;
- pfstype pfs_type;
-{
- 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 &&
- vp->v_mount == mp) {
- if (vget(vp, 0, p))
- goto loop;
- *vpp = vp;
- return (0);
- }
- }
-
- /*
- * otherwise lock the vp list while we call getnewvnode
- * since that can block.
- */
- if (pfsvplock & PROCFS_LOCKED) {
- pfsvplock |= PROCFS_WANT;
- (void) tsleep((caddr_t) &pfsvplock, PINOD, "pfsavp", 0);
- goto loop;
- }
- pfsvplock |= PROCFS_LOCKED;
-
- /*
- * 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(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK);
-
- if ((error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) != 0) {
- FREE(pfs, M_TEMP);
- goto out;
- }
- vp = *vpp;
-
- vp->v_data = pfs;
-
- pfs->pfs_next = 0;
- pfs->pfs_pid = (pid_t) pid;
- pfs->pfs_type = pfs_type;
- pfs->pfs_vnode = vp;
- pfs->pfs_flags = 0;
- pfs->pfs_lockowner = 0;
- pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
-
- switch (pfs_type) {
- case Proot: /* /proc = dr-xr-xr-x */
- 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|VEXEC) |
- (VREAD|VEXEC) >> 3 |
- (VREAD|VEXEC) >> 6;
- vp->v_type = VLNK;
- break;
-
- case Pmem:
- pfs->pfs_mode = (VREAD|VWRITE) |
- (VREAD) >> 3;;
- vp->v_type = VREG;
- break;
-
- case Pregs:
- case Pfpregs:
- case Pdbregs:
- 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:
- case Pmap:
- case Pstatus:
- case Pcmdline:
- case Prlimit:
- pfs->pfs_mode = (VREAD) |
- (VREAD >> 3) |
- (VREAD >> 6);
- vp->v_type = VREG;
- break;
-
- default:
- panic("procfs_allocvp");
- }
-
- /* add to procfs vnode list */
- for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next)
- continue;
- *pp = pfs;
-
-out:
- pfsvplock &= ~PROCFS_LOCKED;
-
- if (pfsvplock & PROCFS_WANT) {
- pfsvplock &= ~PROCFS_WANT;
- wakeup((caddr_t) &pfsvplock);
- }
-
- return (error);
-}
-
-int
-procfs_freevp(vp)
- struct vnode *vp;
-{
- struct pfsnode **pfspp;
- struct pfsnode *pfs = VTOPFS(vp);
-
- for (pfspp = &pfshead; *pfspp != 0; pfspp = &(*pfspp)->pfs_next) {
- if (*pfspp == pfs) {
- *pfspp = pfs->pfs_next;
- break;
- }
- }
-
- FREE(vp->v_data, M_TEMP);
- vp->v_data = 0;
- return (0);
-}
-
-int
-procfs_rw(ap)
- struct vop_read_args *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct uio *uio = ap->a_uio;
- struct proc *curp = uio->uio_procp;
- struct pfsnode *pfs = VTOPFS(vp);
- struct proc *p;
- int rtval;
-
- p = PFIND(pfs->pfs_pid);
- if (p == NULL)
- return (EINVAL);
- PROC_UNLOCK(p);
- if (p->p_pid == 1 && securelevel > 0 && uio->uio_rw == UIO_WRITE)
- return (EACCES);
-
- mp_fixme("pfs_lockowner needs a lock");
- while (pfs->pfs_lockowner) {
- tsleep(&pfs->pfs_lockowner, PRIBIO, "pfslck", 0);
- }
- pfs->pfs_lockowner = curproc->p_pid;
-
- switch (pfs->pfs_type) {
- case Pnote:
- case Pnotepg:
- rtval = procfs_donote(curp, p, pfs, uio);
- break;
-
- case Pregs:
- rtval = procfs_doregs(curp, p, pfs, uio);
- break;
-
- case Pfpregs:
- rtval = procfs_dofpregs(curp, p, pfs, uio);
- break;
-
- case Pdbregs:
- rtval = procfs_dodbregs(curp, p, pfs, uio);
- break;
-
- case Pctl:
- rtval = procfs_doctl(curp, p, pfs, uio);
- break;
-
- case Pstatus:
- rtval = procfs_dostatus(curp, p, pfs, uio);
- break;
-
- case Pmap:
- rtval = procfs_domap(curp, p, pfs, uio);
- break;
-
- case Pmem:
- rtval = procfs_domem(curp, p, pfs, uio);
- break;
-
- case Ptype:
- rtval = procfs_dotype(curp, p, pfs, uio);
- break;
-
- case Pcmdline:
- rtval = procfs_docmdline(curp, p, pfs, uio);
- break;
-
- case Prlimit:
- rtval = procfs_dorlimit(curp, p, pfs, uio);
- break;
-
- default:
- rtval = EOPNOTSUPP;
- break;
- }
- pfs->pfs_lockowner = 0;
- wakeup(&pfs->pfs_lockowner);
- return rtval;
-}
-
-/*
- * Get a string from userland into (buf). Strip a trailing
- * nl character (to allow easy access from the shell).
- * The buffer should be *buflenp + 1 chars long. vfs_getuserstr
- * will automatically add a nul char at the end.
- *
- * Returns 0 on success or the following errors
- *
- * EINVAL: file offset is non-zero.
- * EMSGSIZE: message is longer than kernel buffer
- * EFAULT: user i/o buffer is not addressable
- */
-int
-vfs_getuserstr(uio, buf, buflenp)
- struct uio *uio;
- char *buf;
- int *buflenp;
-{
- int xlen;
- int error;
-
- if (uio->uio_offset != 0)
- return (EINVAL);
-
- xlen = *buflenp;
-
- /* must be able to read the whole string in one go */
- if (xlen < uio->uio_resid)
- return (EMSGSIZE);
- xlen = uio->uio_resid;
-
- if ((error = uiomove(buf, xlen, uio)) != 0)
- return (error);
-
- /* allow multiple writes without seeks */
- uio->uio_offset = 0;
-
- /* cleanup string and remove trailing newline */
- buf[xlen] = '\0';
- xlen = strlen(buf);
- if (xlen > 0 && buf[xlen-1] == '\n')
- buf[--xlen] = '\0';
- *buflenp = xlen;
-
- return (0);
-}
-
-vfs_namemap_t *
-vfs_findname(nm, buf, buflen)
- vfs_namemap_t *nm;
- char *buf;
- int buflen;
-{
-
- for (; nm->nm_name; nm++)
- if (bcmp(buf, nm->nm_name, buflen+1) == 0)
- return (nm);
-
- return (0);
-}
-
-void
-procfs_exit(struct proc *p)
-{
- struct pfsnode *pfs;
- pid_t pid = p->p_pid;
-
- /*
- * The reason for this loop is not obvious -- basicly,
- * procfs_freevp(), which is called via vgone() (eventually),
- * removes the specified procfs node from the pfshead list.
- * It does this by *pfsp = pfs->pfs_next, meaning that it
- * overwrites the node. So when we do pfs = pfs->next, we
- * end up skipping the node that replaces the one that was
- * vgone'd. Since it may have been the last one on the list,
- * it may also have been set to null -- but *our* pfs pointer,
- * here, doesn't see this. So the loop starts from the beginning
- * again.
- *
- * This is not a for() loop because the final event
- * would be "pfs = pfs->pfs_next"; in the case where
- * pfs is set to pfshead again, that would mean that
- * pfshead is skipped over.
- *
- */
- pfs = pfshead;
- while (pfs) {
- if (pfs->pfs_pid == pid) {
- vgone(PFSTOV(pfs));
- pfs = pfshead;
- } else
- pfs = pfs->pfs_next;
- }
-}
diff --git a/sys/miscfs/procfs/procfs_type.c b/sys/miscfs/procfs/procfs_type.c
deleted file mode 100644
index cb2a45f..0000000
--- a/sys/miscfs/procfs/procfs_type.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/sysent.h>
-#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
-
-int
-procfs_dotype(curp, p, pfs, uio)
- struct proc *curp;
- struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
-{
- int len;
- int error;
- /*
- * buffer for emulation type
- */
- char mebuffer[256];
- char *none = "Not Available";
-
- if (uio->uio_rw != UIO_READ)
- return (EOPNOTSUPP);
-
- if (uio->uio_offset != 0)
- return (0);
-
- if (p && p->p_sysent && p->p_sysent->sv_name) {
- len = strlen(p->p_sysent->sv_name);
- bcopy(p->p_sysent->sv_name, mebuffer, len);
- } else {
- len = strlen(none);
- bcopy(none, mebuffer, len);
- }
- mebuffer[len++] = '\n';
- error = uiomove(mebuffer, len, uio);
- return error;
-}
-
-int
-procfs_validtype(p)
- struct proc *p;
-{
- return ((p->p_flag & P_SYSTEM) == 0);
-}
diff --git a/sys/miscfs/procfs/procfs_vfsops.c b/sys/miscfs/procfs/procfs_vfsops.c
deleted file mode 100644
index 91daf9d..0000000
--- a/sys/miscfs/procfs/procfs_vfsops.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 1993 Jan-Simon Pendry
- * Copyright (c) 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95
- *
- * $FreeBSD$
- */
-
-/*
- * procfs VFS interface
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <miscfs/procfs/procfs.h>
-
-static int procfs_mount __P((struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, struct proc *p));
-static int procfs_statfs __P((struct mount *mp, struct statfs *sbp,
- struct proc *p));
-static int procfs_unmount __P((struct mount *mp, int mntflags,
- struct proc *p));
-
-/*
- * VFS Operations.
- *
- * mount system call
- */
-/* ARGSUSED */
-static int
-procfs_mount(mp, path, data, ndp, p)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct proc *p;
-{
- size_t size;
- int error;
-
- if (mp->mnt_flag & MNT_UPDATE)
- return (EOPNOTSUPP);
-
- if (mp->mnt_vfc->vfc_refcount == 1 && (error = at_exit(procfs_exit))) {
- printf("procfs: cannot register procfs_exit with at_exit\n");
- return(error);
- }
-
- mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_data = 0;
- vfs_getnewfsid(mp);
-
- size = sizeof("procfs") - 1;
- bcopy("procfs", mp->mnt_stat.f_mntfromname, size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
- (void)procfs_statfs(mp, &mp->mnt_stat, p);
-
- return (0);
-}
-
-/*
- * unmount system call
- */
-static int
-procfs_unmount(mp, mntflags, p)
- struct mount *mp;
- int mntflags;
- struct proc *p;
-{
- int error;
- int flags = 0;
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
-
- error = vflush(mp, 0, flags);
- if (error)
- return (error);
-
- if (mp->mnt_vfc->vfc_refcount == 1)
- rm_at_exit(procfs_exit);
-
- return (0);
-}
-
-int
-procfs_root(mp, vpp)
- struct mount *mp;
- struct vnode **vpp;
-{
-
- return (procfs_allocvp(mp, vpp, 0, Proot));
-}
-
-/*
- * Get file system statistics.
- */
-static int
-procfs_statfs(mp, sbp, p)
- struct mount *mp;
- struct statfs *sbp;
- struct proc *p;
-{
- sbp->f_bsize = PAGE_SIZE;
- sbp->f_iosize = PAGE_SIZE;
- sbp->f_blocks = 1; /* avoid divide by zero in some df's */
- sbp->f_bfree = 0;
- sbp->f_bavail = 0;
- sbp->f_files = maxproc; /* approx */
- 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);
- }
-
- return (0);
-}
-
-static struct vfsops procfs_vfsops = {
- procfs_mount,
- vfs_stdstart,
- procfs_unmount,
- procfs_root,
- vfs_stdquotactl,
- procfs_statfs,
- vfs_stdsync,
- vfs_stdvget,
- vfs_stdfhtovp,
- vfs_stdcheckexp,
- vfs_stdvptofh,
- vfs_stdinit,
- vfs_stduninit,
- vfs_stdextattrctl,
-};
-
-VFS_SET(procfs_vfsops, procfs, VFCF_SYNTHETIC);
-MODULE_VERSION(procfs, 1);
diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c
deleted file mode 100644
index dbdafc8..0000000
--- a/sys/miscfs/procfs/procfs_vnops.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-/*
- * 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
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
- *
- * $FreeBSD$
- */
-
-/*
- * procfs vnode interface
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/dirent.h>
-#include <sys/fcntl.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/pioctl.h>
-#include <sys/proc.h>
-#include <sys/signalvar.h>
-#include <sys/socket.h>
-#include <sys/sx.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <sys/vnode.h>
-
-#include <machine/reg.h>
-
-#include <vm/vm_zone.h>
-
-#include <miscfs/procfs/procfs.h>
-
-static int procfs_access __P((struct vop_access_args *));
-static int procfs_badop __P((void));
-static int procfs_close __P((struct vop_close_args *));
-static int procfs_getattr __P((struct vop_getattr_args *));
-static int procfs_ioctl __P((struct vop_ioctl_args *));
-static int procfs_lookup __P((struct vop_lookup_args *));
-static int procfs_open __P((struct vop_open_args *));
-static int procfs_print __P((struct vop_print_args *));
-static int procfs_readdir __P((struct vop_readdir_args *));
-static int procfs_readlink __P((struct vop_readlink_args *));
-static int procfs_reclaim __P((struct vop_reclaim_args *));
-static int procfs_setattr __P((struct vop_setattr_args *));
-
-/*
- * This is a list of the valid names in the
- * process-specific sub-directories. It is
- * used in procfs_lookup and procfs_readdir
- */
-static 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
- /* name type validp */
- { DT_DIR, N("."), Pproc, NULL },
- { DT_DIR, N(".."), Proot, NULL },
- { DT_REG, N("mem"), Pmem, NULL },
- { DT_REG, N("regs"), Pregs, procfs_validregs },
- { DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs },
- { DT_REG, N("dbregs"), Pdbregs, procfs_validdbregs },
- { 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 },
- { DT_REG, N("cmdline"), Pcmdline, NULL },
- { DT_REG, N("rlimit"), Prlimit, NULL },
- { DT_LNK, N("file"), Pfile, NULL },
-#undef N
-};
-static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
-
-static pid_t atopid __P((const char *, u_int));
-
-/*
- * set things up for doing i/o on
- * the pfsnode (vp). (vp) is locked
- * on entry, and should be left locked
- * on exit.
- *
- * for procfs we don't need to do anything
- * in particular for i/o. all that is done
- * is to support exclusive open on process
- * memory images.
- */
-static int
-procfs_open(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);
- struct proc *p1, *p2;
- int error = 0;
-
- p2 = PFIND(pfs->pfs_pid);
- if (p2 == NULL)
- return (ENOENT);
- if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL)) {
- error = ENOENT;
- goto out;
- }
-
- switch (pfs->pfs_type) {
- case Pmem:
- if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
- ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) {
- error = EBUSY;
- goto out;
- }
-
- p1 = ap->a_p;
- if (p_can(p1, p2, P_CAN_DEBUG, NULL) &&
- !procfs_kmemaccess(p1)) {
- error = EPERM;
- }
-
- if (ap->a_mode & FWRITE)
- pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
-
- default:
- break;
- }
-out:
- PROC_UNLOCK(p2);
- return (error);
-}
-
-/*
- * close the pfsnode (vp) after doing i/o.
- * (vp) is not locked on entry or exit.
- *
- * nothing to do for procfs other than undo
- * any exclusive open flag (see _open above).
- */
-static int
-procfs_close(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);
- struct proc *p;
-
- switch (pfs->pfs_type) {
- case Pmem:
- if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
- pfs->pfs_flags &= ~(FWRITE|O_EXCL);
- /*
- * If this is the last close, then it checks to see if
- * the target process has PF_LINGER set in p_pfsflags,
- * if this is *not* the case, then the process' stop flags
- * are cleared, and the process is woken up. This is
- * to help prevent the case where a process has been
- * told to stop on an event, but then the requesting process
- * has gone away or forgotten about it.
- */
- if ((ap->a_vp->v_usecount < 2) && (p = pfind(pfs->pfs_pid))) {
- if (!(p->p_pfsflags & PF_LINGER)) {
- p->p_stops = 0;
- p->p_step = 0;
- wakeup(&p->p_step);
- }
- PROC_UNLOCK(p);
- }
- break;
- default:
- break;
- }
-
- return (0);
-}
-
-/*
- * do an ioctl operation on a pfsnode (vp).
- * (vp) is not locked on entry or exit.
- */
-static int
-procfs_ioctl(ap)
- struct vop_ioctl_args *ap;
-{
- struct pfsnode *pfs = VTOPFS(ap->a_vp);
- struct proc *procp, *p;
- int error;
- int signo;
- struct procfs_status *psp;
- unsigned char flags;
-
- p = ap->a_p;
- procp = pfind(pfs->pfs_pid);
- if (procp == NULL) {
- return ENOTTY;
- }
-
- if ((error = p_can(p, procp, P_CAN_DEBUG, NULL))) {
- PROC_UNLOCK(procp);
- return (error == ESRCH ? ENOENT : error);
- }
-
- switch (ap->a_command) {
- case PIOCBIS:
- procp->p_stops |= *(unsigned int*)ap->a_data;
- break;
- case PIOCBIC:
- procp->p_stops &= ~*(unsigned int*)ap->a_data;
- break;
- case PIOCSFL:
- /*
- * NFLAGS is "non-suser_xxx flags" -- currently, only
- * PFS_ISUGID ("ignore set u/g id");
- */
-#define NFLAGS (PF_ISUGID)
- flags = (unsigned char)*(unsigned int*)ap->a_data;
- if (flags & NFLAGS && (error = suser(p))) {
- PROC_UNLOCK(procp);
- return error;
- }
- procp->p_pfsflags = flags;
- break;
- case PIOCGFL:
- *(unsigned int*)ap->a_data = (unsigned int)procp->p_pfsflags;
- /* FALLTHROUGH */
- case PIOCSTATUS:
- psp = (struct procfs_status *)ap->a_data;
- psp->state = (procp->p_step == 0);
- psp->flags = procp->p_pfsflags;
- psp->events = procp->p_stops;
- if (procp->p_step) {
- psp->why = procp->p_stype;
- psp->val = procp->p_xstat;
- } else {
- psp->why = psp->val = 0; /* Not defined values */
- }
- break;
- case PIOCWAIT:
- psp = (struct procfs_status *)ap->a_data;
- if (procp->p_step == 0) {
- error = msleep(&procp->p_stype, &procp->p_mtx, PWAIT | PCATCH,
- "piocwait", 0);
- if (error) {
- PROC_UNLOCK(procp);
- return error;
- }
- }
- psp->state = 1; /* It stopped */
- psp->flags = procp->p_pfsflags;
- psp->events = procp->p_stops;
- psp->why = procp->p_stype; /* why it stopped */
- psp->val = procp->p_xstat; /* any extra info */
- break;
- case PIOCCONT: /* Restart a proc */
- if (procp->p_step == 0) {
- PROC_UNLOCK(procp);
- return EINVAL; /* Can only start a stopped process */
- }
- if ((signo = *(int*)ap->a_data) != 0) {
- if (signo >= NSIG || signo <= 0) {
- PROC_UNLOCK(procp);
- return EINVAL;
- }
- psignal(procp, signo);
- }
- procp->p_step = 0;
- wakeup(&procp->p_step);
- break;
- default:
- PROC_UNLOCK(procp);
- return (ENOTTY);
- }
- PROC_UNLOCK(procp);
- return 0;
-}
-
-/*
- * _reclaim is called when getnewvnode()
- * wants to make use of an entry on the vnode
- * free list. at this time the filesystem needs
- * to free any private data and remove the node
- * from any private lists.
- */
-static int
-procfs_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- return (procfs_freevp(ap->a_vp));
-}
-
-/*
- * _print is used for debugging.
- * just print a readable description
- * of (vp).
- */
-static int
-procfs_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct pfsnode *pfs = VTOPFS(ap->a_vp);
-
- printf("tag VT_PROCFS, type %d, pid %ld, mode %x, flags %lx\n",
- pfs->pfs_type, (long)pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
- return (0);
-}
-
-/*
- * generic entry point for unsupported operations
- */
-static int
-procfs_badop()
-{
-
- return (EIO);
-}
-
-/*
- * Invent attributes for pfsnode (vp) and store
- * them in (vap).
- * Directories lengths are returned as zero since
- * any real length would require the genuine size
- * to be computed, and nothing cares anyway.
- *
- * this is relatively minimal for procfs.
- */
-static int
-procfs_getattr(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;
- struct proc *procp;
- int error;
-
- /*
- * First make sure that the process and its credentials
- * still exist.
- */
- switch (pfs->pfs_type) {
- case Proot:
- case Pcurproc:
- procp = NULL;
- break;
-
- default:
- procp = PFIND(pfs->pfs_pid);
- if (procp == NULL)
- return (ENOENT);
- if (procp->p_cred == NULL || procp->p_ucred == NULL) {
- PROC_UNLOCK(procp);
- return (ENOENT);
- }
-
- if (p_can(ap->a_p, procp, P_CAN_SEE, NULL)) {
- PROC_UNLOCK(procp);
- return (ENOENT);
- }
- PROC_UNLOCK(procp);
- }
-
- error = 0;
-
- /* start by zeroing out the attributes */
- VATTR_NULL(vap);
-
- /* next do all the common fields */
- vap->va_type = ap->a_vp->v_type;
- vap->va_mode = pfs->pfs_mode;
- vap->va_fileid = pfs->pfs_fileno;
- vap->va_flags = 0;
- vap->va_blocksize = PAGE_SIZE;
- vap->va_bytes = vap->va_size = 0;
- vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[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.
- */
- nanotime(&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.
- */
- switch (pfs->pfs_type) {
- case Pctl:
- case Pregs:
- case Pfpregs:
- case Pdbregs:
- if (procp->p_flag & P_SUGID)
- vap->va_mode &= ~((VREAD|VWRITE)|
- ((VREAD|VWRITE)>>3)|
- ((VREAD|VWRITE)>>6));
- break;
- case Pmem:
- /* Retain group kmem readablity. */
- PROC_LOCK(procp);
- if (procp->p_flag & P_SUGID)
- vap->va_mode &= ~(VREAD|VWRITE);
- PROC_UNLOCK(procp);
- break;
- default:
- break;
- }
-
- /*
- * now do the object specific fields
- *
- * The size could be set from struct reg, but it's hardly
- * worth the trouble, and it puts some (potentially) machine
- * dependent data into this machine-independent code. If it
- * becomes important then this function should break out into
- * a per-file stat function in the corresponding .c file.
- */
-
- vap->va_nlink = 1;
- if (procp) {
- PROC_LOCK(procp);
- vap->va_uid = procp->p_ucred->cr_uid;
- vap->va_gid = procp->p_ucred->cr_gid;
- PROC_UNLOCK(procp);
- }
-
- switch (pfs->pfs_type) {
- case Proot:
- /*
- * 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_uid = 0;
- vap->va_gid = 0;
- vap->va_size = vap->va_bytes =
- snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid);
- break;
- }
-
- case Pproc:
- vap->va_nlink = nproc_targets;
- vap->va_size = vap->va_bytes = DEV_BSIZE;
- break;
-
- case Pfile: {
- char *fullpath, *freepath;
- error = textvp_fullpath(procp, &fullpath, &freepath);
- if (error == 0) {
- vap->va_size = strlen(fullpath);
- free(freepath, M_TEMP);
- } else {
- vap->va_size = sizeof("unknown") - 1;
- error = 0;
- }
- vap->va_bytes = vap->va_size;
- break;
- }
-
- case Pmem:
- /*
- * If we denied owner access earlier, then we have to
- * change the owner to root - otherwise 'ps' and friends
- * will break even though they are setgid kmem. *SIGH*
- */
- PROC_LOCK(procp);
- if (procp->p_flag & P_SUGID)
- vap->va_uid = 0;
- else
- vap->va_uid = procp->p_ucred->cr_uid;
- PROC_UNLOCK(procp);
- vap->va_gid = KMEM_GROUP;
- break;
-
- case Pregs:
- vap->va_bytes = vap->va_size = sizeof(struct reg);
- break;
-
- case Pfpregs:
- vap->va_bytes = vap->va_size = sizeof(struct fpreg);
- break;
-
- case Pdbregs:
- vap->va_bytes = vap->va_size = sizeof(struct dbreg);
- break;
-
- case Ptype:
- case Pmap:
- case Pctl:
- case Pstatus:
- case Pnote:
- case Pnotepg:
- case Pcmdline:
- case Prlimit:
- break;
-
- default:
- panic("procfs_getattr");
- }
-
- return (error);
-}
-
-static int
-procfs_setattr(ap)
- struct vop_setattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
-
- if (ap->a_vap->va_flags != VNOVAL)
- return (EOPNOTSUPP);
-
- /*
- * just fake out attribute setting
- * it's not good to generate an error
- * return, otherwise things like creat()
- * will fail when they try to set the
- * file length to 0. worse, this means
- * that echo $note > /proc/$pid/note will fail.
- */
-
- return (0);
-}
-
-/*
- * implement access checking.
- *
- * actually, the check for super-user is slightly
- * broken since it will allow read access to write-only
- * objects. this doesn't cause any particular trouble
- * but does mean that the i/o entry points need to check
- * that the operation really does make sense.
- */
-static int
-procfs_access(ap)
- struct vop_access_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct pfsnode *pfs = VTOPFS(ap->a_vp);
- struct vnode *vp = ap->a_vp;
- struct proc *procp;
- struct vattr *vap;
- struct vattr vattr;
- int error;
-
- switch (pfs->pfs_type) {
- case Proot:
- case Pcurproc:
- break;
- default:
- procp = PFIND(pfs->pfs_pid);
- if (procp == NULL)
- return (ENOENT);
- if (p_can(ap->a_p, procp, P_CAN_SEE, NULL)) {
- PROC_UNLOCK(procp);
- return (ENOENT);
- }
- PROC_UNLOCK(procp);
- }
-
- vap = &vattr;
- error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
- if (error)
- return (error);
-
- return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid,
- ap->a_mode, ap->a_cred, NULL));
-}
-
-/*
- * lookup. this is incredibly complicated in the
- * general case, however for most pseudo-filesystems
- * very little needs to be done.
- *
- * unless you want to get a migraine, just make sure your
- * filesystem doesn't do any locking of its own. otherwise
- * read and inwardly digest ufs_lookup().
- */
-static int
-procfs_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 vnode **vpp = ap->a_vpp;
- struct vnode *dvp = ap->a_dvp;
- char *pname = cnp->cn_nameptr;
- struct proc *curp = cnp->cn_proc;
- struct proc_target *pt;
- pid_t pid;
- struct pfsnode *pfs;
- struct proc *p;
- int i;
-
- *vpp = NULL;
-
- if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME ||
- cnp->cn_nameiop == CREATE)
- return (EROFS);
-
- if (cnp->cn_namelen == 1 && *pname == '.') {
- *vpp = dvp;
- VREF(dvp);
- /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
- return (0);
- }
-
- pfs = VTOPFS(dvp);
- switch (pfs->pfs_type) {
- case Proot:
- if (cnp->cn_flags & ISDOTDOT)
- return (EIO);
-
- if (CNEQ(cnp, "curproc", 7))
- return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc));
-
- pid = atopid(pname, cnp->cn_namelen);
- if (pid == NO_PID)
- break;
-
- p = PFIND(pid);
- if (p == NULL)
- break;
-
- if (p_can(curp, p, P_CAN_SEE, NULL)) {
- PROC_UNLOCK(p);
- break;
- }
- PROC_UNLOCK(p);
-
- return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
-
- case Pproc:
- if (cnp->cn_flags & ISDOTDOT)
- return (procfs_root(dvp->v_mount, vpp));
-
- p = PFIND(pfs->pfs_pid);
- if (p == NULL)
- break;
-
- 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;
- }
- PROC_UNLOCK(p);
- break;
- found:
- PROC_UNLOCK(p);
- return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
- pt->pt_pfstype));
-
- default:
- return (ENOTDIR);
- }
-
- return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
-}
-
-/*
- * Does this process have a text file?
- */
-int
-procfs_validfile(p)
- struct proc *p;
-{
-
- return (procfs_findtextvp(p) != NULLVP);
-}
-
-/*
- * readdir() returns directory entries from pfsnode (vp).
- *
- * We generate just one directory entry at a time, as it would probably
- * not pay off to buffer several entries locally to save uiomove calls.
- */
-static int
-procfs_readdir(ap)
- struct vop_readdir_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- int *a_eofflag;
- int *a_ncookies;
- u_long **a_cookies;
- } */ *ap;
-{
- struct uio *uio = ap->a_uio;
- struct dirent d;
- struct dirent *dp = &d;
- struct pfsnode *pfs;
- int count, error, i, off;
- static u_int delen;
-
- if (!delen) {
-
- d.d_namlen = PROCFS_NAMELEN;
- delen = GENERIC_DIRSIZ(&d);
- }
-
- pfs = VTOPFS(ap->a_vp);
-
- off = (int)uio->uio_offset;
- if (off != uio->uio_offset || off < 0 ||
- off % delen != 0 || uio->uio_resid < delen)
- return (EINVAL);
-
- error = 0;
- count = 0;
- i = off / delen;
-
- switch (pfs->pfs_type) {
- /*
- * this is for the process-specific sub-directories.
- * all that is needed to is copy out all the entries
- * from the procent[] table (top of this file).
- */
- case Pproc: {
- struct proc *p;
- struct proc_target *pt;
-
- p = PFIND(pfs->pfs_pid);
- if (p == NULL)
- break;
- if (p_can(curproc, p, P_CAN_SEE, NULL)) {
- PROC_UNLOCK(p);
- break;
- }
-
- for (pt = &proc_targets[i];
- uio->uio_resid >= delen && i < nproc_targets; pt++, i++) {
- if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
- continue;
-
- dp->d_reclen = delen;
- 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, delen, uio)) != 0)
- break;
- }
- PROC_UNLOCK(p);
-
- break;
- }
-
- /*
- * this is for the root of the procfs filesystem
- * what is needed is a special entry for "curproc"
- * followed by an entry for each process on allproc
-#ifdef PROCFS_ZOMBIE
- * and zombproc.
-#endif
- */
-
- case Proot: {
-#ifdef PROCFS_ZOMBIE
- int doingzomb = 0;
-#endif
- int pcnt = 0;
- struct proc *p;
-
- sx_slock(&allproc_lock);
- p = LIST_FIRST(&allproc);
- for (; p && uio->uio_resid >= delen; i++, pcnt++) {
- bzero((char *) dp, delen);
- dp->d_reclen = delen;
-
- switch (i) {
- case 0: /* `.' */
- case 1: /* `..' */
- dp->d_fileno = PROCFS_FILENO(0, Proot);
- 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:
- dp->d_fileno = PROCFS_FILENO(0, Pcurproc);
- dp->d_namlen = 7;
- bcopy("curproc", dp->d_name, 8);
- dp->d_type = DT_LNK;
- break;
-
- default:
- while (pcnt < i) {
- p = LIST_NEXT(p, p_list);
- if (p == NULL)
- goto done;
- if (p_can(curproc, p, P_CAN_SEE, NULL))
- continue;
- pcnt++;
- }
- while (p_can(curproc, p, P_CAN_SEE, NULL)) {
- p = LIST_NEXT(p, p_list);
- if (p == NULL)
- 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_DIR;
- p = LIST_NEXT(p, p_list);
- break;
- }
-
- if ((error = uiomove((caddr_t)dp, delen, uio)) != 0)
- break;
- }
- done:
-
-#ifdef PROCFS_ZOMBIE
- if (p == NULL && doingzomb == 0) {
- doingzomb = 1;
- p = LIST_FIRST(&zombproc);
- goto again;
- }
-#endif
-
- sx_sunlock(&allproc_lock);
- break;
-
- }
-
- default:
- error = ENOTDIR;
- break;
- }
-
- uio->uio_offset = i * delen;
-
- return (error);
-}
-
-/*
- * readlink reads the link of `curproc' or `file'
- */
-static int
-procfs_readlink(ap)
- struct vop_readlink_args *ap;
-{
- char buf[16]; /* should be enough */
- struct proc *procp;
- struct vnode *vp = ap->a_vp;
- struct pfsnode *pfs = VTOPFS(vp);
- char *fullpath, *freepath;
- int error, len;
-
- switch (pfs->pfs_type) {
- case Pcurproc:
- if (pfs->pfs_fileno != PROCFS_FILENO(0, Pcurproc))
- return (EINVAL);
-
- len = snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid);
-
- return (uiomove(buf, len, ap->a_uio));
- /*
- * There _should_ be no way for an entire process to disappear
- * from under us...
- */
- case Pfile:
- procp = PFIND(pfs->pfs_pid);
- if (procp == NULL || procp->p_cred == NULL ||
- procp->p_ucred == NULL) {
- if (procp != NULL)
- PROC_UNLOCK(procp);
- printf("procfs_readlink: pid %d disappeared\n",
- pfs->pfs_pid);
- return (uiomove("unknown", sizeof("unknown") - 1,
- ap->a_uio));
- }
- PROC_UNLOCK(procp);
- error = textvp_fullpath(procp, &fullpath, &freepath);
- if (error != 0)
- return (uiomove("unknown", sizeof("unknown") - 1,
- ap->a_uio));
- error = uiomove(fullpath, strlen(fullpath), ap->a_uio);
- free(freepath, M_TEMP);
- return (error);
- default:
- return (EINVAL);
- }
-}
-
-/*
- * convert decimal ascii to pid_t
- */
-static pid_t
-atopid(b, len)
- const char *b;
- u_int len;
-{
- pid_t p = 0;
-
- while (len--) {
- char c = *b++;
- if (c < '0' || c > '9')
- return (NO_PID);
- p = 10 * p + (c - '0');
- if (p > PID_MAX)
- return (NO_PID);
- }
-
- return (p);
-}
-
-/*
- * procfs vnode operations.
- */
-vop_t **procfs_vnodeop_p;
-static struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) procfs_access },
- { &vop_advlock_desc, (vop_t *) procfs_badop },
- { &vop_close_desc, (vop_t *) procfs_close },
- { &vop_create_desc, (vop_t *) procfs_badop },
- { &vop_getattr_desc, (vop_t *) procfs_getattr },
- { &vop_link_desc, (vop_t *) procfs_badop },
- { &vop_lookup_desc, (vop_t *) procfs_lookup },
- { &vop_mkdir_desc, (vop_t *) procfs_badop },
- { &vop_mknod_desc, (vop_t *) procfs_badop },
- { &vop_open_desc, (vop_t *) procfs_open },
- { &vop_pathconf_desc, (vop_t *) vop_stdpathconf },
- { &vop_print_desc, (vop_t *) procfs_print },
- { &vop_read_desc, (vop_t *) procfs_rw },
- { &vop_readdir_desc, (vop_t *) procfs_readdir },
- { &vop_readlink_desc, (vop_t *) procfs_readlink },
- { &vop_reclaim_desc, (vop_t *) procfs_reclaim },
- { &vop_remove_desc, (vop_t *) procfs_badop },
- { &vop_rename_desc, (vop_t *) procfs_badop },
- { &vop_rmdir_desc, (vop_t *) procfs_badop },
- { &vop_setattr_desc, (vop_t *) procfs_setattr },
- { &vop_symlink_desc, (vop_t *) procfs_badop },
- { &vop_write_desc, (vop_t *) procfs_rw },
- { &vop_ioctl_desc, (vop_t *) procfs_ioctl },
- { NULL, NULL }
-};
-static struct vnodeopv_desc procfs_vnodeop_opv_desc =
- { &procfs_vnodeop_p, procfs_vnodeop_entries };
-
-VNODEOP_SET(procfs_vnodeop_opv_desc);
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
deleted file mode 100644
index ba81229..0000000
--- a/sys/miscfs/specfs/spec_vnops.c
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * 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
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/proc.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/conf.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/stat.h>
-#include <sys/fcntl.h>
-#include <sys/vmmeter.h>
-#include <sys/tty.h>
-
-#include <vm/vm.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-#include <vm/vm_pager.h>
-
-static int spec_advlock __P((struct vop_advlock_args *));
-static int spec_bmap __P((struct vop_bmap_args *));
-static int spec_close __P((struct vop_close_args *));
-static int spec_freeblks __P((struct vop_freeblks_args *));
-static int spec_fsync __P((struct vop_fsync_args *));
-static int spec_getpages __P((struct vop_getpages_args *));
-static int spec_ioctl __P((struct vop_ioctl_args *));
-static int spec_open __P((struct vop_open_args *));
-static int spec_poll __P((struct vop_poll_args *));
-static int spec_kqfilter __P((struct vop_kqfilter_args *));
-static int spec_print __P((struct vop_print_args *));
-static int spec_read __P((struct vop_read_args *));
-static int spec_strategy __P((struct vop_strategy_args *));
-static int spec_write __P((struct vop_write_args *));
-
-vop_t **spec_vnodeop_p;
-static struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) vop_ebadf },
- { &vop_advlock_desc, (vop_t *) spec_advlock },
- { &vop_bmap_desc, (vop_t *) spec_bmap },
- { &vop_close_desc, (vop_t *) spec_close },
- { &vop_create_desc, (vop_t *) vop_panic },
- { &vop_freeblks_desc, (vop_t *) spec_freeblks },
- { &vop_fsync_desc, (vop_t *) spec_fsync },
- { &vop_getpages_desc, (vop_t *) spec_getpages },
- { &vop_getwritemount_desc, (vop_t *) vop_stdgetwritemount },
- { &vop_ioctl_desc, (vop_t *) spec_ioctl },
- { &vop_lease_desc, (vop_t *) vop_null },
- { &vop_link_desc, (vop_t *) vop_panic },
- { &vop_mkdir_desc, (vop_t *) vop_panic },
- { &vop_mknod_desc, (vop_t *) vop_panic },
- { &vop_open_desc, (vop_t *) spec_open },
- { &vop_pathconf_desc, (vop_t *) vop_stdpathconf },
- { &vop_poll_desc, (vop_t *) spec_poll },
- { &vop_kqfilter_desc, (vop_t *) spec_kqfilter },
- { &vop_print_desc, (vop_t *) spec_print },
- { &vop_read_desc, (vop_t *) spec_read },
- { &vop_readdir_desc, (vop_t *) vop_panic },
- { &vop_readlink_desc, (vop_t *) vop_panic },
- { &vop_reallocblks_desc, (vop_t *) vop_panic },
- { &vop_reclaim_desc, (vop_t *) vop_null },
- { &vop_remove_desc, (vop_t *) vop_panic },
- { &vop_rename_desc, (vop_t *) vop_panic },
- { &vop_rmdir_desc, (vop_t *) vop_panic },
- { &vop_setattr_desc, (vop_t *) vop_ebadf },
- { &vop_strategy_desc, (vop_t *) spec_strategy },
- { &vop_symlink_desc, (vop_t *) vop_panic },
- { &vop_write_desc, (vop_t *) spec_write },
- { NULL, NULL }
-};
-static struct vnodeopv_desc spec_vnodeop_opv_desc =
- { &spec_vnodeop_p, spec_vnodeop_entries };
-
-VNODEOP_SET(spec_vnodeop_opv_desc);
-
-int
-spec_vnoperate(ap)
- struct vop_generic_args /* {
- struct vnodeop_desc *a_desc;
- <other random data follows, presumably>
- } */ *ap;
-{
- return (VOCALL(spec_vnodeop_p, ap->a_desc->vdesc_offset, ap));
-}
-
-static void spec_getpages_iodone __P((struct buf *bp));
-
-/*
- * Open a special file.
- */
-/* ARGSUSED */
-static int
-spec_open(ap)
- struct vop_open_args /* {
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct proc *p = ap->a_p;
- struct vnode *vp = ap->a_vp;
- dev_t dev = vp->v_rdev;
- int error;
- struct cdevsw *dsw;
- const char *cp;
-
- if (vp->v_type == VBLK)
- return ENXIO;
- /*
- * Don't allow open if fs is mounted -nodev.
- */
- if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
- return (ENXIO);
-
- dsw = devsw(dev);
- if ( (dsw == NULL) || (dsw->d_open == NULL))
- return ENXIO;
-
- /* Make this field valid before any I/O in ->d_open */
- if (!dev->si_iosize_max)
- dev->si_iosize_max = DFLTPHYS;
-
- /*
- * XXX: Disks get special billing here, but it is mostly wrong.
- * XXX: diskpartitions can overlap and the real checks should
- * XXX: take this into account, and consequently they need to
- * XXX: live in the diskslicing code. Some checks do.
- */
- if (vn_isdisk(vp, NULL) && ap->a_cred != FSCRED &&
- (ap->a_mode & FWRITE)) {
- /*
- * Never allow opens for write if the device is mounted R/W
- */
- if (vp->v_rdev->si_mountpoint != NULL &&
- !(vp->v_rdev->si_mountpoint->mnt_flag & MNT_RDONLY))
- return (EBUSY);
-
- /*
- * When running in secure mode, do not allow opens
- * for writing if the device is mounted
- */
- if (securelevel >= 1 && vfs_mountedon(vp))
- return (EPERM);
-
- /*
- * When running in very secure mode, do not allow
- * opens for writing of any devices.
- */
- if (securelevel >= 2)
- return (EPERM);
- }
-
- /* XXX: Special casing of ttys for deadfs. Probably redundant */
- if (dsw->d_flags & D_TTY)
- vp->v_flag |= VISTTY;
-
- VOP_UNLOCK(vp, 0, p);
- error = (*dsw->d_open)(dev, ap->a_mode, S_IFCHR, p);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
-
- if (error)
- return (error);
-
- if (dsw->d_flags & D_TTY) {
- if (dev->si_tty) {
- struct tty *tp;
- tp = dev->si_tty;
- if (!tp->t_stop) {
- printf("Warning:%s: no t_stop, using nottystop\n", devtoname(dev));
- tp->t_stop = nottystop;
- }
- }
- }
-
- if (vn_isdisk(vp, NULL)) {
- if (!dev->si_bsize_phys)
- dev->si_bsize_phys = DEV_BSIZE;
- }
- if ((dsw->d_flags & D_DISK) == 0) {
- cp = devtoname(dev);
- if (*cp == '#' && (dsw->d_flags & D_NAGGED) == 0) {
- printf("WARNING: driver %s should register devices with make_dev() (dev_t = \"%s\")\n",
- dsw->d_name, cp);
- dsw->d_flags |= D_NAGGED;
- }
- }
- return (error);
-}
-
-/*
- * Vnode op for read
- */
-/* ARGSUSED */
-static int
-spec_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct vnode *vp;
- struct proc *p;
- struct uio *uio;
- dev_t dev;
- int error, resid;
-
- vp = ap->a_vp;
- dev = vp->v_rdev;
- uio = ap->a_uio;
- p = uio->uio_procp;
- resid = uio->uio_resid;
-
- if (resid == 0)
- return (0);
-
- VOP_UNLOCK(vp, 0, p);
- error = (*devsw(dev)->d_read) (dev, uio, ap->a_ioflag);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (uio->uio_resid != resid || (error == 0 && resid != 0))
- getnanotime(&dev->si_atime);
- return (error);
-}
-
-/*
- * Vnode op for write
- */
-/* ARGSUSED */
-static int
-spec_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct vnode *vp;
- struct proc *p;
- struct uio *uio;
- dev_t dev;
- int error, resid;
-
- vp = ap->a_vp;
- dev = vp->v_rdev;
- uio = ap->a_uio;
- p = uio->uio_procp;
- resid = uio->uio_resid;
-
- VOP_UNLOCK(vp, 0, p);
- error = (*devsw(dev)->d_write) (dev, uio, ap->a_ioflag);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
- getnanotime(&dev->si_ctime);
- dev->si_mtime = dev->si_ctime;
- }
- return (error);
-}
-
-/*
- * Device ioctl operation.
- */
-/* ARGSUSED */
-static int
-spec_ioctl(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;
-{
- dev_t dev;
-
- dev = ap->a_vp->v_rdev;
- return ((*devsw(dev)->d_ioctl)(dev, ap->a_command,
- ap->a_data, ap->a_fflag, ap->a_p));
-}
-
-/* ARGSUSED */
-static int
-spec_poll(ap)
- struct vop_poll_args /* {
- struct vnode *a_vp;
- int a_events;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- dev_t dev;
-
- dev = ap->a_vp->v_rdev;
- return (*devsw(dev)->d_poll)(dev, ap->a_events, ap->a_p);
-}
-
-/* ARGSUSED */
-static int
-spec_kqfilter(ap)
- struct vop_kqfilter_args /* {
- struct vnode *a_vp;
- struct knote *a_kn;
- } */ *ap;
-{
- dev_t dev;
-
- dev = ap->a_vp->v_rdev;
- if (devsw(dev)->d_flags & D_KQFILTER)
- return (*devsw(dev)->d_kqfilter)(dev, ap->a_kn);
- return (1);
-}
-
-/*
- * Synch buffers associated with a block device
- */
-/* ARGSUSED */
-static int
-spec_fsync(ap)
- struct vop_fsync_args /* {
- struct vnode *a_vp;
- struct ucred *a_cred;
- int a_waitfor;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct buf *bp;
- struct buf *nbp;
- int s;
- int maxretry = 10000; /* large, arbitrarily chosen */
-
- if (!vn_isdisk(vp, NULL))
- return (0);
-
-loop1:
- /*
- * MARK/SCAN initialization to avoid infinite loops
- */
- s = splbio();
- TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
- bp->b_flags &= ~B_SCANNED;
- }
- splx(s);
-
- /*
- * Flush all dirty buffers associated with a block device.
- */
-loop2:
- s = splbio();
- for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
- nbp = TAILQ_NEXT(bp, b_vnbufs);
- if ((bp->b_flags & B_SCANNED) != 0)
- continue;
- bp->b_flags |= B_SCANNED;
- if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
- continue;
- if ((bp->b_flags & B_DELWRI) == 0)
- panic("spec_fsync: not dirty");
- if ((vp->v_flag & VOBJBUF) && (bp->b_flags & B_CLUSTEROK)) {
- BUF_UNLOCK(bp);
- vfs_bio_awrite(bp);
- splx(s);
- } else {
- bremfree(bp);
- splx(s);
- bawrite(bp);
- }
- goto loop2;
- }
-
- /*
- * If synchronous the caller expects us to completely resolve all
- * dirty buffers in the system. Wait for in-progress I/O to
- * complete (which could include background bitmap writes), then
- * retry if dirty blocks still exist.
- */
- if (ap->a_waitfor == MNT_WAIT) {
- while (vp->v_numoutput) {
- vp->v_flag |= VBWAIT;
- (void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "spfsyn", 0);
- }
- if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
- if (--maxretry != 0) {
- splx(s);
- goto loop1;
- }
- vprint("spec_fsync: giving up on dirty", vp);
- }
- }
- splx(s);
- return (0);
-}
-
-/*
- * Just call the device strategy routine
- */
-static int
-spec_strategy(ap)
- struct vop_strategy_args /* {
- struct vnode *a_vp;
- struct buf *a_bp;
- } */ *ap;
-{
- struct buf *bp;
- struct vnode *vp;
- struct mount *mp;
- int error;
-
- bp = ap->a_bp;
- vp = ap->a_vp;
- if ((bp->b_iocmd == BIO_WRITE)) {
- if ((bp->b_flags & B_VALIDSUSPWRT) == 0 &&
- bp->b_vp != NULL && bp->b_vp->v_mount != NULL &&
- (bp->b_vp->v_mount->mnt_kern_flag & MNTK_SUSPENDED) != 0)
- panic("spec_strategy: bad I/O");
- bp->b_flags &= ~B_VALIDSUSPWRT;
- if (LIST_FIRST(&bp->b_dep) != NULL)
- buf_start(bp);
- if ((vp->v_flag & VCOPYONWRITE) && vp->v_rdev->si_copyonwrite &&
- (error = (*vp->v_rdev->si_copyonwrite)(vp, bp)) != 0 &&
- error != EOPNOTSUPP) {
- bp->b_io.bio_error = error;
- bp->b_io.bio_flags |= BIO_ERROR;
- biodone(&bp->b_io);
- return (0);
- }
- }
- /*
- * Collect statistics on synchronous and asynchronous read
- * and write counts for disks that have associated filesystems.
- */
- if (vn_isdisk(vp, NULL) && (mp = vp->v_rdev->si_mountpoint) != NULL) {
- if (bp->b_iocmd == BIO_WRITE) {
- if (bp->b_lock.lk_lockholder == LK_KERNPROC)
- mp->mnt_stat.f_asyncwrites++;
- else
- mp->mnt_stat.f_syncwrites++;
- } else {
- if (bp->b_lock.lk_lockholder == LK_KERNPROC)
- mp->mnt_stat.f_asyncreads++;
- else
- mp->mnt_stat.f_syncreads++;
- }
- }
- KASSERT(devsw(bp->b_dev) != NULL,
- ("No devsw on dev %s responsible for buffer %p\n",
- devtoname(bp->b_dev), bp));
- KASSERT(devsw(bp->b_dev)->d_strategy != NULL,
- ("No strategy on dev %s responsible for buffer %p\n",
- devtoname(bp->b_dev), bp));
- DEV_STRATEGY(bp, 0);
- return (0);
-}
-
-static int
-spec_freeblks(ap)
- struct vop_freeblks_args /* {
- struct vnode *a_vp;
- daddr_t a_addr;
- daddr_t a_length;
- } */ *ap;
-{
- struct cdevsw *bsw;
- struct buf *bp;
-
- /*
- * XXX: This assumes that strategy does the deed right away.
- * XXX: this may not be TRTTD.
- */
- bsw = devsw(ap->a_vp->v_rdev);
- if ((bsw->d_flags & D_CANFREE) == 0)
- return (0);
- bp = geteblk(ap->a_length);
- bp->b_iocmd = BIO_DELETE;
- bp->b_dev = ap->a_vp->v_rdev;
- bp->b_blkno = ap->a_addr;
- bp->b_offset = dbtob(ap->a_addr);
- bp->b_bcount = ap->a_length;
- BUF_KERNPROC(bp);
- DEV_STRATEGY(bp, 0);
- return (0);
-}
-
-/*
- * Implement degenerate case where the block requested is the block
- * returned, and assume that the entire device is contiguous in regards
- * to the contiguous block range (runp and runb).
- */
-static int
-spec_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;
- int *a_runb;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- int runp = 0;
- int runb = 0;
-
- if (ap->a_vpp != NULL)
- *ap->a_vpp = vp;
- if (ap->a_bnp != NULL)
- *ap->a_bnp = ap->a_bn;
- if (vp->v_mount != NULL)
- runp = runb = MAXBSIZE / vp->v_mount->mnt_stat.f_iosize;
- if (ap->a_runp != NULL)
- *ap->a_runp = runp;
- if (ap->a_runb != NULL)
- *ap->a_runb = runb;
- return (0);
-}
-
-/*
- * Device close routine
- */
-/* ARGSUSED */
-static int
-spec_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct proc *p = ap->a_p;
- dev_t dev = vp->v_rdev;
-
- /*
- * Hack: a tty device that is a controlling terminal
- * has a reference from the session structure.
- * We cannot easily tell that a character device is
- * a controlling terminal, unless it is the closing
- * process' controlling terminal. In that case,
- * if the reference count is 2 (this last descriptor
- * plus the session), release the reference from the session.
- */
- if (vcount(vp) == 2 && p && (vp->v_flag & VXLOCK) == 0 &&
- vp == p->p_session->s_ttyvp) {
- vrele(vp);
- p->p_session->s_ttyvp = NULL;
- }
- /*
- * We do not want to really close the device if it
- * is still in use unless we are trying to close it
- * forcibly. Since every use (buffer, vnode, swap, cmap)
- * holds a reference to the vnode, and because we mark
- * any other vnodes that alias this device, when the
- * sum of the reference counts on all the aliased
- * vnodes descends to one, we are on last close.
- */
- if (vp->v_flag & VXLOCK) {
- /* Forced close */
- } else if (devsw(dev)->d_flags & D_TRACKCLOSE) {
- /* Keep device updated on status */
- } else if (vcount(vp) > 1) {
- return (0);
- }
- return (devsw(dev)->d_close(dev, ap->a_fflag, S_IFCHR, p));
-}
-
-/*
- * Print out the contents of a special device vnode.
- */
-static int
-spec_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
-
- printf("tag VT_NON, dev %s\n", devtoname(ap->a_vp->v_rdev));
- return (0);
-}
-
-/*
- * Special device advisory byte-level locks.
- */
-/* ARGSUSED */
-static int
-spec_advlock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
-{
-
- return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
-}
-
-static void
-spec_getpages_iodone(bp)
- struct buf *bp;
-{
-
- bp->b_flags |= B_DONE;
- wakeup(bp);
-}
-
-static int
-spec_getpages(ap)
- struct vop_getpages_args *ap;
-{
- vm_offset_t kva;
- int error;
- int i, pcount, size, s;
- daddr_t blkno;
- struct buf *bp;
- vm_page_t m;
- vm_ooffset_t offset;
- int toff, nextoff, nread;
- struct vnode *vp = ap->a_vp;
- int blksiz;
- int gotreqpage;
-
- error = 0;
- pcount = round_page(ap->a_count) / PAGE_SIZE;
-
- /*
- * Calculate the offset of the transfer and do sanity check.
- * FreeBSD currently only supports an 8 TB range due to b_blkno
- * being in DEV_BSIZE ( usually 512 ) byte chunks on call to
- * VOP_STRATEGY. XXX
- */
- offset = IDX_TO_OFF(ap->a_m[0]->pindex) + ap->a_offset;
-
-#define DADDR_T_BIT (sizeof(daddr_t)*8)
-#define OFFSET_MAX ((1LL << (DADDR_T_BIT + DEV_BSHIFT)) - 1)
-
- if (offset < 0 || offset > OFFSET_MAX) {
- /* XXX still no %q in kernel. */
- printf("spec_getpages: preposterous offset 0x%x%08x\n",
- (u_int)((u_quad_t)offset >> 32),
- (u_int)(offset & 0xffffffff));
- return (VM_PAGER_ERROR);
- }
-
- blkno = btodb(offset);
-
- /*
- * Round up physical size for real devices. We cannot round using
- * v_mount's block size data because v_mount has nothing to do with
- * the device. i.e. it's usually '/dev'. We need the physical block
- * size for the device itself.
- *
- * We can't use v_rdev->si_mountpoint because it only exists when the
- * block device is mounted. However, we can use v_rdev.
- */
-
- if (vn_isdisk(vp, NULL))
- blksiz = vp->v_rdev->si_bsize_phys;
- else
- blksiz = DEV_BSIZE;
-
- size = (ap->a_count + blksiz - 1) & ~(blksiz - 1);
-
- bp = getpbuf(NULL);
- kva = (vm_offset_t)bp->b_data;
-
- /*
- * Map the pages to be read into the kva.
- */
- pmap_qenter(kva, ap->a_m, pcount);
-
- /* Build a minimal buffer header. */
- bp->b_iocmd = BIO_READ;
- bp->b_iodone = spec_getpages_iodone;
-
- /* B_PHYS is not set, but it is nice to fill this in. */
- bp->b_rcred = bp->b_wcred = curproc->p_ucred;
- if (bp->b_rcred != NOCRED)
- crhold(bp->b_rcred);
- if (bp->b_wcred != NOCRED)
- crhold(bp->b_wcred);
- bp->b_blkno = blkno;
- bp->b_lblkno = blkno;
- pbgetvp(ap->a_vp, bp);
- bp->b_bcount = size;
- bp->b_bufsize = size;
- bp->b_resid = 0;
- bp->b_runningbufspace = bp->b_bufsize;
- runningbufspace += bp->b_runningbufspace;
-
- cnt.v_vnodein++;
- cnt.v_vnodepgsin += pcount;
-
- mtx_unlock(&vm_mtx);
- mtx_lock(&Giant);
- /* Do the input. */
- BUF_STRATEGY(bp);
-
- s = splbio();
-
- /* We definitely need to be at splbio here. */
- while ((bp->b_flags & B_DONE) == 0)
- tsleep(bp, PVM, "spread", 0);
-
- splx(s);
- mtx_unlock(&Giant);
- mtx_lock(&vm_mtx);
-
- if ((bp->b_ioflags & BIO_ERROR) != 0) {
- if (bp->b_error)
- error = bp->b_error;
- else
- error = EIO;
- }
-
- nread = size - bp->b_resid;
-
- if (nread < ap->a_count) {
- bzero((caddr_t)kva + nread,
- ap->a_count - nread);
- }
- pmap_qremove(kva, pcount);
-
-
- gotreqpage = 0;
- for (i = 0, toff = 0; i < pcount; i++, toff = nextoff) {
- nextoff = toff + PAGE_SIZE;
- m = ap->a_m[i];
-
- m->flags &= ~PG_ZERO;
-
- if (nextoff <= nread) {
- m->valid = VM_PAGE_BITS_ALL;
- vm_page_undirty(m);
- } else if (toff < nread) {
- /*
- * Since this is a VM request, we have to supply the
- * unaligned offset to allow vm_page_set_validclean()
- * to zero sub-DEV_BSIZE'd portions of the page.
- */
- vm_page_set_validclean(m, 0, nread - toff);
- } else {
- m->valid = 0;
- vm_page_undirty(m);
- }
-
- if (i != ap->a_reqpage) {
- /*
- * Just in case someone was asking for this page we
- * now tell them that it is ok to use.
- */
- if (!error || (m->valid == VM_PAGE_BITS_ALL)) {
- if (m->valid) {
- if (m->flags & PG_WANTED) {
- vm_page_activate(m);
- } else {
- vm_page_deactivate(m);
- }
- vm_page_wakeup(m);
- } else {
- vm_page_free(m);
- }
- } else {
- vm_page_free(m);
- }
- } else if (m->valid) {
- gotreqpage = 1;
- /*
- * Since this is a VM request, we need to make the
- * entire page presentable by zeroing invalid sections.
- */
- if (m->valid != VM_PAGE_BITS_ALL)
- vm_page_zero_invalid(m, FALSE);
- }
- }
- if (!gotreqpage) {
- m = ap->a_m[ap->a_reqpage];
- printf(
- "spec_getpages:(%s) I/O read failure: (error=%d) bp %p vp %p\n",
- devtoname(bp->b_dev), error, bp, bp->b_vp);
- printf(
- " size: %d, resid: %ld, a_count: %d, valid: 0x%x\n",
- size, bp->b_resid, ap->a_count, m->valid);
- printf(
- " nread: %d, reqpage: %d, pindex: %lu, pcount: %d\n",
- nread, ap->a_reqpage, (u_long)m->pindex, pcount);
- /*
- * Free the buffer header back to the swap buffer pool.
- */
- relpbuf(bp, NULL);
- return VM_PAGER_ERROR;
- }
- /*
- * Free the buffer header back to the swap buffer pool.
- */
- relpbuf(bp, NULL);
- return VM_PAGER_OK;
-}
diff --git a/sys/miscfs/umapfs/umap.h b/sys/miscfs/umapfs/umap.h
deleted file mode 100644
index eb562ed..0000000
--- a/sys/miscfs/umapfs/umap.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * the UCLA Ficus project.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)umap.h 8.4 (Berkeley) 8/20/94
- *
- * $FreeBSD$
- */
-
-#define MAPFILEENTRIES 64
-#define GMAPFILEENTRIES 16
-#define NOBODY 32767
-#define NULLGROUP 65534
-
-struct umap_args {
- char *target; /* Target of loopback */
- int nentries; /* # of entries in user map array */
- int gnentries; /* # of entries in group map array */
- u_long (*mapdata)[2]; /* pointer to array of user mappings */
- u_long (*gmapdata)[2]; /* pointer to array of group mappings */
-};
-
-struct umap_mount {
- struct mount *umapm_vfs;
- struct vnode *umapm_rootvp; /* Reference to root umap_node */
- int info_nentries; /* number of uid mappings */
- int info_gnentries; /* number of gid mappings */
- u_long info_mapdata[MAPFILEENTRIES][2]; /* mapping data for
- user mapping in ficus */
- u_long info_gmapdata[GMAPFILEENTRIES][2]; /*mapping data for
- group mapping in ficus */
-};
-
-#ifdef _KERNEL
-/*
- * A cache of vnode references
- */
-struct umap_node {
- 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 */
-};
-
-extern int umapfs_init __P((struct vfsconf *vfsp));
-extern int umap_node_create __P((struct mount *mp, struct vnode *target, struct vnode **vpp));
-extern u_long umap_reverse_findid __P((u_long id, u_long map[][2], int nentries));
-extern void umap_mapids __P((struct mount *v_mount, struct ucred *credp));
-
-#define MOUNTTOUMAPMOUNT(mp) ((struct umap_mount *)((mp)->mnt_data))
-#define VTOUMAP(vp) ((struct umap_node *)(vp)->v_data)
-#define UMAPTOV(xp) ((xp)->umap_vnode)
-#ifdef DIAGNOSTIC
-extern struct vnode *umap_checkvp __P((struct vnode *vp, char *fil, int lno));
-#define UMAPVPTOLOWERVP(vp) umap_checkvp((vp), __FILE__, __LINE__)
-#else
-#define UMAPVPTOLOWERVP(vp) (VTOUMAP(vp)->umap_lowervp)
-#endif
-
-extern vop_t **umap_vnodeop_p;
-#endif /* _KERNEL */
diff --git a/sys/miscfs/umapfs/umap_subr.c b/sys/miscfs/umapfs/umap_subr.c
deleted file mode 100644
index 1f94d50..0000000
--- a/sys/miscfs/umapfs/umap_subr.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * 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
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)umap_subr.c 8.9 (Berkeley) 5/14/95
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-
-#include <miscfs/umapfs/umap.h>
-
-#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
-#define NUMAPNODECACHE 16
-
-/*
- * Null layer cache:
- * Each cache entry holds a reference to the target vnode
- * along with a pointer to the alias vnode. When an
- * entry is added the target vnode is VREF'd. When the
- * alias is removed the target vnode is vrele'd.
- */
-
-#define UMAP_NHASH(vp) \
- (&umap_node_hashtbl \
- [((uintptr_t)(void *)(vp) >> LOG2_SIZEVNODE) & umap_node_hash])
-static LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
-static 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));
-
-/*
- * Initialise cache headers
- */
-int
-umapfs_init(vfsp)
- struct vfsconf *vfsp;
-{
-
-#ifdef DEBUG
- printf("umapfs_init\n"); /* printed during system boot */
-#endif
- umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
- return (0);
-}
-
-/*
- * umap_findid is called by various routines in umap_vnodeops.c to
- * find a user or group id in a map.
- */
-static u_long
-umap_findid(id, map, nentries)
- u_long id;
- u_long map[][2];
- int nentries;
-{
- int i;
-
- /* Find uid entry in map */
- i = 0;
- while ((i<nentries) && ((map[i][0]) != id))
- i++;
-
- if (i < nentries)
- return (map[i][1]);
- else
- return (-1);
-
-}
-
-/*
- * umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to
- * find a user or group id in a map, in reverse.
- */
-u_long
-umap_reverse_findid(id, map, nentries)
- u_long id;
- u_long map[][2];
- int nentries;
-{
- int i;
-
- /* Find uid entry in map */
- i = 0;
- while ((i<nentries) && ((map[i][1]) != id))
- i++;
-
- if (i < nentries)
- return (map[i][0]);
- else
- return (-1);
-
-}
-
-/*
- * Return alias for target vnode if already exists, else 0.
- */
-static struct vnode *
-umap_node_find(mp, targetvp)
- struct mount *mp;
- struct vnode *targetvp;
-{
- struct proc *p = curproc; /* XXX */
- struct umap_node_hashhead *hd;
- struct umap_node *a;
- struct vnode *vp;
-
-#ifdef DEBUG
- printf("umap_node_find(mp = %p, target = %p)\n",
- (void *)mp, (void *)targetvp);
-#endif
-
- /*
- * Find hash base, and then search the (two-way) linked
- * list looking for a umap_node structure which is referencing
- * the target vnode. If found, the increment the umap_node
- * reference count (but NOT the target vnode's VREF counter).
- */
- hd = UMAP_NHASH(targetvp);
-loop:
- LIST_FOREACH(a, hd, umap_hash) {
- if (a->umap_lowervp == targetvp &&
- a->umap_vnode->v_mount == mp) {
- vp = UMAPTOV(a);
- /*
- * We need vget for the VXLOCK
- * stuff, but we don't want to lock
- * the lower node.
- */
- if (vget(vp, 0, p)) {
-#ifdef DEBUG
- printf ("umap_node_find: vget failed.\n");
-#endif
- goto loop;
- }
- return (vp);
- }
- }
-
-#ifdef DEBUG
- printf("umap_node_find(%p, %p): NOT found\n",
- (void *)mp, (void *)targetvp);
-#endif
-
- return (0);
-}
-
-/*
- * Make a new umap_node node.
- * Vp is the alias vnode, lofsvp is the target vnode.
- * Maintain a reference to (targetvp).
- */
-static int
-umap_node_alloc(mp, lowervp, vpp)
- struct mount *mp;
- struct vnode *lowervp;
- struct vnode **vpp;
-{
- struct umap_node_hashhead *hd;
- struct umap_node *xp;
- struct vnode *othervp, *vp;
- int error;
-
- /* XXX This routine probably needs a node_alloc lock */
-
- /*
- * 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(xp, struct umap_node *, sizeof(struct umap_node),
- M_TEMP, M_WAITOK);
-
- error = getnewvnode(VT_UMAP, mp, umap_vnodeop_p, vpp);
- if (error) {
- FREE(xp, M_TEMP);
- return (error);
- }
- vp = *vpp;
-
- vp->v_type = lowervp->v_type;
- xp->umap_vnode = vp;
- vp->v_data = xp;
- xp->umap_lowervp = lowervp;
- /*
- * Before we insert our new node onto the hash chains,
- * check to see if someone else has beaten us to it.
- * (We could have slept in MALLOC.)
- */
- othervp = umap_node_find(mp, lowervp);
- if (othervp) {
- FREE(xp, M_TEMP);
- vp->v_type = VBAD; /* node is discarded */
- vp->v_usecount = 0; /* XXX */
- *vpp = othervp;
- return (0);
- }
- VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */
- hd = UMAP_NHASH(lowervp);
- LIST_INSERT_HEAD(hd, xp, umap_hash);
- return (0);
-}
-
-
-/*
- * Try to find an existing umap_node vnode refering
- * to it, otherwise make a new umap_node vnode which
- * contains a reference to the target vnode.
- */
-int
-umap_node_create(mp, targetvp, newvpp)
- struct mount *mp;
- struct vnode *targetvp;
- struct vnode **newvpp;
-{
- struct vnode *aliasvp;
-
- aliasvp = umap_node_find(mp, targetvp);
- if (aliasvp) {
- /*
- * Take another reference to the alias vnode
- */
-#ifdef DEBUG
- vprint("umap_node_create: exists", aliasvp);
-#endif
- /* VREF(aliasvp); */
- } else {
- int error;
-
- /*
- * Get new vnode.
- */
-#ifdef DEBUG
- printf("umap_node_create: create new alias vnode\n");
-#endif
- /*
- * Make new vnode reference the umap_node.
- */
- error = umap_node_alloc(mp, targetvp, &aliasvp);
- if (error)
- return (error);
-
- /*
- * aliasvp is already VREF'd by getnewvnode()
- */
- }
-
- vrele(targetvp);
-
-#ifdef DEBUG
- vprint("umap_node_create: alias", aliasvp);
- vprint("umap_node_create: target", targetvp);
-#endif
-
- *newvpp = aliasvp;
- return (0);
-}
-
-#ifdef DIAGNOSTIC
-int umap_checkvp_barrier = 1;
-struct vnode *
-umap_checkvp(vp, fil, lno)
- struct vnode *vp;
- char *fil;
- int lno;
-{
- struct umap_node *a = VTOUMAP(vp);
-#if 0
- /*
- * Can't do this check because vop_reclaim runs
- * with funny vop vector.
- */
- if (vp->v_op != umap_vnodeop_p) {
- printf ("umap_checkvp: on non-umap-node\n");
- while (umap_checkvp_barrier) /*WAIT*/ ;
- panic("umap_checkvp");
- }
-#endif
- if (a->umap_lowervp == NULL) {
- /* Should never happen */
- int i; u_long *p;
- printf("vp = %p, ZERO ptr\n", (void *)vp);
- for (p = (u_long *) a, i = 0; i < 8; i++)
- printf(" %p", (void *)p[i]);
- printf("\n");
- /* wait for debugger */
- while (umap_checkvp_barrier) /*WAIT*/ ;
- panic("umap_checkvp");
- }
- if (a->umap_lowervp->v_usecount < 1) {
- int i; u_long *p;
- printf("vp = %p, unref'ed lowervp\n", (void *)vp);
- for (p = (u_long *) a, i = 0; i < 8; i++)
- printf(" %p", (void *)p[i]);
- printf("\n");
- /* wait for debugger */
- while (umap_checkvp_barrier) /*WAIT*/ ;
- panic ("umap with unref'ed lowervp");
- }
-#if 0
- printf("umap %x/%d -> %x/%d [%s, %d]\n",
- a->umap_vnode, a->umap_vnode->v_usecount,
- a->umap_lowervp, a->umap_lowervp->v_usecount,
- fil, lno);
-#endif
- return (a->umap_lowervp);
-}
-#endif /* DIAGNOSTIC */
-
-/* umap_mapids maps all of the ids in a credential, both user and group. */
-
-void
-umap_mapids(v_mount, credp)
- struct mount *v_mount;
- struct ucred *credp;
-{
- int i;
- uid_t uid;
- gid_t gid;
-
- if (credp == NOCRED)
- return;
-
- /* Find uid entry in map */
-
- uid = (uid_t) umap_findid(credp->cr_uid,
- MOUNTTOUMAPMOUNT(v_mount)->info_mapdata,
- MOUNTTOUMAPMOUNT(v_mount)->info_nentries);
-
- if (uid != -1)
- credp->cr_uid = uid;
- else
- credp->cr_uid = (uid_t) NOBODY;
-
-#ifdef notdef
- /* cr_gid is the same as cr_groups[0] in 4BSD */
-
- /* Find gid entry in map */
-
- gid = (gid_t) umap_findid(credp->cr_gid,
- MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata,
- MOUNTTOUMAPMOUNT(v_mount)->info_gnentries);
-
- if (gid != -1)
- credp->cr_gid = gid;
- else
- credp->cr_gid = NULLGROUP;
-#endif
-
- /* Now we must map each of the set of groups in the cr_groups
- structure. */
-
- i = 0;
- while (credp->cr_groups[i] != 0) {
- gid = (gid_t) umap_findid(credp->cr_groups[i],
- MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata,
- MOUNTTOUMAPMOUNT(v_mount)->info_gnentries);
-
- if (gid != -1)
- credp->cr_groups[i++] = gid;
- else
- credp->cr_groups[i++] = NULLGROUP;
- }
-}
diff --git a/sys/miscfs/umapfs/umap_vfsops.c b/sys/miscfs/umapfs/umap_vfsops.c
deleted file mode 100644
index 280ded9..0000000
--- a/sys/miscfs/umapfs/umap_vfsops.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * 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
- * the UCLA Ficus project.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
- *
- * $FreeBSD$
- */
-
-/*
- * Umap Layer
- * (See mount_umap(8) for a description of this layer.)
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/vnode.h>
-
-#include <miscfs/umapfs/umap.h>
-
-static MALLOC_DEFINE(M_UMAPFSMNT, "UMAP mount", "UMAP mount structure");
-
-static int umapfs_fhtovp __P((struct mount *mp, struct fid *fidp,
- struct vnode **vpp));
-static int umapfs_checkexp __P((struct mount *mp, struct sockaddr *nam,
- int *extflagsp, struct ucred **credanonp));
-static int umapfs_mount __P((struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, struct proc *p));
-static int umapfs_quotactl __P((struct mount *mp, int cmd, uid_t uid,
- caddr_t arg, struct proc *p));
-static int umapfs_root __P((struct mount *mp, struct vnode **vpp));
-static int umapfs_start __P((struct mount *mp, int flags, struct proc *p));
-static int umapfs_statfs __P((struct mount *mp, struct statfs *sbp,
- struct proc *p));
-static int umapfs_sync __P((struct mount *mp, int waitfor,
- struct ucred *cred, struct proc *p));
-static int umapfs_unmount __P((struct mount *mp, int mntflags,
- struct proc *p));
-static int umapfs_vget __P((struct mount *mp, ino_t ino,
- struct vnode **vpp));
-static int umapfs_vptofh __P((struct vnode *vp, struct fid *fhp));
-static int umapfs_extattrctl __P((struct mount *mp, int cmd,
- struct vnode *filename_vp,
- int namespace, const char *attrname,
- struct proc *p));
-
-/*
- * Mount umap layer
- */
-static int
-umapfs_mount(mp, path, data, ndp, p)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct proc *p;
-{
- struct umap_args args;
- struct vnode *lowerrootvp, *vp;
- struct vnode *umapm_rootvp;
- struct umap_mount *amp;
- u_int size;
- int error;
-#ifdef DEBUG
- int i;
-#endif
-
- /*
- * Only for root
- */
- if ((error = suser(p)) != 0)
- return (error);
-
-#ifdef DEBUG
- printf("umapfs_mount(mp = %p)\n", (void *)mp);
-#endif
-
- /*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- return (EOPNOTSUPP);
- /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
- }
-
- /*
- * Get argument
- */
- error = copyin(data, (caddr_t)&args, sizeof(struct umap_args));
- if (error)
- return (error);
-
- /*
- * Find lower node
- */
- NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
- UIO_USERSPACE, args.target, p);
- error = namei(ndp);
- if (error)
- return (error);
- NDFREE(ndp, NDF_ONLY_PNBUF);
-
- /*
- * Sanity check on lower vnode
- */
- lowerrootvp = ndp->ni_vp;
-#ifdef DEBUG
- printf("vp = %p, check for VDIR...\n", (void *)lowerrootvp);
-#endif
- vrele(ndp->ni_dvp);
- ndp->ni_dvp = 0;
-
- if (lowerrootvp->v_type != VDIR) {
- vput(lowerrootvp);
- return (EINVAL);
- }
-
-#ifdef DEBUG
- printf("mp = %p\n", (void *)mp);
-#endif
-
- amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
- M_UMAPFSMNT, M_WAITOK); /* XXX */
-
- /*
- * Save reference to underlying FS
- */
- amp->umapm_vfs = lowerrootvp->v_mount;
-
- /*
- * Now copy in the number of entries and maps for umap mapping.
- */
- amp->info_nentries = args.nentries;
- amp->info_gnentries = args.gnentries;
- error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
- 2*sizeof(u_long)*args.nentries);
- if (error)
- return (error);
-
-#ifdef DEBUG
- printf("umap_mount:nentries %d\n",args.nentries);
- for (i = 0; i < args.nentries; i++)
- printf(" %lu maps to %lu\n", amp->info_mapdata[i][0],
- amp->info_mapdata[i][1]);
-#endif
-
- error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
- 2*sizeof(u_long)*args.gnentries);
- if (error)
- return (error);
-
-#ifdef DEBUG
- printf("umap_mount:gnentries %d\n",args.gnentries);
- for (i = 0; i < args.gnentries; i++)
- printf(" group %lu maps to %lu\n",
- amp->info_gmapdata[i][0],
- amp->info_gmapdata[i][1]);
-#endif
-
-
- /*
- * Save reference. Each mount also holds
- * a reference on the root vnode.
- */
- error = umap_node_create(mp, lowerrootvp, &vp);
- /*
- * Unlock the node (either the lower or the alias)
- */
- VOP_UNLOCK(vp, 0, p);
- /*
- * Make sure the node alias worked
- */
- if (error) {
- vrele(lowerrootvp);
- free(amp, M_UMAPFSMNT); /* XXX */
- return (error);
- }
-
- /*
- * Keep a held reference to the root vnode.
- * It is vrele'd in umapfs_unmount.
- */
- umapm_rootvp = vp;
- umapm_rootvp->v_flag |= VROOT;
- amp->umapm_rootvp = umapm_rootvp;
- if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
- mp->mnt_flag |= MNT_LOCAL;
- mp->mnt_data = (qaddr_t) amp;
- vfs_getnewfsid(mp);
-
- (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
- &size);
- bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
- (void)umapfs_statfs(mp, &mp->mnt_stat, p);
-#ifdef DEBUG
- printf("umapfs_mount: lower %s, alias at %s\n",
- mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
-#endif
- return (0);
-}
-
-/*
- * VFS start. Nothing needed here - the start routine
- * on the underlying filesystem will have been called
- * when that filesystem was mounted.
- */
-static int
-umapfs_start(mp, flags, p)
- struct mount *mp;
- int flags;
- struct proc *p;
-{
- return (0);
- /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
-}
-
-/*
- * Free reference to umap layer
- */
-static int
-umapfs_unmount(mp, mntflags, p)
- struct mount *mp;
- int mntflags;
- struct proc *p;
-{
- int error;
- int flags = 0;
-
-#ifdef DEBUG
- printf("umapfs_unmount(mp = %p)\n", (void *)mp);
-#endif
-
- if (mntflags & MNT_FORCE)
- flags |= FORCECLOSE;
-
- /*
- * Clear out buffer cache. I don't think we
- * ever get anything cached at this level at the
- * moment, but who knows...
- */
-#ifdef notyet
- mntflushbuf(mp, 0);
- if (mntinvalbuf(mp, 1))
- return (EBUSY);
-#endif
- /* There is 1 extra root vnode reference (umapm_rootvp). */
- error = vflush(mp, 1, flags);
- if (error)
- return (error);
-
- /*
- * Finally, throw away the umap_mount structure
- */
- free(mp->mnt_data, M_UMAPFSMNT); /* XXX */
- mp->mnt_data = 0;
- return (0);
-}
-
-static int
-umapfs_root(mp, vpp)
- struct mount *mp;
- struct vnode **vpp;
-{
- struct proc *p = curproc; /* XXX */
- struct vnode *vp;
-
-#ifdef DEBUG
- printf("umapfs_root(mp = %p, vp = %p->%p)\n",
- (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
- (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
-#endif
-
- /*
- * Return locked reference to root.
- */
- vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
- VREF(vp);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- *vpp = vp;
- return (0);
-}
-
-static int
-umapfs_quotactl(mp, cmd, uid, arg, p)
- struct mount *mp;
- int cmd;
- uid_t uid;
- caddr_t arg;
- struct proc *p;
-{
- return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
-}
-
-static int
-umapfs_statfs(mp, sbp, p)
- struct mount *mp;
- struct statfs *sbp;
- struct proc *p;
-{
- int error;
- struct statfs mstat;
-
-#ifdef DEBUG
- printf("umapfs_statfs(mp = %p, vp = %p->%p)\n",
- (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
- (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
-#endif
-
- bzero(&mstat, sizeof(mstat));
-
- error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
- if (error)
- return (error);
-
- /* now copy across the "interesting" information and fake the rest */
- sbp->f_type = mstat.f_type;
- sbp->f_flags = mstat.f_flags;
- sbp->f_bsize = mstat.f_bsize;
- sbp->f_iosize = mstat.f_iosize;
- sbp->f_blocks = mstat.f_blocks;
- sbp->f_bfree = mstat.f_bfree;
- sbp->f_bavail = mstat.f_bavail;
- sbp->f_files = mstat.f_files;
- sbp->f_ffree = mstat.f_ffree;
- if (sbp != &mp->mnt_stat) {
- bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
- bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
- bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
- }
- return (0);
-}
-
-static int
-umapfs_sync(mp, waitfor, cred, p)
- struct mount *mp;
- int waitfor;
- struct ucred *cred;
- struct proc *p;
-{
- /*
- * XXX - Assumes no data cached at umap layer.
- */
- return (0);
-}
-
-static int
-umapfs_vget(mp, ino, vpp)
- struct mount *mp;
- ino_t ino;
- struct vnode **vpp;
-{
-
- return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
-}
-
-static int
-umapfs_fhtovp(mp, fidp, vpp)
- struct mount *mp;
- struct fid *fidp;
- struct vnode **vpp;
-{
-
- return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, vpp));
-}
-
-static int
-umapfs_checkexp(mp, nam, exflagsp, credanonp)
- struct mount *mp;
- struct sockaddr *nam;
- int *exflagsp;
- struct ucred **credanonp;
-{
-
- return (VFS_CHECKEXP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, nam,
- exflagsp, credanonp));
-}
-
-static int
-umapfs_vptofh(vp, fhp)
- struct vnode *vp;
- struct fid *fhp;
-{
- return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
-}
-
-static int
-umapfs_extattrctl(mp, cmd, filename_vp, namespace, attrname, p)
- struct mount *mp;
- int cmd;
- struct vnode *filename_vp;
- int namespace;
- const char *attrname;
- struct proc *p;
-{
- return (VFS_EXTATTRCTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd,
- filename_vp, namespace, attrname, p));
-}
-
-
-static struct vfsops umap_vfsops = {
- umapfs_mount,
- umapfs_start,
- umapfs_unmount,
- umapfs_root,
- umapfs_quotactl,
- umapfs_statfs,
- umapfs_sync,
- umapfs_vget,
- umapfs_fhtovp,
- umapfs_checkexp,
- umapfs_vptofh,
- umapfs_init,
- vfs_stduninit,
- umapfs_extattrctl,
-};
-
-VFS_SET(umap_vfsops, umap, VFCF_LOOPBACK);
diff --git a/sys/miscfs/umapfs/umap_vnops.c b/sys/miscfs/umapfs/umap_vnops.c
deleted file mode 100644
index 5bf29c8..0000000
--- a/sys/miscfs/umapfs/umap_vnops.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * the UCLA Ficus project.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)umap_vnops.c 8.6 (Berkeley) 5/22/95
- * $FreeBSD$
- */
-
-/*
- * Umap Layer
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/sysctl.h>
-#include <sys/vnode.h>
-
-#include <miscfs/umapfs/umap.h>
-#include <miscfs/nullfs/null.h>
-
-static int umap_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
-SYSCTL_INT(_debug, OID_AUTO, umapfs_bug_bypass, CTLFLAG_RW,
- &umap_bug_bypass, 0, "");
-
-static int umap_bypass __P((struct vop_generic_args *ap));
-static int umap_getattr __P((struct vop_getattr_args *ap));
-static int umap_inactive __P((struct vop_inactive_args *ap));
-static int umap_lock __P((struct vop_lock_args *ap));
-static int umap_print __P((struct vop_print_args *ap));
-static int umap_reclaim __P((struct vop_reclaim_args *ap));
-static int umap_rename __P((struct vop_rename_args *ap));
-static int umap_unlock __P((struct vop_unlock_args *ap));
-
-/*
- * This is the 10-Apr-92 bypass routine.
- * See null_vnops.c:null_bypass for more details.
- */
-static int
-umap_bypass(ap)
- struct vop_generic_args /* {
- struct vnodeop_desc *a_desc;
- <other random data follows, presumably>
- } */ *ap;
-{
- struct ucred **credpp = 0, *credp = 0;
- struct ucred *savecredp = 0, *savecompcredp = 0;
- struct ucred *compcredp = 0;
- struct vnode **this_vp_p;
- int error;
- struct vnode *old_vps[VDESC_MAX_VPS];
- struct vnode *vp1 = 0;
- struct vnode **vps_p[VDESC_MAX_VPS];
- struct vnode ***vppp;
- struct vnodeop_desc *descp = ap->a_desc;
- int reles, i;
- struct componentname **compnamepp = 0;
-
- if (umap_bug_bypass)
- printf ("umap_bypass: %s\n", descp->vdesc_name);
-
-#ifdef DIAGNOSTIC
- /*
- * We require at least one vp.
- */
- if (descp->vdesc_vp_offsets == NULL ||
- descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
- panic ("umap_bypass: no vp's in map");
-#endif
-
- /*
- * Map the vnodes going in.
- * Later, we'll invoke the operation based on
- * the first mapped vnode's operation vector.
- */
- reles = descp->vdesc_flags;
- for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
- if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
- break; /* bail out at end of list */
- vps_p[i] = this_vp_p =
- VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i], ap);
-
- if (i == 0) {
- vp1 = *vps_p[0];
- }
-
- /*
- * We're not guaranteed that any but the first vnode
- * are of our type. Check for and don't map any
- * that aren't. (Must map first vp or vclean fails.)
- */
-
- if (i && (*this_vp_p)->v_op != umap_vnodeop_p) {
- old_vps[i] = NULL;
- } else {
- old_vps[i] = *this_vp_p;
- *(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
- if (reles & 1)
- VREF(*this_vp_p);
- }
-
- }
-
- /*
- * Fix the credentials. (That's the purpose of this layer.)
- */
-
- if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
-
- credpp = VOPARG_OFFSETTO(struct ucred**,
- descp->vdesc_cred_offset, ap);
-
- /* Save old values */
-
- savecredp = (*credpp);
- if (savecredp != NOCRED)
- (*credpp) = crdup(savecredp);
- credp = *credpp;
-
- if (umap_bug_bypass && credp->cr_uid != 0)
- printf("umap_bypass: user was %lu, group %lu\n",
- (u_long)credp->cr_uid, (u_long)credp->cr_gid);
-
- /* Map all ids in the credential structure. */
-
- umap_mapids(vp1->v_mount, credp);
-
- if (umap_bug_bypass && credp->cr_uid != 0)
- printf("umap_bypass: user now %lu, group %lu\n",
- (u_long)credp->cr_uid, (u_long)credp->cr_gid);
- }
-
- /* BSD often keeps a credential in the componentname structure
- * for speed. If there is one, it better get mapped, too.
- */
-
- if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
-
- compnamepp = VOPARG_OFFSETTO(struct componentname**,
- descp->vdesc_componentname_offset, ap);
-
- compcredp = (*compnamepp)->cn_cred;
- savecompcredp = compcredp;
- if (savecompcredp != NOCRED)
- (*compnamepp)->cn_cred = crdup(savecompcredp);
- compcredp = (*compnamepp)->cn_cred;
-
- if (umap_bug_bypass && compcredp->cr_uid != 0)
- printf(
- "umap_bypass: component credit user was %lu, group %lu\n",
- (u_long)compcredp->cr_uid,
- (u_long)compcredp->cr_gid);
-
- /* Map all ids in the credential structure. */
-
- umap_mapids(vp1->v_mount, compcredp);
-
- if (umap_bug_bypass && compcredp->cr_uid != 0)
- printf(
- "umap_bypass: component credit user now %lu, group %lu\n",
- (u_long)compcredp->cr_uid,
- (u_long)compcredp->cr_gid);
- }
-
- /*
- * Call the operation on the lower layer
- * with the modified argument structure.
- */
- error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
-
- /*
- * Maintain the illusion of call-by-value
- * by restoring vnodes in the argument structure
- * to their original value.
- */
- reles = descp->vdesc_flags;
- for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
- if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
- break; /* bail out at end of list */
- if (old_vps[i]) {
- *(vps_p[i]) = old_vps[i];
- if (reles & 1)
- vrele(*(vps_p[i]));
- };
- };
-
- /*
- * Map the possible out-going vpp
- * (Assumes that the lower layer always returns
- * a VREF'ed vpp unless it gets an error.)
- */
- if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
- !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
- !error) {
- if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
- goto out;
- vppp = VOPARG_OFFSETTO(struct vnode***,
- descp->vdesc_vpp_offset, ap);
- if (*vppp)
- error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp);
- };
-
- out:
- /*
- * Free duplicate cred structure and restore old one.
- */
- if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
- if (umap_bug_bypass && credp && credp->cr_uid != 0)
- printf("umap_bypass: returning-user was %lu\n",
- (u_long)credp->cr_uid);
-
- if (savecredp != NOCRED) {
- crfree(credp);
- (*credpp) = savecredp;
- if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
- printf(
- "umap_bypass: returning-user now %lu\n\n",
- (u_long)(*credpp)->cr_uid);
- }
- }
-
- if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
- if (umap_bug_bypass && compcredp && compcredp->cr_uid != 0)
- printf(
- "umap_bypass: returning-component-user was %lu\n",
- (u_long)compcredp->cr_uid);
-
- if (savecompcredp != NOCRED) {
- crfree(compcredp);
- (*compnamepp)->cn_cred = savecompcredp;
- if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
- printf(
- "umap_bypass: returning-component-user now %lu\n",
- (u_long)compcredp->cr_uid);
- }
- }
-
- return (error);
-}
-
-
-/*
- * We handle getattr to change the fsid.
- */
-static int
-umap_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- short uid, gid;
- int error, tmpid, nentries, gnentries;
- u_long (*mapdata)[2], (*gmapdata)[2];
- struct vnode **vp1p;
- struct vnodeop_desc *descp = ap->a_desc;
-
- error = umap_bypass((struct vop_generic_args *)ap);
- if (error)
- return (error);
-
- /*
- * Umap needs to map the uid and gid returned by a stat
- * into the proper values for this site. This involves
- * finding the returned uid in the mapping information,
- * translating it into the uid on the other end,
- * and filling in the proper field in the vattr
- * structure pointed to by ap->a_vap. The group
- * is easier, since currently all groups will be
- * translate to the NULLGROUP.
- */
-
- /* Find entry in map */
-
- uid = ap->a_vap->va_uid;
- gid = ap->a_vap->va_gid;
- if (umap_bug_bypass)
- printf("umap_getattr: mapped uid = %d, mapped gid = %d\n", uid,
- gid);
-
- vp1p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap);
- nentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries;
- mapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata);
- gnentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries;
- gmapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata);
-
- /* Reverse map the uid for the vnode. Since it's a reverse
- map, we can't use umap_mapids() to do it. */
-
- tmpid = umap_reverse_findid(uid, mapdata, nentries);
-
- if (tmpid != -1) {
-
- ap->a_vap->va_uid = (uid_t) tmpid;
- if (umap_bug_bypass)
- printf("umap_getattr: original uid = %d\n", uid);
- } else
- ap->a_vap->va_uid = (uid_t) NOBODY;
-
- /* Reverse map the gid for the vnode. */
-
- tmpid = umap_reverse_findid(gid, gmapdata, gnentries);
-
- if (tmpid != -1) {
-
- ap->a_vap->va_gid = (gid_t) tmpid;
- if (umap_bug_bypass)
- printf("umap_getattr: original gid = %d\n", gid);
- } else
- ap->a_vap->va_gid = (gid_t) NULLGROUP;
-
- 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.
- */
-static 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((struct vop_generic_args *)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;
-{
- vop_nounlock(ap);
- ap->a_flags &= ~LK_INTERLOCK;
- return (null_bypass((struct vop_generic_args *)ap));
-}
-
-static int
-umap_inactive(ap)
- struct vop_inactive_args /* {
- struct vnode *a_vp;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct umap_node *xp = VTOUMAP(vp);
- struct vnode *lowervp = xp->umap_lowervp;
- /*
- * Do nothing (and _don't_ bypass).
- * Wait to vrele lowervp until reclaim,
- * so that until then our umap_node is in the
- * cache and reusable.
- *
- */
- VOP_INACTIVE(lowervp, ap->a_p);
- VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
- return (0);
-}
-
-static int
-umap_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct umap_node *xp = VTOUMAP(vp);
- struct vnode *lowervp = xp->umap_lowervp;
-
- /* After this assignment, this node will not be re-used. */
- xp->umap_lowervp = NULL;
- LIST_REMOVE(xp, umap_hash);
- FREE(vp->v_data, M_TEMP);
- vp->v_data = NULL;
- vrele(lowervp);
- return (0);
-}
-
-static int
-umap_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- printf("\ttag VT_UMAPFS, vp=%p, lowervp=%p\n", vp, UMAPVPTOLOWERVP(vp));
- return (0);
-}
-
-static int
-umap_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
-{
- int error;
- struct componentname *compnamep;
- struct ucred *compcredp, *savecompcredp;
- struct vnode *vp;
-
- /*
- * Rename is irregular, having two componentname structures.
- * We need to map the cre in the second structure,
- * and then bypass takes care of the rest.
- */
-
- vp = ap->a_fdvp;
- compnamep = ap->a_tcnp;
- compcredp = compnamep->cn_cred;
-
- savecompcredp = compcredp;
- compcredp = compnamep->cn_cred = crdup(savecompcredp);
-
- if (umap_bug_bypass && compcredp->cr_uid != 0)
- printf(
- "umap_rename: rename component credit user was %lu, group %lu\n",
- (u_long)compcredp->cr_uid, (u_long)compcredp->cr_gid);
-
- /* Map all ids in the credential structure. */
-
- umap_mapids(vp->v_mount, compcredp);
-
- if (umap_bug_bypass && compcredp->cr_uid != 0)
- printf(
- "umap_rename: rename component credit user now %lu, group %lu\n",
- (u_long)compcredp->cr_uid, (u_long)compcredp->cr_gid);
-
- error = umap_bypass((struct vop_generic_args *)ap);
-
- /* Restore the additional mapped componentname cred structure. */
-
- crfree(compcredp);
- compnamep->cn_cred = savecompcredp;
-
- return error;
-}
-
-/*
- * Global vfs data structures
- */
-/*
- * XXX - strategy, bwrite are hand coded currently. They should
- * go away with a merged buffer/block cache.
- *
- */
-vop_t **umap_vnodeop_p;
-static struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) umap_bypass },
- { &vop_getattr_desc, (vop_t *) umap_getattr },
- { &vop_inactive_desc, (vop_t *) umap_inactive },
- { &vop_lock_desc, (vop_t *) umap_lock },
- { &vop_print_desc, (vop_t *) umap_print },
- { &vop_reclaim_desc, (vop_t *) umap_reclaim },
- { &vop_rename_desc, (vop_t *) umap_rename },
- { &vop_unlock_desc, (vop_t *) umap_unlock },
- { NULL, NULL }
-};
-static struct vnodeopv_desc umap_vnodeop_opv_desc =
- { &umap_vnodeop_p, umap_vnodeop_entries };
-
-VNODEOP_SET(umap_vnodeop_opv_desc);
diff --git a/sys/miscfs/union/union.h b/sys/miscfs/union/union.h
deleted file mode 100644
index 63a881c..0000000
--- a/sys/miscfs/union/union.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994 Jan-Simon Pendry.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)union.h 8.9 (Berkeley) 12/10/94
- * $FreeBSD$
- */
-
-struct union_args {
- char *target; /* Target of loopback */
- int mntflags; /* Options on the mount */
-};
-
-#define UNMNT_ABOVE 0x0001 /* Target appears below mount point */
-#define UNMNT_BELOW 0x0002 /* Target appears below mount point */
-#define UNMNT_REPLACE 0x0003 /* Target replaces mount point */
-#define UNMNT_OPMASK 0x0003
-
-struct union_mount {
- struct vnode *um_uppervp; /* UN_ULOCK holds locking state */
- struct vnode *um_lowervp; /* Left unlocked */
- struct ucred *um_cred; /* Credentials of user calling mount */
- int um_cmode; /* cmask from mount process */
- int um_op; /* Operation mode */
-};
-
-#ifdef _KERNEL
-
-#ifndef DIAGNOSTIC
-#define DIAGNOSTIC
-#endif
-
-/*
- * DEFDIRMODE is the mode bits used to create a shadow directory.
- */
-#define VRWXMODE (VREAD|VWRITE|VEXEC)
-#define VRWMODE (VREAD|VWRITE)
-#define UN_DIRMODE ((VRWXMODE)|(VRWXMODE>>3)|(VRWXMODE>>6))
-#define UN_FILEMODE ((VRWMODE)|(VRWMODE>>3)|(VRWMODE>>6))
-
-/*
- * A cache of vnode references (hangs off v_data)
- *
- * Placing un_lock as the first elements theoretically allows us to
- * use the vop_stdlock functions. However, we need to make sure of
- * certain side effects so we will still punch in our own code.
- */
-struct union_node {
- struct lock un_lock;
- LIST_ENTRY(union_node) un_cache; /* Hash chain */
- struct vnode *un_vnode; /* Back pointer */
- 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_openl; /* # of opens on lowervp */
- int un_exclcnt; /* exclusive count */
- 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
-};
-
-/*
- * XXX UN_ULOCK - indicates that the uppervp is locked
- *
- * UN_CACHED - node is in the union cache
- */
-
-/*#define UN_ULOCK 0x04*/ /* Upper node is locked */
-#define UN_CACHED 0x10 /* In union cache */
-
-/*
- * Hash table locking flags
- */
-
-#define UNVP_WANT 0x01
-#define UNVP_LOCKED 0x02
-
-extern int union_allocvp __P((struct vnode **, struct mount *,
- struct vnode *,
- struct vnode *,
- struct componentname *, struct vnode *,
- struct vnode *, int));
-extern int union_freevp __P((struct vnode *));
-extern struct vnode *union_dircache __P((struct vnode *, 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_cn_close __P((struct vnode *, int, struct ucred *,
- struct proc *));
-extern void union_removed_upper __P((struct union_node *un));
-extern struct vnode *union_lowervp __P((struct vnode *));
-extern void union_newsize __P((struct vnode *, off_t, off_t));
-
-extern int (*union_dircheckp) __P((struct proc *, struct vnode **,
- struct file *));
-
-#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
-#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
-#define UNIONTOV(un) ((un)->un_vnode)
-#define LOWERVP(vp) (VTOUNION(vp)->un_lowervp)
-#define UPPERVP(vp) (VTOUNION(vp)->un_uppervp)
-#define OTHERVP(vp) (UPPERVP(vp) ? UPPERVP(vp) : LOWERVP(vp))
-
-#define UDEBUG(x) if (uniondebug) printf x
-#define UDEBUG_ENABLED 1
-
-extern vop_t **union_vnodeop_p;
-extern struct vfsops union_vfsops;
-extern int uniondebug;
-
-#endif /* _KERNEL */
diff --git a/sys/miscfs/union/union_subr.c b/sys/miscfs/union/union_subr.c
deleted file mode 100644
index ce38e2d..0000000
--- a/sys/miscfs/union/union_subr.c
+++ /dev/null
@@ -1,1360 +0,0 @@
-/*
- * Copyright (c) 1994 Jan-Simon Pendry
- * Copyright (c) 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)union_subr.c 8.20 (Berkeley) 5/20/95
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/fcntl.h>
-#include <sys/file.h>
-#include <sys/filedesc.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/namei.h>
-#include <sys/stat.h>
-#include <sys/vnode.h>
-
-#include <vm/vm.h>
-#include <vm/vm_extern.h> /* for vnode_pager_setsize */
-#include <vm/vm_zone.h>
-#include <vm/vm_object.h> /* for vm cache coherency */
-
-#include <miscfs/union/union.h>
-
-#include <sys/proc.h>
-
-extern int union_init __P((void));
-
-/* must be power of two, otherwise change UNION_HASH() */
-#define NHASH 32
-
-/* unsigned int ... */
-#define UNION_HASH(u, l) \
- (((((uintptr_t) (u)) + ((uintptr_t) l)) >> 8) & (NHASH-1))
-
-static LIST_HEAD(unhead, union_node) unhead[NHASH];
-static int unvplock[NHASH];
-
-static void union_dircache_r __P((struct vnode *vp, struct vnode ***vppp,
- int *cntp));
-static int union_list_lock __P((int ix));
-static void union_list_unlock __P((int ix));
-static int union_relookup __P((struct union_mount *um, struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct componentname *cn, char *path,
- int pathlen));
-static void union_updatevp __P((struct union_node *un,
- struct vnode *uppervp,
- struct vnode *lowervp));
-static void union_newlower __P((struct union_node *, struct vnode *));
-static void union_newupper __P((struct union_node *, struct vnode *));
-static int union_copyfile __P((struct vnode *, struct vnode *,
- struct ucred *, struct proc *));
-static int union_vn_create __P((struct vnode **, struct union_node *,
- struct proc *));
-static int union_vn_close __P((struct vnode *, int, struct ucred *,
- struct proc *));
-
-int
-union_init()
-{
- int i;
-
- for (i = 0; i < NHASH; i++)
- LIST_INIT(&unhead[i]);
- bzero((caddr_t)unvplock, sizeof(unvplock));
- return (0);
-}
-
-static int
-union_list_lock(ix)
- int ix;
-{
- if (unvplock[ix] & UNVP_LOCKED) {
- unvplock[ix] |= UNVP_WANT;
- (void) tsleep((caddr_t) &unvplock[ix], PINOD, "unllck", 0);
- return (1);
- }
- unvplock[ix] |= UNVP_LOCKED;
- return (0);
-}
-
-static void
-union_list_unlock(ix)
- int ix;
-{
- unvplock[ix] &= ~UNVP_LOCKED;
-
- if (unvplock[ix] & UNVP_WANT) {
- unvplock[ix] &= ~UNVP_WANT;
- wakeup((caddr_t) &unvplock[ix]);
- }
-}
-
-/*
- * union_updatevp:
- *
- * The uppervp, if not NULL, must be referenced and not locked by us
- * The lowervp, if not NULL, must be referenced.
- *
- * if uppervp and lowervp match pointers already installed, nothing
- * happens. The passed vp's (when matching) are not adjusted. This
- * routine may only be called by union_newupper() and union_newlower().
- */
-
-static void
-union_updatevp(un, uppervp, lowervp)
- struct union_node *un;
- struct vnode *uppervp;
- struct vnode *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, uhash;
-
- /*
- * Ensure locking is ordered from lower to higher
- * to avoid deadlocks.
- */
- if (nhash < ohash) {
- lhash = nhash;
- uhash = ohash;
- } else {
- lhash = ohash;
- uhash = nhash;
- }
-
- if (lhash != uhash) {
- while (union_list_lock(lhash))
- continue;
- }
-
- while (union_list_lock(uhash))
- 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);
- if (un->un_path) {
- free(un->un_path, M_TEMP);
- un->un_path = 0;
- }
- }
- un->un_lowervp = lowervp;
- un->un_lowersz = VNOVAL;
- }
-
- if (un->un_uppervp != uppervp) {
- if (un->un_uppervp)
- vrele(un->un_uppervp);
- un->un_uppervp = uppervp;
- un->un_uppersz = VNOVAL;
- }
-
- if (docache && (ohash != nhash)) {
- LIST_INSERT_HEAD(&unhead[nhash], un, un_cache);
- un->un_flags |= UN_CACHED;
- }
-
- union_list_unlock(nhash);
-}
-
-/*
- * Set a new lowervp. The passed lowervp must be referenced and will be
- * stored in the vp in a referenced state.
- */
-
-static void
-union_newlower(un, lowervp)
- struct union_node *un;
- struct vnode *lowervp;
-{
- union_updatevp(un, un->un_uppervp, lowervp);
-}
-
-/*
- * Set a new uppervp. The passed uppervp must be locked and will be
- * stored in the vp in a locked state. The caller should not unlock
- * uppervp.
- */
-
-static void
-union_newupper(un, uppervp)
- struct union_node *un;
- struct vnode *uppervp;
-{
- union_updatevp(un, uppervp, un->un_lowervp);
-}
-
-/*
- * 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) {
- UDEBUG(("union: %s size now %ld\n",
- (uppersz != VNOVAL ? "upper" : "lower"), (long)sz));
- /*
- * There is no need to change size of non-existent object
- */
- /* vnode_pager_setsize(vp, sz); */
- }
-}
-
-/*
- * union_allocvp: allocate a union_node and associate it with a
- * parent union_node and one or two vnodes.
- *
- * vpp Holds the returned vnode locked and referenced if no
- * error occurs.
- *
- * mp Holds the mount point. mp may or may not be busied.
- * allocvp makes no changes to mp.
- *
- * dvp Holds the parent union_node to the one we wish to create.
- * XXX may only be used to traverse an uncopied lowervp-based
- * tree? XXX
- *
- * dvp may or may not be locked. allocvp makes no changes
- * to dvp.
- *
- * upperdvp Holds the parent vnode to uppervp, generally used along
- * with path component information to create a shadow of
- * lowervp when uppervp does not exist.
- *
- * upperdvp is referenced but unlocked on entry, and will be
- * dereferenced on return.
- *
- * uppervp Holds the new uppervp vnode to be stored in the
- * union_node we are allocating. uppervp is referenced but
- * not locked, and will be dereferenced on return.
- *
- * lowervp Holds the new lowervp vnode to be stored in the
- * union_node we are allocating. lowervp is referenced but
- * not locked, and will be dereferenced on return.
- *
- * cnp Holds path component information to be coupled with
- * lowervp and upperdvp to allow unionfs to create an uppervp
- * later on. Only used if lowervp is valid. The conents
- * of cnp is only valid for the duration of the call.
- *
- * docache Determine whether this node should be entered in the
- * cache or whether it should be destroyed as soon as possible.
- *
- * all union_nodes are maintained on a singly-linked
- * list. new nodes are only allocated when they cannot
- * be found on this list. entries on the list are
- * removed when the vfs reclaim entry is called.
- *
- * a single lock is kept for the entire list. this is
- * needed because the getnewvnode() function can block
- * waiting for a vnode to become free, in which case there
- * may be more than one process trying to get the same
- * vnode. this lock is only taken if we are going to
- * call getnewvnode, since the kernel itself is single-threaded.
- *
- * if an entry is found on the list, then call vget() to
- * take a reference. this is done because there may be
- * zero references to it and so it needs to removed from
- * the vnode free list.
- */
-
-int
-union_allocvp(vpp, mp, dvp, upperdvp, cnp, uppervp, lowervp, docache)
- struct vnode **vpp;
- struct mount *mp;
- struct vnode *dvp; /* parent union vnode */
- struct vnode *upperdvp; /* parent vnode of uppervp */
- 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 union_mount *um = MOUNTTOUNIONMOUNT(mp);
- struct proc *p = (cnp) ? cnp->cn_proc : curproc;
- int hash = 0;
- int vflag;
- int try;
-
- if (uppervp == NULLVP && lowervp == NULLVP)
- panic("union: unidentifiable allocation");
-
- if (uppervp && lowervp && (uppervp->v_type != lowervp->v_type)) {
- vrele(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:
- if (!docache) {
- un = 0;
- } else for (try = 0; try < 3; try++) {
- switch (try) {
- case 0:
- if (lowervp == NULLVP)
- continue;
- hash = UNION_HASH(uppervp, lowervp);
- break;
-
- case 1:
- if (uppervp == NULLVP)
- continue;
- hash = UNION_HASH(uppervp, NULLVP);
- break;
-
- case 2:
- if (lowervp == NULLVP)
- continue;
- hash = UNION_HASH(NULLVP, lowervp);
- break;
- }
-
- while (union_list_lock(hash))
- continue;
-
- LIST_FOREACH(un, &unhead[hash], un_cache) {
- if ((un->un_lowervp == lowervp ||
- un->un_lowervp == NULLVP) &&
- (un->un_uppervp == uppervp ||
- un->un_uppervp == NULLVP) &&
- (UNIONTOV(un)->v_mount == mp)) {
- if (vget(UNIONTOV(un), 0,
- cnp ? cnp->cn_proc : NULL)) {
- union_list_unlock(hash);
- goto loop;
- }
- break;
- }
- }
-
- union_list_unlock(hash);
-
- if (un)
- break;
- }
-
- if (un) {
- /*
- * Obtain a lock on the union_node. Everything is unlocked
- * except for dvp, so check that case. If they match, our
- * new un is already locked. Otherwise we have to lock our
- * new un.
- *
- * A potential deadlock situation occurs when we are holding
- * one lock while trying to get another. We must follow
- * strict ordering rules to avoid it. We try to locate dvp
- * by scanning up from un_vnode, since the most likely
- * scenario is un being under dvp.
- */
-
- if (dvp && un->un_vnode != dvp) {
- struct vnode *scan = un->un_vnode;
-
- do {
- scan = VTOUNION(scan)->un_pvp;
- } while (scan && scan->v_tag == VT_UNION && scan != dvp);
- if (scan != dvp) {
- /*
- * our new un is above dvp (we never saw dvp
- * while moving up the tree).
- */
- VREF(dvp);
- VOP_UNLOCK(dvp, 0, p);
- error = vn_lock(un->un_vnode, LK_EXCLUSIVE, p);
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
- vrele(dvp);
- } else {
- /*
- * our new un is under dvp
- */
- error = vn_lock(un->un_vnode, LK_EXCLUSIVE, p);
- }
- } else if (dvp == NULLVP) {
- /*
- * dvp is NULL, we need to lock un.
- */
- error = vn_lock(un->un_vnode, LK_EXCLUSIVE, p);
- } else {
- /*
- * dvp == un->un_vnode, we are already locked.
- */
- error = 0;
- }
-
- if (error)
- goto loop;
-
- /*
- * At this point, the union_node is locked and referenced.
- *
- * uppervp is locked and referenced or NULL, lowervp is
- * referenced or NULL.
- */
- UDEBUG(("Modify existing un %p vn %p upper %p(refs %d) -> %p(refs %d)\n",
- un, un->un_vnode, un->un_uppervp,
- (un->un_uppervp ? un->un_uppervp->v_usecount : -99),
- uppervp,
- (uppervp ? uppervp->v_usecount : -99)
- ));
-
- if (uppervp != un->un_uppervp) {
- KASSERT(uppervp == NULL || uppervp->v_usecount > 0, ("union_allocvp: too few refs %d (at least 1 required) on uppervp", uppervp->v_usecount));
- union_newupper(un, uppervp);
- } else if (uppervp) {
- KASSERT(uppervp->v_usecount > 1, ("union_allocvp: too few refs %d (at least 2 required) on uppervp", uppervp->v_usecount));
- vrele(uppervp);
- }
-
- /*
- * Save information about the lower layer.
- * This needs to keep track of pathname
- * and directory information which union_vn_create
- * might need.
- */
- if (lowervp != un->un_lowervp) {
- union_newlower(un, lowervp);
- if (cnp && (lowervp != NULLVP)) {
- un->un_path = malloc(cnp->cn_namelen+1,
- M_TEMP, M_WAITOK);
- bcopy(cnp->cn_nameptr, un->un_path,
- cnp->cn_namelen);
- un->un_path[cnp->cn_namelen] = '\0';
- }
- } else if (lowervp) {
- vrele(lowervp);
- }
-
- /*
- * and upperdvp
- */
- if (upperdvp != un->un_dirvp) {
- if (un->un_dirvp)
- vrele(un->un_dirvp);
- un->un_dirvp = upperdvp;
- } else if (upperdvp) {
- vrele(upperdvp);
- }
-
- *vpp = UNIONTOV(un);
- return (0);
- }
-
- 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;
- }
-
- /*
- * Create new node rather then replace old node
- */
-
- error = getnewvnode(VT_UNION, mp, union_vnodeop_p, vpp);
- if (error) {
- /*
- * If an error occurs clear out vnodes.
- */
- if (lowervp)
- vrele(lowervp);
- if (uppervp)
- vrele(uppervp);
- if (upperdvp)
- vrele(upperdvp);
- *vpp = NULL;
- goto out;
- }
-
- 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
- (*vpp)->v_type = lowervp->v_type;
-
- un = VTOUNION(*vpp);
- bzero(un, sizeof(*un));
-
- lockinit(&un->un_lock, PVFS, "unlock", 0, 0);
- vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, p);
-
- un->un_vnode = *vpp;
- un->un_uppervp = uppervp;
- un->un_uppersz = VNOVAL;
- un->un_lowervp = lowervp;
- un->un_lowersz = VNOVAL;
- un->un_dirvp = upperdvp;
- un->un_pvp = dvp; /* only parent dir in new allocation */
- if (dvp != NULLVP)
- VREF(dvp);
- un->un_dircache = 0;
- un->un_openl = 0;
-
- if (cnp && (lowervp != NULLVP)) {
- un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
- bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
- un->un_path[cnp->cn_namelen] = '\0';
- } else {
- un->un_path = 0;
- un->un_dirvp = NULL;
- }
-
- if (docache) {
- LIST_INSERT_HEAD(&unhead[hash], un, un_cache);
- un->un_flags |= UN_CACHED;
- }
-
-out:
- if (docache)
- union_list_unlock(hash);
-
- return (error);
-}
-
-int
-union_freevp(vp)
- struct vnode *vp;
-{
- struct union_node *un = VTOUNION(vp);
-
- if (un->un_flags & UN_CACHED) {
- un->un_flags &= ~UN_CACHED;
- LIST_REMOVE(un, un_cache);
- }
-
- if (un->un_pvp != NULLVP) {
- vrele(un->un_pvp);
- un->un_pvp = NULL;
- }
- if (un->un_uppervp != NULLVP) {
- vrele(un->un_uppervp);
- un->un_uppervp = NULL;
- }
- if (un->un_lowervp != NULLVP) {
- vrele(un->un_lowervp);
- un->un_lowervp = NULL;
- }
- if (un->un_dirvp != NULLVP) {
- vrele(un->un_dirvp);
- un->un_dirvp = NULL;
- }
- if (un->un_path) {
- free(un->un_path, M_TEMP);
- un->un_path = NULL;
- }
- lockdestroy(&un->un_lock);
-
- FREE(vp->v_data, M_TEMP);
- vp->v_data = 0;
-
- return (0);
-}
-
-/*
- * copyfile. copy the vnode (fvp) to the vnode (tvp)
- * using a sequence of reads and writes. both (fvp)
- * and (tvp) are locked on entry and exit.
- *
- * fvp and tvp are both exclusive locked on call, but their refcount's
- * haven't been bumped at all.
- */
-static int
-union_copyfile(fvp, tvp, cred, p)
- struct vnode *fvp;
- struct vnode *tvp;
- struct ucred *cred;
- struct proc *p;
-{
- char *buf;
- struct uio uio;
- struct iovec iov;
- int error = 0;
-
- /*
- * strategy:
- * allocate a buffer of size MAXBSIZE.
- * loop doing reads and writes, keeping track
- * of the current uio offset.
- * give up at the first sign of trouble.
- */
-
- bzero(&uio, sizeof(uio));
-
- uio.uio_procp = p;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_offset = 0;
-
- VOP_LEASE(fvp, p, cred, LEASE_READ);
- VOP_LEASE(tvp, p, cred, LEASE_WRITE);
-
- buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
-
- /* ugly loop follows... */
- do {
- off_t offset = uio.uio_offset;
- int count;
- int bufoffset;
-
- /*
- * Setup for big read
- */
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- iov.iov_base = buf;
- iov.iov_len = MAXBSIZE;
- uio.uio_resid = iov.iov_len;
- uio.uio_rw = UIO_READ;
-
- if ((error = VOP_READ(fvp, &uio, 0, cred)) != 0)
- break;
-
- /*
- * Get bytes read, handle read eof case and setup for
- * write loop
- */
- if ((count = MAXBSIZE - uio.uio_resid) == 0)
- break;
- bufoffset = 0;
-
- /*
- * Write until an error occurs or our buffer has been
- * exhausted, then update the offset for the next read.
- */
- while (bufoffset < count) {
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- iov.iov_base = buf + bufoffset;
- iov.iov_len = count - bufoffset;
- uio.uio_offset = offset + bufoffset;
- uio.uio_rw = UIO_WRITE;
- uio.uio_resid = iov.iov_len;
-
- if ((error = VOP_WRITE(tvp, &uio, 0, cred)) != 0)
- break;
- bufoffset += (count - bufoffset) - uio.uio_resid;
- }
- uio.uio_offset = offset + bufoffset;
- } while (error == 0);
-
- free(buf, M_TEMP);
- return (error);
-}
-
-/*
- *
- * un's vnode 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 mount *mp;
- struct vnode *lvp, *uvp;
-
- /*
- * If the user does not have read permission, the vnode should not
- * be copied to upper layer.
- */
- vn_lock(un->un_lowervp, LK_EXCLUSIVE | LK_RETRY, p);
- error = VOP_ACCESS(un->un_lowervp, VREAD, cred, p);
- VOP_UNLOCK(un->un_lowervp, 0, p);
- if (error)
- return (error);
-
- if ((error = vn_start_write(un->un_dirvp, &mp, V_WAIT | PCATCH)) != 0)
- return (error);
- if ((error = union_vn_create(&uvp, un, p)) != 0) {
- vn_finished_write(mp);
- return (error);
- }
-
- lvp = un->un_lowervp;
-
- KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
- 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 && vn_canvmio(lvp) == TRUE)
- error = vfs_object_create(lvp, p, cred);
- if (error == 0) {
- error = union_copyfile(lvp, uvp, cred, p);
- VOP_UNLOCK(lvp, 0, p);
- (void) VOP_CLOSE(lvp, FREAD, cred, p);
- }
- if (error == 0)
- UDEBUG(("union: copied up %s\n", un->un_path));
-
- }
- VOP_UNLOCK(uvp, 0, p);
- vn_finished_write(mp);
- union_newupper(un, uvp);
- KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
- union_vn_close(uvp, FWRITE, cred, p);
- KASSERT(uvp->v_usecount > 0, ("copy: uvp refcount 0: %d", uvp->v_usecount));
- /*
- * 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);
- }
- if (un->un_openl) {
- if (vn_canvmio(uvp) == TRUE)
- error = vfs_object_create(uvp, p, cred);
- }
- un->un_openl = 0;
- }
-
- return (error);
-
-}
-
-/*
- * union_relookup:
- *
- * dvp should be locked on entry and will be locked on return. No
- * net change in the ref count will occur.
- *
- * If an error is returned, *vpp will be invalid, otherwise it
- * will hold a locked, referenced vnode. If *vpp == dvp then
- * remember that only one exclusive lock is held.
- */
-
-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.
- */
- cn->cn_namelen = pathlen;
- cn->cn_pnbuf = zalloc(namei_zone);
- bcopy(path, cn->cn_pnbuf, cn->cn_namelen);
- cn->cn_pnbuf[cn->cn_namelen] = '\0';
-
- cn->cn_nameiop = CREATE;
- cn->cn_flags = (LOCKPARENT|LOCKLEAF|HASBUF|SAVENAME|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_consume = cnp->cn_consume;
-
- VREF(dvp);
- VOP_UNLOCK(dvp, 0, cnp->cn_proc);
-
- /*
- * Pass dvp unlocked and referenced on call to relookup().
- *
- * If an error occurs, dvp will be returned unlocked and dereferenced.
- */
-
- if ((error = relookup(dvp, vpp, cn)) != 0) {
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_proc);
- return(error);
- }
-
- /*
- * If no error occurs, dvp will be returned locked with the reference
- * left as before, and vpp will be returned referenced and locked.
- *
- * We want to return with dvp as it was passed to us, so we get
- * rid of our reference.
- */
- vrele(dvp);
- return (0);
-}
-
-/*
- * Create a shadow directory in the upper layer.
- * The new vnode is returned locked.
- *
- * (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 shadow directory,
- * it is locked (but not ref'd) on entry and return.
- * (cnp) is the componentname to be created.
- * (vpp) is the returned newly created shadow directory, which
- * is returned locked and ref'd
- */
-int
-union_mkshadow(um, dvp, cnp, vpp)
- struct union_mount *um;
- struct vnode *dvp;
- struct componentname *cnp;
- struct vnode **vpp;
-{
- int error;
- struct vattr va;
- struct proc *p = cnp->cn_proc;
- struct componentname cn;
- struct mount *mp;
-
- if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)) != 0)
- return (error);
- if ((error = union_relookup(um, dvp, vpp, cnp, &cn,
- cnp->cn_nameptr, cnp->cn_namelen)) != 0) {
- vn_finished_write(mp);
- return (error);
- }
-
- if (*vpp) {
- if (cn.cn_flags & HASBUF) {
- zfree(namei_zone, cn.cn_pnbuf);
- cn.cn_flags &= ~HASBUF;
- }
- if (dvp == *vpp)
- vrele(*vpp);
- else
- vput(*vpp);
- vn_finished_write(mp);
- *vpp = NULLVP;
- return (EEXIST);
- }
-
- /*
- * policy: when creating the shadow directory in the
- * upper layer, create it owned by the user who did
- * the mount, group from parent directory, and mode
- * 777 modified by umask (ie mostly identical to the
- * mkdir syscall). (jsp, kb)
- */
-
- VATTR_NULL(&va);
- va.va_type = VDIR;
- va.va_mode = um->um_cmode;
-
- /* VOP_LEASE: dvp is locked */
- VOP_LEASE(dvp, p, cn.cn_cred, LEASE_WRITE);
-
- error = VOP_MKDIR(dvp, vpp, &cn, &va);
- if (cn.cn_flags & HASBUF) {
- zfree(namei_zone, cn.cn_pnbuf);
- cn.cn_flags &= ~HASBUF;
- }
- /*vput(dvp);*/
- vn_finished_write(mp);
- 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 return.
- * (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 proc *p = cnp->cn_proc;
- struct vnode *wvp;
- struct componentname cn;
- struct mount *mp;
-
- if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)) != 0)
- return (error);
- error = union_relookup(um, dvp, &wvp, cnp, &cn, path, strlen(path));
- if (error) {
- vn_finished_write(mp);
- return (error);
- }
-
- if (wvp) {
- if (cn.cn_flags & HASBUF) {
- zfree(namei_zone, cn.cn_pnbuf);
- cn.cn_flags &= ~HASBUF;
- }
- if (wvp == dvp)
- vrele(wvp);
- else
- vput(wvp);
- vn_finished_write(mp);
- return (EEXIST);
- }
-
- /* VOP_LEASE: dvp is locked */
- VOP_LEASE(dvp, p, p->p_ucred, LEASE_WRITE);
-
- error = VOP_WHITEOUT(dvp, &cn, CREATE);
- if (cn.cn_flags & HASBUF) {
- zfree(namei_zone, cn.cn_pnbuf);
- cn.cn_flags &= ~HASBUF;
- }
- vn_finished_write(mp);
- return (error);
-}
-
-/*
- * union_vn_create: creates and opens a new shadow file
- * on the upper union layer. this function is similar
- * in spirit to calling vn_open but it avoids calling namei().
- * the problem with calling namei is that a) it locks too many
- * things, and b) it doesn't start at the "right" directory,
- * whereas relookup is told where to start.
- *
- * On entry, the vnode associated with un is locked. It remains locked
- * on return.
- *
- * If no error occurs, *vpp contains a locked referenced vnode for your
- * use. If an error occurs *vpp iis undefined.
- */
-static int
-union_vn_create(vpp, un, p)
- struct vnode **vpp;
- struct union_node *un;
- struct proc *p;
-{
- struct vnode *vp;
- struct ucred *cred = p->p_ucred;
- struct vattr vat;
- struct vattr *vap = &vat;
- int fmode = FFLAGS(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL);
- int error;
- int cmode = UN_FILEMODE & ~p->p_fd->fd_cmask;
- struct componentname cn;
-
- *vpp = NULLVP;
-
- /*
- * Build a new componentname structure (for the same
- * reasons outlines in union_mkshadow).
- * The difference here is that the file is owned by
- * the current user, rather than by the person who
- * did the mount, since the current user needs to be
- * able to write the file (that's why it is being
- * copied in the first place).
- */
- cn.cn_namelen = strlen(un->un_path);
- cn.cn_pnbuf = zalloc(namei_zone);
- bcopy(un->un_path, cn.cn_pnbuf, cn.cn_namelen+1);
- cn.cn_nameiop = CREATE;
- cn.cn_flags = (LOCKPARENT|LOCKLEAF|HASBUF|SAVENAME|ISLASTCN);
- cn.cn_proc = p;
- cn.cn_cred = p->p_ucred;
- cn.cn_nameptr = cn.cn_pnbuf;
- cn.cn_consume = 0;
-
- /*
- * Pass dvp unlocked and referenced on call to relookup().
- *
- * If an error occurs, dvp will be returned unlocked and dereferenced.
- */
- VREF(un->un_dirvp);
- error = relookup(un->un_dirvp, &vp, &cn);
- if (error)
- return (error);
-
- /*
- * If no error occurs, dvp will be returned locked with the reference
- * left as before, and vpp will be returned referenced and locked.
- */
- if (vp) {
- vput(un->un_dirvp);
- if (cn.cn_flags & HASBUF) {
- zfree(namei_zone, cn.cn_pnbuf);
- cn.cn_flags &= ~HASBUF;
- }
- if (vp == un->un_dirvp)
- vrele(vp);
- else
- vput(vp);
- return (EEXIST);
- }
-
- /*
- * Good - there was no race to create the file
- * so go ahead and create it. The permissions
- * on the file will be 0666 modified by the
- * current user's umask. Access to the file, while
- * it is unioned, will require access to the top *and*
- * bottom files. Access when not unioned will simply
- * require access to the top-level file.
- * TODO: confirm choice of access permissions.
- */
- VATTR_NULL(vap);
- vap->va_type = VREG;
- vap->va_mode = cmode;
- VOP_LEASE(un->un_dirvp, p, cred, LEASE_WRITE);
- error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
- if (cn.cn_flags & HASBUF) {
- zfree(namei_zone, cn.cn_pnbuf);
- cn.cn_flags &= ~HASBUF;
- }
- vput(un->un_dirvp);
- if (error)
- return (error);
-
- error = VOP_OPEN(vp, fmode, cred, p);
- if (error == 0 && vn_canvmio(vp) == TRUE)
- error = vfs_object_create(vp, p, cred);
- if (error) {
- vput(vp);
- return (error);
- }
- vp->v_writecount++;
- *vpp = vp;
- return (0);
-}
-
-static int
-union_vn_close(vp, fmode, cred, p)
- struct vnode *vp;
- int fmode;
- struct ucred *cred;
- struct proc *p;
-{
-
- if (fmode & FWRITE)
- --vp->v_writecount;
- return (VOP_CLOSE(vp, fmode, cred, p));
-}
-
-#if 0
-
-/*
- * union_removed_upper:
- *
- * called with union_node unlocked. XXX
- */
-
-void
-union_removed_upper(un)
- struct union_node *un;
-{
- struct proc *p = curproc; /* XXX */
- struct vnode **vpp;
-
- /*
- * Do not set the uppervp to NULLVP. If lowervp is NULLVP,
- * union node will have neither uppervp nor lowervp. We remove
- * the union node from cache, so that it will not be referrenced.
- */
- union_newupper(un, NULLVP);
- 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_CACHED) {
- un->un_flags &= ~UN_CACHED;
- LIST_REMOVE(un, un_cache);
- }
-}
-
-#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 == NULL) {
- cnt = 0;
- union_dircache_r(vp, 0, &cnt);
- cnt++;
- dircache = 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);*/
- UDEBUG(("ALLOCVP-3 %p ref %d\n", *vpp, (*vpp ? (*vpp)->v_usecount : -99)));
- VREF(*vpp);
- error = union_allocvp(&nvp, vp->v_mount, NULLVP, NULLVP, NULL, *vpp, NULLVP, 0);
- UDEBUG(("ALLOCVP-3B %p ref %d\n", nvp, (*vpp ? (*vpp)->v_usecount : -99)));
- if (error)
- goto out;
-
- VTOUNION(vp)->un_dircache = 0;
- un = VTOUNION(nvp);
- un->un_dircache = dircache;
-
-out:
- VOP_UNLOCK(vp, 0, p);
- return (nvp);
-}
-
-/*
- * Module glue to remove #ifdef UNION from vfs_syscalls.c
- */
-static int
-union_dircheck(struct proc *p, struct vnode **vp, struct file *fp)
-{
- int error = 0;
-
- if ((*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 == 0 && vn_canvmio(lvp) == TRUE)
- error = vfs_object_create(lvp, p, fp->f_cred);
- 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;
- return -1; /* goto unionread */
- }
- }
- return error;
-}
-
-static int
-union_modevent(module_t mod, int type, void *data)
-{
- switch (type) {
- case MOD_LOAD:
- union_dircheckp = union_dircheck;
- break;
- case MOD_UNLOAD:
- union_dircheckp = NULL;
- break;
- default:
- break;
- }
- return 0;
-}
-
-static moduledata_t union_mod = {
- "union_dircheck",
- union_modevent,
- NULL
-};
-
-DECLARE_MODULE(union_dircheck, union_mod, SI_SUB_VFS, SI_ORDER_ANY);
diff --git a/sys/miscfs/union/union_vfsops.c b/sys/miscfs/union/union_vfsops.c
deleted file mode 100644
index d38f31e..0000000
--- a/sys/miscfs/union/union_vfsops.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * 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
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
- * $FreeBSD$
- */
-
-/*
- * Union Layer
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/malloc.h>
-#include <sys/filedesc.h>
-#include <miscfs/union/union.h>
-
-static MALLOC_DEFINE(M_UNIONFSMNT, "UNION mount", "UNION mount structure");
-
-extern int union_init __P((struct vfsconf *));
-static int union_mount __P((struct mount *mp, char *path, caddr_t data,
- struct nameidata *ndp, struct proc *p));
-static int union_root __P((struct mount *mp, struct vnode **vpp));
-static int union_statfs __P((struct mount *mp, struct statfs *sbp,
- struct proc *p));
-static int union_unmount __P((struct mount *mp, int mntflags,
- struct proc *p));
-
-/*
- * Mount union filesystem
- */
-static int
-union_mount(mp, path, data, ndp, p)
- struct mount *mp;
- char *path;
- caddr_t data;
- struct nameidata *ndp;
- struct proc *p;
-{
- int error = 0;
- struct union_args args;
- struct vnode *lowerrootvp = NULLVP;
- struct vnode *upperrootvp = NULLVP;
- struct union_mount *um = 0;
- struct ucred *cred = 0;
- char *cp = 0;
- int len;
- u_int size;
-
- UDEBUG(("union_mount(mp = %p)\n", (void *)mp));
-
- /*
- * Disable clustered write, otherwise system becomes unstable.
- */
- mp->mnt_flag |= MNT_NOCLUSTERW;
-
- /*
- * Update is a no-op
- */
- if (mp->mnt_flag & MNT_UPDATE) {
- /*
- * Need to provide.
- * 1. a way to convert between rdonly and rdwr mounts.
- * 2. support for nfs exports.
- */
- error = EOPNOTSUPP;
- goto bad;
- }
-
- /*
- * Get argument
- */
- error = copyin(data, (caddr_t)&args, sizeof(struct union_args));
- if (error)
- goto bad;
-
- /*
- * Obtain lower vnode. Vnode is stored in mp->mnt_vnodecovered.
- * We need to reference it but not lock it.
- */
-
- lowerrootvp = mp->mnt_vnodecovered;
- VREF(lowerrootvp);
-
-#if 0
- /*
- * Unlock lower node to avoid deadlock.
- */
- if (lowerrootvp->v_op == union_vnodeop_p)
- VOP_UNLOCK(lowerrootvp, 0, p);
-#endif
-
- /*
- * Obtain upper vnode by calling namei() on the path. The
- * upperrootvp will be turned referenced but not locked.
- */
- NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT,
- UIO_USERSPACE, args.target, p);
-
- error = namei(ndp);
-
-#if 0
- if (lowerrootvp->v_op == union_vnodeop_p)
- vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY, p);
-#endif
- if (error)
- goto bad;
-
- NDFREE(ndp, NDF_ONLY_PNBUF);
- upperrootvp = ndp->ni_vp;
- vrele(ndp->ni_dvp);
- ndp->ni_dvp = NULL;
-
- UDEBUG(("mount_root UPPERVP %p locked = %d\n", upperrootvp,
- VOP_ISLOCKED(upperrootvp, NULL)));
-
- /*
- * Check multi union mount to avoid `lock myself again' panic.
- * Also require that it be a directory.
- */
- if (upperrootvp == VTOUNION(lowerrootvp)->un_uppervp) {
-#ifdef DIAGNOSTIC
- printf("union_mount: multi union mount?\n");
-#endif
- error = EDEADLK;
- goto bad;
- }
-
- if (upperrootvp->v_type != VDIR) {
- error = EINVAL;
- goto bad;
- }
-
- /*
- * Allocate our union_mount structure and populate the fields.
- * The vnode references are stored in the union_mount as held,
- * unlocked references. Depending on the _BELOW flag, the
- * filesystems are viewed in a different order. In effect this
- * is the same as providing a mount-under option to the mount
- * syscall.
- */
-
- um = (struct union_mount *) malloc(sizeof(struct union_mount),
- M_UNIONFSMNT, M_WAITOK | M_ZERO);
-
- um->um_op = args.mntflags & UNMNT_OPMASK;
-
- switch (um->um_op) {
- case UNMNT_ABOVE:
- um->um_lowervp = lowerrootvp;
- um->um_uppervp = upperrootvp;
- upperrootvp = NULL;
- lowerrootvp = NULL;
- break;
-
- case UNMNT_BELOW:
- um->um_lowervp = upperrootvp;
- um->um_uppervp = lowerrootvp;
- upperrootvp = NULL;
- lowerrootvp = NULL;
- break;
-
- case UNMNT_REPLACE:
- vrele(lowerrootvp);
- lowerrootvp = NULL;
- um->um_uppervp = upperrootvp;
- um->um_lowervp = lowerrootvp;
- upperrootvp = NULL;
- break;
-
- default:
- error = EINVAL;
- goto bad;
- }
-
- /*
- * 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, NULL, 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;
-
- /*
- * Depending on what you think the MNT_LOCAL flag might mean,
- * you may want the && to be || on the conditional below.
- * At the moment it has been defined that the filesystem is
- * only local if it is all local, ie the MNT_LOCAL flag implies
- * that the entire namespace is local. If you think the MNT_LOCAL
- * flag implies that some of the files might be stored locally
- * then you will want to change the conditional.
- */
- if (um->um_op == UNMNT_ABOVE) {
- if (((um->um_lowervp == NULLVP) ||
- (um->um_lowervp->v_mount->mnt_flag & MNT_LOCAL)) &&
- (um->um_uppervp->v_mount->mnt_flag & MNT_LOCAL))
- mp->mnt_flag |= MNT_LOCAL;
- }
-
- /*
- * Copy in the upper layer's RDONLY flag. This is for the benefit
- * of lookup() which explicitly checks the flag, rather than asking
- * the filesystem for its own opinion. This means, that an update
- * mount of the underlying filesystem to go from rdonly to rdwr
- * will leave the unioned view as read-only.
- */
- mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
-
- mp->mnt_data = (qaddr_t) um;
- vfs_getnewfsid(mp);
-
- switch (um->um_op) {
- case UNMNT_ABOVE:
- cp = "<above>:";
- break;
- case UNMNT_BELOW:
- cp = "<below>:";
- break;
- case UNMNT_REPLACE:
- cp = "";
- break;
- }
- len = strlen(cp);
- bcopy(cp, mp->mnt_stat.f_mntfromname, len);
-
- cp = mp->mnt_stat.f_mntfromname + len;
- len = MNAMELEN - len;
-
- (void) copyinstr(args.target, cp, len - 1, &size);
- bzero(cp + size, len - size);
-
- (void)union_statfs(mp, &mp->mnt_stat, p);
-
- UDEBUG(("union_mount: from %s, on %s\n",
- mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname));
- return (0);
-
-bad:
- if (um) {
- if (um->um_uppervp)
- vrele(um->um_uppervp);
- if (um->um_lowervp)
- vrele(um->um_lowervp);
- /* XXX other fields */
- free(um, M_UNIONFSMNT);
- }
- if (cred)
- crfree(cred);
- if (upperrootvp)
- vrele(upperrootvp);
- if (lowerrootvp)
- vrele(lowerrootvp);
- return (error);
-}
-
-/*
- * Free reference to union layer
- */
-static int
-union_unmount(mp, mntflags, p)
- struct mount *mp;
- int mntflags;
- struct proc *p;
-{
- struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
- int error;
- int freeing;
- int flags = 0;
-
- UDEBUG(("union_unmount(mp = %p)\n", (void *)mp));
-
- if (mntflags & MNT_FORCE)
- 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; (error = vflush(mp, 0, flags)) != 0;) {
- struct vnode *vp;
- int n;
-
- /* count #vnodes held on mount list */
- n = 0;
- LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes)
- n++;
-
- /* if this is unchanged then stop */
- if (n == freeing)
- break;
-
- /* otherwise try once more time */
- freeing = n;
- }
-
- /* If the most recent vflush failed, the filesystem is still busy. */
- if (error)
- return (error);
-
- /*
- * Discard references to upper and lower target vnodes.
- */
- if (um->um_lowervp)
- vrele(um->um_lowervp);
- vrele(um->um_uppervp);
- crfree(um->um_cred);
- /*
- * Finally, throw away the union_mount structure
- */
- free(mp->mnt_data, M_UNIONFSMNT); /* XXX */
- mp->mnt_data = 0;
- return (0);
-}
-
-static int
-union_root(mp, vpp)
- struct mount *mp;
- struct vnode **vpp;
-{
- struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
- int error;
-
- /*
- * Supply an unlocked reference to um_uppervp and to um_lowervp. It
- * is possible for um_uppervp to be locked without the associated
- * root union_node being locked. We let union_allocvp() deal with
- * it.
- */
- UDEBUG(("union_root UPPERVP %p locked = %d\n", um->um_uppervp,
- VOP_ISLOCKED(um->um_uppervp, NULL)));
-
- VREF(um->um_uppervp);
- if (um->um_lowervp)
- VREF(um->um_lowervp);
-
- error = union_allocvp(vpp, mp, NULLVP, NULLVP, NULL,
- um->um_uppervp, um->um_lowervp, 1);
- UDEBUG(("error %d\n", error));
- UDEBUG(("union_root2 UPPERVP %p locked = %d\n", um->um_uppervp,
- VOP_ISLOCKED(um->um_uppervp, NULL)));
-
- return (error);
-}
-
-static int
-union_statfs(mp, sbp, p)
- struct mount *mp;
- struct statfs *sbp;
- struct proc *p;
-{
- int error;
- struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
- struct statfs mstat;
- int lbsize;
-
- UDEBUG(("union_statfs(mp = %p, lvp = %p, uvp = %p)\n",
- (void *)mp, (void *)um->um_lowervp, (void *)um->um_uppervp));
-
- bzero(&mstat, sizeof(mstat));
-
- if (um->um_lowervp) {
- error = VFS_STATFS(um->um_lowervp->v_mount, &mstat, p);
- if (error)
- return (error);
- }
-
- /* now copy across the "interesting" information and fake the rest */
-#if 0
- sbp->f_type = mstat.f_type;
- sbp->f_flags = mstat.f_flags;
- sbp->f_bsize = mstat.f_bsize;
- sbp->f_iosize = mstat.f_iosize;
-#endif
- lbsize = mstat.f_bsize;
- sbp->f_blocks = mstat.f_blocks;
- sbp->f_bfree = mstat.f_bfree;
- sbp->f_bavail = mstat.f_bavail;
- sbp->f_files = mstat.f_files;
- sbp->f_ffree = mstat.f_ffree;
-
- error = VFS_STATFS(um->um_uppervp->v_mount, &mstat, p);
- if (error)
- return (error);
-
- sbp->f_flags = mstat.f_flags;
- sbp->f_bsize = mstat.f_bsize;
- sbp->f_iosize = mstat.f_iosize;
-
- /*
- * if the lower and upper blocksizes differ, then frig the
- * block counts so that the sizes reported by df make some
- * kind of sense. none of this makes sense though.
- */
-
- if (mstat.f_bsize != lbsize)
- sbp->f_blocks = ((off_t) sbp->f_blocks * 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_files += mstat.f_files;
- 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);
- }
- return (0);
-}
-
-static struct vfsops union_vfsops = {
- union_mount,
- vfs_stdstart, /* underlying start already done */
- union_unmount,
- union_root,
- vfs_stdquotactl,
- union_statfs,
- vfs_stdsync, /* XXX assumes no cached data on union level */
- vfs_stdvget,
- vfs_stdfhtovp,
- vfs_stdcheckexp,
- vfs_stdvptofh,
- union_init,
- vfs_stduninit,
- vfs_stdextattrctl,
-};
-
-VFS_SET(union_vfsops, union, VFCF_LOOPBACK);
diff --git a/sys/miscfs/union/union_vnops.c b/sys/miscfs/union/union_vnops.c
deleted file mode 100644
index 3402825..0000000
--- a/sys/miscfs/union/union_vnops.c
+++ /dev/null
@@ -1,1966 +0,0 @@
-/*
- * 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.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <sys/kernel.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-#include <sys/namei.h>
-#include <sys/malloc.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/lock.h>
-#include <sys/sysctl.h>
-#include <miscfs/union/union.h>
-
-#include <vm/vm.h>
-#include <vm/vnode_pager.h>
-
-#include <vm/vm_page.h>
-#include <vm/vm_object.h>
-
-int uniondebug = 0;
-
-#if UDEBUG_ENABLED
-SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RW, &uniondebug, 0, "");
-#else
-SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RD, &uniondebug, 0, "");
-#endif
-
-static int union_access __P((struct vop_access_args *ap));
-static int union_advlock __P((struct vop_advlock_args *ap));
-static int union_close __P((struct vop_close_args *ap));
-static int union_create __P((struct vop_create_args *ap));
-static int union_createvobject __P((struct vop_createvobject_args *ap));
-static int union_destroyvobject __P((struct vop_destroyvobject_args *ap));
-static int union_fsync __P((struct vop_fsync_args *ap));
-static int union_getattr __P((struct vop_getattr_args *ap));
-static int union_getvobject __P((struct vop_getvobject_args *ap));
-static int union_inactive __P((struct vop_inactive_args *ap));
-static int union_ioctl __P((struct vop_ioctl_args *ap));
-static int union_lease __P((struct vop_lease_args *ap));
-static int union_link __P((struct vop_link_args *ap));
-static int union_lock __P((struct vop_lock_args *ap));
-static int union_lookup __P((struct vop_lookup_args *ap));
-static int union_lookup1 __P((struct vnode *udvp, struct vnode **dvp,
- struct vnode **vpp,
- struct componentname *cnp));
-static int union_mkdir __P((struct vop_mkdir_args *ap));
-static int union_mknod __P((struct vop_mknod_args *ap));
-static int union_open __P((struct vop_open_args *ap));
-static int union_pathconf __P((struct vop_pathconf_args *ap));
-static int union_print __P((struct vop_print_args *ap));
-static int union_read __P((struct vop_read_args *ap));
-static int union_readdir __P((struct vop_readdir_args *ap));
-static int union_readlink __P((struct vop_readlink_args *ap));
-static int union_getwritemount __P((struct vop_getwritemount_args *ap));
-static int union_reclaim __P((struct vop_reclaim_args *ap));
-static int union_remove __P((struct vop_remove_args *ap));
-static int union_rename __P((struct vop_rename_args *ap));
-static int union_revoke __P((struct vop_revoke_args *ap));
-static int union_rmdir __P((struct vop_rmdir_args *ap));
-static int union_poll __P((struct vop_poll_args *ap));
-static int union_setattr __P((struct vop_setattr_args *ap));
-static int union_strategy __P((struct vop_strategy_args *ap));
-static int union_symlink __P((struct vop_symlink_args *ap));
-static int union_unlock __P((struct vop_unlock_args *ap));
-static int union_whiteout __P((struct vop_whiteout_args *ap));
-static int union_write __P((struct vop_read_args *ap));
-
-static __inline
-struct vnode *
-union_lock_upper(struct union_node *un, struct proc *p)
-{
- struct vnode *uppervp;
-
- if ((uppervp = un->un_uppervp) != NULL) {
- VREF(uppervp);
- vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, p);
- }
- KASSERT((uppervp == NULL || uppervp->v_usecount > 0), ("uppervp usecount is 0"));
- return(uppervp);
-}
-
-static __inline
-void
-union_unlock_upper(struct vnode *uppervp, struct proc *p)
-{
- vput(uppervp);
-}
-
-static __inline
-struct vnode *
-union_lock_other(struct union_node *un, struct proc *p)
-{
- struct vnode *vp;
-
- if (un->un_uppervp != NULL) {
- vp = union_lock_upper(un, p);
- } else if ((vp = un->un_lowervp) != NULL) {
- VREF(vp);
- vn_lock(vp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, p);
- }
- return(vp);
-}
-
-static __inline
-void
-union_unlock_other(struct vnode *vp, struct proc *p)
-{
- vput(vp);
-}
-
-/*
- * union_lookup:
- *
- * udvp must be exclusively locked on call and will remain
- * exclusively locked on return. This is the mount point
- * for out filesystem.
- *
- * dvp Our base directory, locked and referenced.
- * The passed dvp will be dereferenced and unlocked on return
- * and a new dvp will be returned which is locked and
- * referenced in the same variable.
- *
- * vpp is filled in with the result if no error occured,
- * locked and ref'd.
- *
- * If an error is returned, *vpp is set to NULLVP. If no
- * error occurs, *vpp is returned with a reference and an
- * exclusive lock.
- */
-
-static int
-union_lookup1(udvp, pdvp, vpp, cnp)
- struct vnode *udvp;
- struct vnode **pdvp;
- struct vnode **vpp;
- struct componentname *cnp;
-{
- int error;
- struct proc *p = cnp->cn_proc;
- struct vnode *dvp = *pdvp;
- struct vnode *tdvp;
- struct mount *mp;
-
- /*
- * If stepping up the directory tree, check for going
- * back across the mount point, in which case do what
- * lookup would do by stepping back down the mount
- * hierarchy.
- */
- if (cnp->cn_flags & ISDOTDOT) {
- 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.
- */
- tdvp = dvp;
- dvp = dvp->v_mount->mnt_vnodecovered;
- VREF(dvp);
- vput(tdvp);
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
- }
- }
-
- /*
- * Set return dvp to be the upperdvp 'parent directory.
- */
- *pdvp = dvp;
-
- /*
- * If the VOP_LOOKUP call generates an error, tdvp is invalid and no
- * changes will have been made to dvp, so we are set to return.
- */
-
- error = VOP_LOOKUP(dvp, &tdvp, cnp);
- if (error) {
- UDEBUG(("dvp %p error %d flags %lx\n", dvp, error, cnp->cn_flags));
- *vpp = NULL;
- return (error);
- }
-
- /*
- * The parent directory will have been unlocked, unless lookup
- * found the last component or if dvp == tdvp (tdvp must be locked).
- *
- * We want our dvp to remain locked and ref'd. We also want tdvp
- * to remain locked and ref'd.
- */
- UDEBUG(("parentdir %p result %p flag %lx\n", dvp, tdvp, cnp->cn_flags));
-
- if (dvp != tdvp && (cnp->cn_flags & ISLASTCN) == 0)
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
-
- /*
- * Lastly check if the current node is a mount point in
- * which case walk up the mount hierarchy making sure not to
- * bump into the root of the mount tree (ie. dvp != udvp).
- *
- * We use dvp as a temporary variable here, it is no longer related
- * to the dvp above. However, we have to ensure that both *pdvp and
- * tdvp are locked on return.
- */
-
- dvp = tdvp;
- while (
- dvp != udvp &&
- (dvp->v_type == VDIR) &&
- (mp = dvp->v_mountedhere)
- ) {
- int relock_pdvp = 0;
-
- if (vfs_busy(mp, 0, 0, p))
- continue;
-
- if (dvp == *pdvp)
- relock_pdvp = 1;
- vput(dvp);
- dvp = NULL;
- error = VFS_ROOT(mp, &dvp);
-
- vfs_unbusy(mp, p);
-
- if (relock_pdvp)
- vn_lock(*pdvp, LK_EXCLUSIVE | LK_RETRY, p);
-
- if (error) {
- *vpp = NULL;
- return (error);
- }
- }
- *vpp = dvp;
- return (0);
-}
-
-static int
-union_lookup(ap)
- struct vop_lookup_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- int error;
- int uerror, lerror;
- struct vnode *uppervp, *lowervp;
- struct vnode *upperdvp, *lowerdvp;
- struct vnode *dvp = ap->a_dvp; /* starting dir */
- struct union_node *dun = VTOUNION(dvp); /* associated union node */
- 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 = NULL;
- int iswhiteout;
- struct vattr va;
-
- *ap->a_vpp = NULLVP;
-
- /*
- * Disallow write attemps to the filesystem mounted read-only.
- */
- if ((cnp->cn_flags & ISLASTCN) &&
- (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
- (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
- return (EROFS);
- }
-
- /*
- * For any lookup's we do, always return with the parent locked
- */
- cnp->cn_flags |= LOCKPARENT;
-
- lowerdvp = dun->un_lowervp;
- uppervp = NULLVP;
- lowervp = NULLVP;
- iswhiteout = 0;
-
- uerror = ENOENT;
- lerror = ENOENT;
-
- /*
- * Get a private lock on uppervp and a reference, effectively
- * taking it out of the union_node's control.
- *
- * We must lock upperdvp while holding our lock on dvp
- * to avoid a deadlock.
- */
- upperdvp = union_lock_upper(dun, p);
-
- /*
- * do the lookup in the upper level.
- * if that level comsumes additional pathnames,
- * then assume that something special is going
- * on and just return that vnode.
- */
- if (upperdvp != NULLVP) {
- /*
- * We do not have to worry about the DOTDOT case, we've
- * already unlocked dvp.
- */
- UDEBUG(("A %p\n", upperdvp));
-
- /*
- * Do the lookup. We must supply a locked and referenced
- * upperdvp to the function and will get a new locked and
- * referenced upperdvp back with the old having been
- * dereferenced.
- *
- * If an error is returned, uppervp will be NULLVP. If no
- * error occurs, uppervp will be the locked and referenced
- * return vnode or possibly NULL, depending on what is being
- * requested. It is possible that the returned uppervp
- * will be the same as upperdvp.
- */
- uerror = union_lookup1(um->um_uppervp, &upperdvp, &uppervp, cnp);
- UDEBUG((
- "uerror %d upperdvp %p %d/%d, uppervp %p ref=%d/lck=%d\n",
- uerror,
- upperdvp,
- upperdvp->v_usecount,
- VOP_ISLOCKED(upperdvp, NULL),
- uppervp,
- (uppervp ? uppervp->v_usecount : -99),
- (uppervp ? VOP_ISLOCKED(uppervp, NULL) : -99)
- ));
-
- /*
- * Disallow write attemps to the filesystem mounted read-only.
- */
- if (uerror == EJUSTRETURN && (cnp->cn_flags & ISLASTCN) &&
- (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
- (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) {
- error = EROFS;
- goto out;
- }
-
- /*
- * Special case. If cn_consume != 0 skip out. The result
- * of the lookup is transfered to our return variable. If
- * an error occured we have to throw away the results.
- */
-
- if (cnp->cn_consume != 0) {
- if ((error = uerror) == 0) {
- *ap->a_vpp = uppervp;
- uppervp = NULL;
- }
- goto out;
- }
-
- /*
- * Calculate whiteout, fall through
- */
-
- if (uerror == ENOENT || uerror == EJUSTRETURN) {
- if (cnp->cn_flags & ISWHITEOUT) {
- iswhiteout = 1;
- } else if (lowerdvp != NULLVP) {
- int terror;
-
- terror = VOP_GETATTR(upperdvp, &va,
- cnp->cn_cred, cnp->cn_proc);
- if (terror == 0 && (va.va_flags & OPAQUE))
- iswhiteout = 1;
- }
- }
- }
-
- /*
- * in a similar way to the upper layer, do the lookup
- * in the lower layer. this time, if there is some
- * component magic going on, then vput whatever we got
- * back from the upper layer and return the lower vnode
- * instead.
- */
-
- if (lowerdvp != NULLVP && !iswhiteout) {
- int nameiop;
-
- UDEBUG(("B %p\n", lowerdvp));
-
- /*
- * Force only LOOKUPs on the lower node, since
- * we won't be making changes to it anyway.
- */
- nameiop = cnp->cn_nameiop;
- cnp->cn_nameiop = LOOKUP;
- if (um->um_op == UNMNT_BELOW) {
- saved_cred = cnp->cn_cred;
- cnp->cn_cred = um->um_cred;
- }
-
- /*
- * We shouldn't have to worry about locking interactions
- * between the lower layer and our union layer (w.r.t.
- * `..' processing) because we don't futz with lowervp
- * locks in the union-node instantiation code path.
- *
- * union_lookup1() requires lowervp to be locked on entry,
- * and it will be unlocked on return. The ref count will
- * not change. On return lowervp doesn't represent anything
- * to us so we NULL it out.
- */
- VREF(lowerdvp);
- vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, p);
- lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp);
- if (lowerdvp == lowervp)
- vrele(lowerdvp);
- else
- vput(lowerdvp);
- lowerdvp = NULL; /* lowerdvp invalid after vput */
-
- if (um->um_op == UNMNT_BELOW)
- cnp->cn_cred = saved_cred;
- cnp->cn_nameiop = nameiop;
-
- if (cnp->cn_consume != 0 || lerror == EACCES) {
- if ((error = lerror) == 0) {
- *ap->a_vpp = lowervp;
- lowervp = NULL;
- }
- goto out;
- }
- } else {
- UDEBUG(("C %p\n", lowerdvp));
- if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) {
- if ((lowervp = LOWERVP(dun->un_pvp)) != NULL) {
- VREF(lowervp);
- vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, p);
- lerror = 0;
- }
- }
- }
-
- /*
- * Ok. Now we have uerror, uppervp, upperdvp, lerror, and lowervp.
- *
- * 1. If both layers returned an error, select the upper layer.
- *
- * 2. If the upper layer faile and the bottom layer succeeded,
- * two subcases occur:
- *
- * a. The bottom vnode is not a directory, in which case
- * just return a new union vnode referencing an
- * empty top layer and the existing bottom layer.
- *
- * b. The button vnode is a directory, in which case
- * create a new directory in the top layer and
- * and fall through to case 3.
- *
- * 3. If the top layer succeeded then return a new union
- * vnode referencing whatever the new top layer and
- * whatever the bottom layer returned.
- */
-
- /* case 1. */
- if ((uerror != 0) && (lerror != 0)) {
- error = uerror;
- goto out;
- }
-
- /* case 2. */
- if (uerror != 0 /* && (lerror == 0) */ ) {
- if (lowervp->v_type == VDIR) { /* case 2b. */
- KASSERT(uppervp == NULL, ("uppervp unexpectedly non-NULL"));
- /*
- * oops, uppervp has a problem, we may have to shadow.
- */
- uerror = union_mkshadow(um, upperdvp, cnp, &uppervp);
- if (uerror) {
- error = uerror;
- goto out;
- }
- }
- }
-
- /*
- * Must call union_allocvp with both the upper and lower vnodes
- * referenced and the upper vnode locked. ap->a_vpp is returned
- * referenced and locked. lowervp, uppervp, and upperdvp are
- * absorbed by union_allocvp() whether it succeeds or fails.
- *
- * upperdvp is the parent directory of uppervp which may be
- * different, depending on the path, from dvp->un_uppervp. That's
- * why it is a separate argument. Note that it must be unlocked.
- *
- * dvp must be locked on entry to the call and will be locked on
- * return.
- */
-
- if (uppervp && uppervp != upperdvp)
- VOP_UNLOCK(uppervp, 0, p);
- if (lowervp)
- VOP_UNLOCK(lowervp, 0, p);
- if (upperdvp)
- VOP_UNLOCK(upperdvp, 0, p);
-
- error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
- uppervp, lowervp, 1);
-
- UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? ((*ap->a_vpp)->v_usecount) : -99));
-
- uppervp = NULL;
- upperdvp = NULL;
- lowervp = NULL;
-
- /*
- * Termination Code
- *
- * - put away any extra junk laying around. Note that lowervp
- * (if not NULL) will never be the same as *ap->a_vp and
- * neither will uppervp, because when we set that state we
- * NULL-out lowervp or uppervp. On the otherhand, upperdvp
- * may match uppervp or *ap->a_vpp.
- *
- * - relock/unlock dvp if appropriate.
- */
-
-out:
- if (upperdvp) {
- if (upperdvp == uppervp || upperdvp == *ap->a_vpp)
- vrele(upperdvp);
- else
- vput(upperdvp);
- }
-
- if (uppervp)
- vput(uppervp);
-
- if (lowervp)
- vput(lowervp);
-
- /*
- * Restore LOCKPARENT state
- */
-
- if (!lockparent)
- cnp->cn_flags &= ~LOCKPARENT;
-
- UDEBUG(("Out %d vpp %p/%d lower %p upper %p\n", error, *ap->a_vpp,
- ((*ap->a_vpp) ? (*ap->a_vpp)->v_usecount : -99),
- lowervp, uppervp));
-
- /*
- * dvp lock state, determine whether to relock dvp. dvp is expected
- * to be locked on return if:
- *
- * - there was an error (except not EJUSTRETURN), or
- * - we hit the last component and lockparent is true
- *
- * dvp_is_locked is the current state of the dvp lock, not counting
- * the possibility that *ap->a_vpp == dvp (in which case it is locked
- * anyway). Note that *ap->a_vpp == dvp only if no error occured.
- */
-
- if (*ap->a_vpp != dvp) {
- if ((error == 0 || error == EJUSTRETURN) &&
- (!lockparent || (cnp->cn_flags & ISLASTCN) == 0)) {
- VOP_UNLOCK(dvp, 0, p);
- }
- }
-
- /*
- * Diagnostics
- */
-
-#ifdef DIAGNOSTIC
- if (cnp->cn_namelen == 1 &&
- cnp->cn_nameptr[0] == '.' &&
- *ap->a_vpp != dvp) {
- panic("union_lookup returning . (%p) not same as startdir (%p)", ap->a_vpp, dvp);
- }
-#endif
-
- return (error);
-}
-
-/*
- * union_create:
- *
- * a_dvp is locked on entry and remains locked on return. a_vpp is returned
- * locked if no error occurs, otherwise it is garbage.
- */
-
-static int
-union_create(ap)
- struct vop_create_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- struct union_node *dun = VTOUNION(ap->a_dvp);
- struct componentname *cnp = ap->a_cnp;
- struct proc *p = cnp->cn_proc;
- struct vnode *dvp;
- int error = EROFS;
-
- if ((dvp = union_lock_upper(dun, p)) != NULL) {
- struct vnode *vp;
- struct mount *mp;
-
- error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
- if (error == 0) {
- mp = ap->a_dvp->v_mount;
- VOP_UNLOCK(vp, 0, p);
- UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vp->v_usecount));
- error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
- cnp, vp, NULLVP, 1);
- UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_usecount));
- }
- union_unlock_upper(dvp, p);
- }
- return (error);
-}
-
-static 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 vnode *uppervp;
- int error = EOPNOTSUPP;
-
- if ((uppervp = union_lock_upper(un, cnp->cn_proc)) != NULLVP) {
- error = VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags);
- union_unlock_upper(uppervp, cnp->cn_proc);
- }
- return(error);
-}
-
-/*
- * union_mknod:
- *
- * a_dvp is locked on entry and should remain locked on return.
- * a_vpp is garbagre whether an error occurs or not.
- */
-
-static int
-union_mknod(ap)
- struct vop_mknod_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- struct union_node *dun = VTOUNION(ap->a_dvp);
- struct componentname *cnp = ap->a_cnp;
- struct vnode *dvp;
- int error = EROFS;
-
- if ((dvp = union_lock_upper(dun, cnp->cn_proc)) != NULL) {
- error = VOP_MKNOD(dvp, ap->a_vpp, cnp, ap->a_vap);
- union_unlock_upper(dvp, cnp->cn_proc);
- }
- return (error);
-}
-
-/*
- * union_open:
- *
- * run open VOP. When opening the underlying vnode we have to mimic
- * vn_open. What we *really* need to do to avoid screwups if the
- * open semantics change is to call vn_open(). For example, ufs blows
- * up if you open a file but do not vmio it prior to writing.
- */
-
-static int
-union_open(ap)
- struct vop_open_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct union_node *un = VTOUNION(ap->a_vp);
- struct vnode *tvp;
- int mode = ap->a_mode;
- struct ucred *cred = ap->a_cred;
- struct proc *p = ap->a_p;
- int error = 0;
- int tvpisupper = 1;
-
- /*
- * If there is an existing upper vp then simply open that.
- * The upper vp takes precedence over the lower vp. When opening
- * a lower vp for writing copy it to the uppervp and then open the
- * uppervp.
- *
- * At the end of this section tvp will be left locked.
- */
- if ((tvp = union_lock_upper(un, p)) == NULLVP) {
- /*
- * If the lower vnode is being opened for writing, then
- * copy the file contents to the upper vnode and open that,
- * otherwise can simply open the lower vnode.
- */
- tvp = un->un_lowervp;
- if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
- int docopy = !(mode & O_TRUNC);
- error = union_copyup(un, docopy, cred, p);
- tvp = union_lock_upper(un, p);
- } else {
- un->un_openl++;
- VREF(tvp);
- vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p);
- tvpisupper = 0;
- }
- }
-
- /*
- * We are holding the correct vnode, open it
- */
-
- if (error == 0)
- error = VOP_OPEN(tvp, mode, cred, p);
-
- /*
- * Absolutely necessary or UFS will blowup
- */
- if (error == 0 && vn_canvmio(tvp) == TRUE) {
- error = vfs_object_create(tvp, p, cred);
- }
-
- /*
- * Release any locks held
- */
- if (tvpisupper) {
- if (tvp)
- union_unlock_upper(tvp, p);
- } else {
- vput(tvp);
- }
- return (error);
-}
-
-/*
- * union_close:
- *
- * It is unclear whether a_vp is passed locked or unlocked. Whatever
- * the case we do not change it.
- */
-
-static int
-union_close(ap)
- struct vop_close_args /* {
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct union_node *un = VTOUNION(ap->a_vp);
- struct vnode *vp;
-
- if ((vp = un->un_uppervp) == NULLVP) {
-#ifdef UNION_DIAGNOSTIC
- if (un->un_openl <= 0)
- panic("union: un_openl cnt");
-#endif
- --un->un_openl;
- vp = un->un_lowervp;
- }
- ap->a_vp = vp;
- return (VCALL(vp, VOFFSET(vop_close), ap));
-}
-
-/*
- * Check access permission on the union vnode.
- * The access check being enforced is to check
- * against both the underlying vnode, and any
- * copied vnode. This ensures that no additional
- * file permissions are given away simply because
- * the user caused an implicit file copy.
- */
-static int
-union_access(ap)
- struct vop_access_args /* {
- struct vnodeop_desc *a_desc;
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct union_node *un = VTOUNION(ap->a_vp);
- struct proc *p = ap->a_p;
- int error = EACCES;
- struct vnode *vp;
-
- /*
- * Disallow write attempts on filesystems mounted read-only.
- */
- if ((ap->a_mode & VWRITE) &&
- (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) {
- switch (ap->a_vp->v_type) {
- case VREG:
- case VDIR:
- case VLNK:
- return (EROFS);
- default:
- break;
- }
- }
-
- if ((vp = union_lock_upper(un, p)) != NULLVP) {
- ap->a_vp = vp;
- error = VCALL(vp, VOFFSET(vop_access), ap);
- union_unlock_upper(vp, p);
- return(error);
- }
-
- if ((vp = un->un_lowervp) != NULLVP) {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
- ap->a_vp = vp;
-
- /*
- * Remove VWRITE from a_mode if our mount point is RW, because
- * we want to allow writes and lowervp may be read-only.
- */
- if ((un->un_vnode->v_mount->mnt_flag & MNT_RDONLY) == 0)
- ap->a_mode &= ~VWRITE;
-
- error = VCALL(vp, VOFFSET(vop_access), ap);
- if (error == 0) {
- struct union_mount *um;
-
- um = MOUNTTOUNIONMOUNT(un->un_vnode->v_mount);
-
- if (um->um_op == UNMNT_BELOW) {
- ap->a_cred = um->um_cred;
- error = VCALL(vp, VOFFSET(vop_access), ap);
- }
- }
- VOP_UNLOCK(vp, 0, p);
- }
- return(error);
-}
-
-/*
- * We handle getattr only to change the fsid and
- * track object sizes
- *
- * 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.
- *
- * Because of this we cannot use our normal locking functions
- * if we do not intend to lock the main a_vp node. At the moment
- * we are running without any specific locking at all, but beware
- * to any programmer that care must be taken if locking is added
- * to this function.
- */
-
-static int
-union_getattr(ap)
- struct vop_getattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- int error;
- struct union_node *un = VTOUNION(ap->a_vp);
- struct vnode *vp;
- struct vattr *vap;
- struct vattr va;
-
- /*
- * Some programs walk the filesystem hierarchy by counting
- * links to directories to avoid stat'ing all the time.
- * This means the link count on directories needs to be "correct".
- * The only way to do that is to call getattr on both layers
- * and fix up the link count. The link count will not necessarily
- * be accurate but will be large enough to defeat the tree walkers.
- */
-
- vap = ap->a_vap;
-
- if ((vp = un->un_uppervp) != NULLVP) {
- error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
- if (error)
- return (error);
- /* XXX isn't this dangerouso without a lock? */
- union_newsize(ap->a_vp, vap->va_size, VNOVAL);
- }
-
- if (vp == NULLVP) {
- vp = un->un_lowervp;
- } else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) {
- vp = un->un_lowervp;
- vap = &va;
- } else {
- vp = NULLVP;
- }
-
- if (vp != NULLVP) {
- error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
- if (error)
- return (error);
- /* XXX isn't this dangerous without a lock? */
- 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;
- return (0);
-}
-
-static int
-union_setattr(ap)
- struct vop_setattr_args /* {
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct union_node *un = VTOUNION(ap->a_vp);
- struct proc *p = ap->a_p;
- struct vattr *vap = ap->a_vap;
- struct vnode *uppervp;
- int error;
-
- /*
- * Disallow write attempts on filesystems mounted read-only.
- */
- if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) &&
- (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)) {
- return (EROFS);
- }
-
- /*
- * Handle case of truncating lower object to zero size,
- * by creating a zero length upper object. This is to
- * handle the case of open with O_TRUNC and O_CREAT.
- */
- if (un->un_uppervp == NULLVP && (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);
- }
-
- /*
- * Try to set attributes in upper layer,
- * otherwise return read-only filesystem error.
- */
- error = EROFS;
- if ((uppervp = union_lock_upper(un, p)) != NULLVP) {
- 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);
- union_unlock_upper(uppervp, p);
- }
- return (error);
-}
-
-static int
-union_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct union_node *un = VTOUNION(ap->a_vp);
- struct proc *p = ap->a_uio->uio_procp;
- struct vnode *uvp;
- int error;
-
- uvp = union_lock_other(un, p);
- KASSERT(uvp != NULL, ("union_read: backing vnode missing!"));
-
- error = VOP_READ(uvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
- union_unlock_other(uvp, 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 (uvp == 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);
-}
-
-static int
-union_write(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- struct union_node *un = VTOUNION(ap->a_vp);
- struct proc *p = ap->a_uio->uio_procp;
- struct vnode *uppervp;
- int error;
-
- if ((uppervp = union_lock_upper(un, p)) == NULLVP)
- panic("union: missing upper layer in write");
-
- error = VOP_WRITE(uppervp, ap->a_uio, ap->a_ioflag, ap->a_cred);
-
- /*
- * 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);
- }
- union_unlock_upper(uppervp, p);
- return (error);
-}
-
-static int
-union_lease(ap)
- struct vop_lease_args /* {
- struct vnode *a_vp;
- struct proc *a_p;
- struct ucred *a_cred;
- int a_flag;
- } */ *ap;
-{
- struct vnode *ovp = OTHERVP(ap->a_vp);
-
- ap->a_vp = ovp;
- return (VCALL(ovp, VOFFSET(vop_lease), ap));
-}
-
-static int
-union_ioctl(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;
-{
- struct vnode *ovp = OTHERVP(ap->a_vp);
-
- ap->a_vp = ovp;
- return (VCALL(ovp, VOFFSET(vop_ioctl), ap));
-}
-
-static int
-union_poll(ap)
- struct vop_poll_args /* {
- struct vnode *a_vp;
- int a_events;
- struct ucred *a_cred;
- struct proc *a_p;
- } */ *ap;
-{
- struct vnode *ovp = OTHERVP(ap->a_vp);
-
- ap->a_vp = ovp;
- return (VCALL(ovp, VOFFSET(vop_poll), ap));
-}
-
-static 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);
-}
-
-static int
-union_fsync(ap)
- struct vop_fsync_args /* {
- struct vnode *a_vp;
- struct ucred *a_cred;
- int a_waitfor;
- struct proc *a_p;
- } */ *ap;
-{
- int error = 0;
- struct proc *p = ap->a_p;
- struct vnode *targetvp;
- struct union_node *un = VTOUNION(ap->a_vp);
-
- if ((targetvp = union_lock_other(un, p)) != NULLVP) {
- error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
- union_unlock_other(targetvp, p);
- }
-
- return (error);
-}
-
-/*
- * union_remove:
- *
- * Remove the specified cnp. The dvp and vp are passed to us locked
- * and must remain locked on return.
- */
-
-static int
-union_remove(ap)
- struct vop_remove_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- 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;
- struct vnode *uppervp;
- struct vnode *upperdvp;
- int error;
-
- if ((upperdvp = union_lock_upper(dun, p)) == NULLVP)
- panic("union remove: null upper vnode");
-
- if ((uppervp = union_lock_upper(un, p)) != NULLVP) {
- if (union_dowhiteout(un, cnp->cn_cred, p))
- cnp->cn_flags |= DOWHITEOUT;
- error = VOP_REMOVE(upperdvp, uppervp, cnp);
-#if 0
- /* XXX */
- if (!error)
- union_removed_upper(un);
-#endif
- union_unlock_upper(uppervp, p);
- } else {
- error = union_mkwhiteout(
- MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
- upperdvp, ap->a_cnp, un->un_path);
- }
- union_unlock_upper(upperdvp, p);
- return (error);
-}
-
-/*
- * union_link:
- *
- * tdvp will be locked on entry, vp will not be locked on entry.
- * tdvp should remain locked on return and vp should remain unlocked
- * on return.
- */
-
-static int
-union_link(ap)
- struct vop_link_args /* {
- struct vnode *a_tdvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- struct componentname *cnp = ap->a_cnp;
- struct proc *p = cnp->cn_proc;
- struct union_node *dun = VTOUNION(ap->a_tdvp);
- struct vnode *vp;
- struct vnode *tdvp;
- int error = 0;
-
- if (ap->a_tdvp->v_op != ap->a_vp->v_op) {
- vp = ap->a_vp;
- } else {
- struct union_node *tun = VTOUNION(ap->a_vp);
-
- if (tun->un_uppervp == NULLVP) {
- vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p);
-#if 0
- if (dun->un_uppervp == tun->un_dirvp) {
- if (dun->un_flags & UN_ULOCK) {
- dun->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(dun->un_uppervp, 0, p);
- }
- }
-#endif
- error = union_copyup(tun, 1, cnp->cn_cred, p);
-#if 0
- if (dun->un_uppervp == tun->un_dirvp) {
- vn_lock(dun->un_uppervp,
- LK_EXCLUSIVE | LK_RETRY, p);
- dun->un_flags |= UN_ULOCK;
- }
-#endif
- VOP_UNLOCK(ap->a_vp, 0, p);
- }
- vp = tun->un_uppervp;
- }
-
- if (error)
- return (error);
-
- /*
- * Make sure upper is locked, then unlock the union directory we were
- * called with to avoid a deadlock while we are calling VOP_LINK on
- * the upper (with tdvp locked and vp not locked). Our ap->a_tdvp
- * is expected to be locked on return.
- */
-
- if ((tdvp = union_lock_upper(dun, p)) == NULLVP)
- return (EROFS);
-
- VOP_UNLOCK(ap->a_tdvp, 0, p); /* unlock calling node */
- error = VOP_LINK(tdvp, vp, cnp); /* call link on upper */
-
- /*
- * We have to unlock tdvp prior to relocking our calling node in
- * order to avoid a deadlock.
- */
- union_unlock_upper(tdvp, p);
- vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY, p);
- return (error);
-}
-
-static int
-union_rename(ap)
- struct vop_rename_args /* {
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
- } */ *ap;
-{
- int error;
- struct vnode *fdvp = ap->a_fdvp;
- struct vnode *fvp = ap->a_fvp;
- struct vnode *tdvp = ap->a_tdvp;
- struct vnode *tvp = ap->a_tvp;
-
- /*
- * Figure out what fdvp to pass to our upper or lower vnode. If we
- * replace the fdvp, release the original one and ref the new one.
- */
-
- if (fdvp->v_op == union_vnodeop_p) { /* always true */
- struct union_node *un = VTOUNION(fdvp);
- if (un->un_uppervp == NULLVP) {
- /*
- * this should never happen in normal
- * operation but might if there was
- * a problem creating the top-level shadow
- * directory.
- */
- error = EXDEV;
- goto bad;
- }
- fdvp = un->un_uppervp;
- VREF(fdvp);
- vrele(ap->a_fdvp);
- }
-
- /*
- * Figure out what fvp to pass to our upper or lower vnode. If we
- * replace the fvp, release the original one and ref the new one.
- */
-
- if (fvp->v_op == union_vnodeop_p) { /* always true */
- struct union_node *un = VTOUNION(fvp);
-#if 0
- struct union_mount *um = MOUNTTOUNIONMOUNT(fvp->v_mount);
-#endif
-
- if (un->un_uppervp == NULLVP) {
- switch(fvp->v_type) {
- case VREG:
- vn_lock(un->un_vnode, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_proc);
- error = union_copyup(un, 1, ap->a_fcnp->cn_cred, ap->a_fcnp->cn_proc);
- VOP_UNLOCK(un->un_vnode, 0, ap->a_fcnp->cn_proc);
- if (error)
- goto bad;
- break;
- case VDIR:
- /*
- * XXX not yet.
- *
- * There is only one way to rename a directory
- * based in the lowervp, and that is to copy
- * the entire directory hierarchy. Otherwise
- * it would not last across a reboot.
- */
-#if 0
- vrele(fvp);
- fvp = NULL;
- vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_proc);
- error = union_mkshadow(um, fdvp,
- ap->a_fcnp, &un->un_uppervp);
- VOP_UNLOCK(fdvp, 0, ap->a_fcnp->cn_proc);
- if (un->un_uppervp)
- VOP_UNLOCK(un->un_uppervp, 0, ap->a_fcnp->cn_proc);
- if (error)
- goto bad;
- break;
-#endif
- default:
- error = EXDEV;
- goto bad;
- }
- }
-
- if (un->un_lowervp != NULLVP)
- ap->a_fcnp->cn_flags |= DOWHITEOUT;
- fvp = un->un_uppervp;
- VREF(fvp);
- vrele(ap->a_fvp);
- }
-
- /*
- * Figure out what tdvp (destination directory) to pass to the
- * lower level. If we replace it with uppervp, we need to vput the
- * old one. The exclusive lock is transfered to what we will pass
- * down in the VOP_RENAME and we replace uppervp with a simple
- * reference.
- */
-
- if (tdvp->v_op == union_vnodeop_p) {
- struct union_node *un = VTOUNION(tdvp);
-
- if (un->un_uppervp == NULLVP) {
- /*
- * this should never happen in normal
- * operation but might if there was
- * a problem creating the top-level shadow
- * directory.
- */
- error = EXDEV;
- goto bad;
- }
-
- /*
- * new tdvp is a lock and reference on uppervp, put away
- * the old tdvp.
- */
- tdvp = union_lock_upper(un, ap->a_tcnp->cn_proc);
- vput(ap->a_tdvp);
- }
-
- /*
- * Figure out what tvp (destination file) to pass to the
- * lower level.
- *
- * If the uppervp file does not exist put away the (wrong)
- * file and change tvp to NULL.
- */
-
- if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) {
- struct union_node *un = VTOUNION(tvp);
-
- tvp = union_lock_upper(un, ap->a_tcnp->cn_proc);
- vput(ap->a_tvp);
- /* note: tvp may be NULL */
- }
-
- /*
- * VOP_RENAME releases/vputs prior to returning, so we have no
- * cleanup to do.
- */
-
- return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp));
-
- /*
- * Error. We still have to release / vput the various elements.
- */
-
-bad:
- vrele(fdvp);
- if (fvp)
- vrele(fvp);
- vput(tdvp);
- if (tvp != NULLVP) {
- if (tvp != tdvp)
- vput(tvp);
- else
- vrele(tvp);
- }
- return (error);
-}
-
-static int
-union_mkdir(ap)
- struct vop_mkdir_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- } */ *ap;
-{
- struct union_node *dun = VTOUNION(ap->a_dvp);
- struct componentname *cnp = ap->a_cnp;
- struct proc *p = cnp->cn_proc;
- struct vnode *upperdvp;
- int error = EROFS;
-
- if ((upperdvp = union_lock_upper(dun, p)) != NULLVP) {
- struct vnode *vp;
-
- error = VOP_MKDIR(upperdvp, &vp, cnp, ap->a_vap);
- union_unlock_upper(upperdvp, p);
-
- if (error == 0) {
- VOP_UNLOCK(vp, 0, p);
- UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vp->v_usecount));
- error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount,
- ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1);
- UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vp->v_usecount));
- }
- }
- return (error);
-}
-
-static int
-union_rmdir(ap)
- struct vop_rmdir_args /* {
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
- } */ *ap;
-{
- 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;
- struct vnode *upperdvp;
- struct vnode *uppervp;
- int error;
-
- if ((upperdvp = union_lock_upper(dun, p)) == NULLVP)
- panic("union rmdir: null upper vnode");
-
- if ((uppervp = union_lock_upper(un, p)) != NULLVP) {
- if (union_dowhiteout(un, cnp->cn_cred, p))
- cnp->cn_flags |= DOWHITEOUT;
- error = VOP_RMDIR(upperdvp, uppervp, ap->a_cnp);
- union_unlock_upper(uppervp, p);
- } else {
- error = union_mkwhiteout(
- MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
- dun->un_uppervp, ap->a_cnp, un->un_path);
- }
- union_unlock_upper(upperdvp, p);
- return (error);
-}
-
-/*
- * union_symlink:
- *
- * dvp is locked on entry and remains locked on return. a_vpp is garbage
- * (unused).
- */
-
-static int
-union_symlink(ap)
- struct vop_symlink_args /* {
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
- } */ *ap;
-{
- struct union_node *dun = VTOUNION(ap->a_dvp);
- struct componentname *cnp = ap->a_cnp;
- struct proc *p = cnp->cn_proc;
- struct vnode *dvp;
- int error = EROFS;
-
- if ((dvp = union_lock_upper(dun, p)) != NULLVP) {
- error = VOP_SYMLINK(dvp, ap->a_vpp, cnp, ap->a_vap,
- ap->a_target);
- union_unlock_upper(dvp, p);
- }
- return (error);
-}
-
-/*
- * union_readdir works in concert with getdirentries and
- * readdir(3) to provide a list of entries in the unioned
- * directories. getdirentries is responsible for walking
- * down the union stack. readdir(3) is responsible for
- * eliminating duplicate names from the returned data stream.
- */
-static int
-union_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;
-{
- struct union_node *un = VTOUNION(ap->a_vp);
- struct proc *p = ap->a_uio->uio_procp;
- struct vnode *uvp;
- int error = 0;
-
- if ((uvp = union_lock_upper(un, p)) != NULLVP) {
- ap->a_vp = uvp;
- error = VCALL(uvp, VOFFSET(vop_readdir), ap);
- union_unlock_upper(uvp, p);
- }
- return(error);
-}
-
-static int
-union_readlink(ap)
- struct vop_readlink_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- } */ *ap;
-{
- int error;
- struct union_node *un = VTOUNION(ap->a_vp);
- struct uio *uio = ap->a_uio;
- struct proc *p = uio->uio_procp;
- struct vnode *vp;
-
- vp = union_lock_other(un, p);
- KASSERT(vp != NULL, ("union_readlink: backing vnode missing!"));
-
- ap->a_vp = vp;
- error = VCALL(vp, VOFFSET(vop_readlink), ap);
- union_unlock_other(vp, p);
-
- return (error);
-}
-
-static int
-union_getwritemount(ap)
- struct vop_getwritemount_args /* {
- struct vnode *a_vp;
- struct mount **a_mpp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
- struct vnode *uvp = UPPERVP(vp);
-
- if (uvp == NULL) {
- VI_LOCK(vp);
- if (vp->v_flag & VFREE) {
- VI_UNLOCK(vp);
- return (EOPNOTSUPP);
- }
- VI_UNLOCK(vp);
- return (EACCES);
- }
- return(VOP_GETWRITEMOUNT(uvp, ap->a_mpp));
-}
-
-/*
- * union_inactive:
- *
- * Called with the vnode locked. We are expected to unlock the vnode.
- */
-
-static 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).
- * Wait to vrele lowervp until reclaim,
- * so that until then our union_node is in the
- * cache and reusable.
- *
- * NEEDSWORK: Someday, consider inactive'ing
- * the lowervp and then trying to reactivate it
- * with capabilities (v_id)
- * like they do in the name lookup cache code.
- * That's too much work for now.
- */
-
- 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 0
- if ((un->un_flags & UN_ULOCK) && un->un_uppervp) {
- un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp, 0, p);
- }
-#endif
-
- VOP_UNLOCK(vp, 0, p);
-
- if ((un->un_flags & UN_CACHED) == 0)
- vgone(vp);
-
- return (0);
-}
-
-static int
-union_reclaim(ap)
- struct vop_reclaim_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- union_freevp(ap->a_vp);
-
- return (0);
-}
-
-static int
-union_lock(ap)
- struct vop_lock_args *ap;
-{
-#if 0
- struct vnode *vp = ap->a_vp;
- struct proc *p = ap->a_p;
- int flags = ap->a_flags;
- struct union_node *un;
-#endif
- int error;
-
- error = vop_stdlock(ap);
-#if 0
- un = VTOUNION(vp);
-
- if (error == 0) {
- /*
- * Lock the upper if it exists and this is an exclusive lock
- * request.
- */
- if (un->un_uppervp != NULLVP &&
- (flags & LK_TYPE_MASK) == LK_EXCLUSIVE) {
- if ((un->un_flags & UN_ULOCK) == 0 && vp->v_usecount) {
- error = vn_lock(un->un_uppervp, flags, p);
- if (error) {
- struct vop_unlock_args uap = { 0 };
- uap.a_vp = ap->a_vp;
- uap.a_flags = ap->a_flags;
- uap.a_p = ap->a_p;
- vop_stdunlock(&uap);
- return (error);
- }
- un->un_flags |= UN_ULOCK;
- }
- }
- }
-#endif
- return (error);
-}
-
-/*
- * union_unlock:
- *
- * Unlock our union node. This also unlocks uppervp.
- */
-static int
-union_unlock(ap)
- struct vop_unlock_args /* {
- struct vnode *a_vp;
- int a_flags;
- struct proc *a_p;
- } */ *ap;
-{
-#if 0
- struct union_node *un = VTOUNION(ap->a_vp);
-#endif
- int error;
-
-#if 0
- KASSERT((un->un_uppervp == NULL || un->un_uppervp->v_usecount > 0), ("uppervp usecount is 0"));
-#endif
-
- error = vop_stdunlock(ap);
-#if 0
-
- /*
- * If no exclusive locks remain and we are holding an uppervp lock,
- * remove the uppervp lock.
- */
-
- if ((un->un_flags & UN_ULOCK) &&
- lockstatus(&un->un_lock, NULL) != LK_EXCLUSIVE) {
- un->un_flags &= ~UN_ULOCK;
- VOP_UNLOCK(un->un_uppervp, LK_EXCLUSIVE, p);
- }
-#endif
- return(error);
-}
-
-/*
- * unionvp do not hold a VM object and there is no need to create one for
- * upper or lower vp because it is done in the union_open()
- */
-static int
-union_createvobject(ap)
- struct vop_createvobject_args /* {
- struct vnode *vp;
- struct ucred *cred;
- struct proc *p;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- vp->v_flag |= VOBJBUF;
- return (0);
-}
-
-/*
- * We have nothing to destroy and this operation shouldn't be bypassed.
- */
-static int
-union_destroyvobject(ap)
- struct vop_destroyvobject_args /* {
- struct vnode *vp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- vp->v_flag &= ~VOBJBUF;
- return (0);
-}
-
-/*
- * Get VM object from the upper or lower vp
- */
-static int
-union_getvobject(ap)
- struct vop_getvobject_args /* {
- struct vnode *vp;
- struct vm_object **objpp;
- } */ *ap;
-{
- struct vnode *ovp = OTHERVP(ap->a_vp);
-
- if (ovp == NULL)
- return EINVAL;
- return (VOP_GETVOBJECT(ovp, ap->a_objpp));
-}
-
-static int
-union_print(ap)
- struct vop_print_args /* {
- struct vnode *a_vp;
- } */ *ap;
-{
- struct vnode *vp = ap->a_vp;
-
- 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);
-}
-
-static int
-union_pathconf(ap)
- struct vop_pathconf_args /* {
- struct vnode *a_vp;
- int a_name;
- int *a_retval;
- } */ *ap;
-{
- int error;
- struct proc *p = curproc; /* XXX */
- struct union_node *un = VTOUNION(ap->a_vp);
- struct vnode *vp;
-
- vp = union_lock_other(un, p);
- KASSERT(vp != NULL, ("union_pathconf: backing vnode missing!"));
-
- ap->a_vp = vp;
- error = VCALL(vp, VOFFSET(vop_pathconf), ap);
- union_unlock_other(vp, p);
-
- return (error);
-}
-
-static int
-union_advlock(ap)
- struct vop_advlock_args /* {
- struct vnode *a_vp;
- caddr_t a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- } */ *ap;
-{
- register struct vnode *ovp = OTHERVP(ap->a_vp);
-
- ap->a_vp = ovp;
- return (VCALL(ovp, VOFFSET(vop_advlock), ap));
-}
-
-
-/*
- * XXX - vop_strategy must be hand coded because it has no
- * YYY - and it is not coherent with anything
- *
- * vnode in its arguments.
- * This goes away with a merged VM/buffer cache.
- */
-static int
-union_strategy(ap)
- struct vop_strategy_args /* {
- struct vnode *a_vp;
- struct buf *a_bp;
- } */ *ap;
-{
- struct buf *bp = ap->a_bp;
- struct vnode *othervp = OTHERVP(bp->b_vp);
-
-#ifdef DIAGNOSTIC
- if (othervp == NULLVP)
- panic("union_strategy: nil vp");
- if ((bp->b_iocmd == BIO_WRITE) &&
- (othervp == LOWERVP(bp->b_vp)))
- panic("union_strategy: writing to lowervp");
-#endif
- return (VOP_STRATEGY(othervp, bp));
-}
-
-/*
- * Global vfs data structures
- */
-vop_t **union_vnodeop_p;
-static struct vnodeopv_entry_desc union_vnodeop_entries[] = {
- { &vop_default_desc, (vop_t *) vop_defaultop },
- { &vop_access_desc, (vop_t *) union_access },
- { &vop_advlock_desc, (vop_t *) union_advlock },
- { &vop_bmap_desc, (vop_t *) vop_eopnotsupp },
- { &vop_close_desc, (vop_t *) union_close },
- { &vop_create_desc, (vop_t *) union_create },
- { &vop_createvobject_desc, (vop_t *) union_createvobject },
- { &vop_destroyvobject_desc, (vop_t *) union_destroyvobject },
- { &vop_fsync_desc, (vop_t *) union_fsync },
- { &vop_getattr_desc, (vop_t *) union_getattr },
- { &vop_getvobject_desc, (vop_t *) union_getvobject },
- { &vop_inactive_desc, (vop_t *) union_inactive },
- { &vop_ioctl_desc, (vop_t *) union_ioctl },
- { &vop_islocked_desc, (vop_t *) vop_stdislocked },
- { &vop_lease_desc, (vop_t *) union_lease },
- { &vop_link_desc, (vop_t *) union_link },
- { &vop_lock_desc, (vop_t *) union_lock },
- { &vop_lookup_desc, (vop_t *) union_lookup },
- { &vop_mkdir_desc, (vop_t *) union_mkdir },
- { &vop_mknod_desc, (vop_t *) union_mknod },
- { &vop_open_desc, (vop_t *) union_open },
- { &vop_pathconf_desc, (vop_t *) union_pathconf },
- { &vop_poll_desc, (vop_t *) union_poll },
- { &vop_print_desc, (vop_t *) union_print },
- { &vop_read_desc, (vop_t *) union_read },
- { &vop_readdir_desc, (vop_t *) union_readdir },
- { &vop_readlink_desc, (vop_t *) union_readlink },
- { &vop_getwritemount_desc, (vop_t *) union_getwritemount },
- { &vop_reclaim_desc, (vop_t *) union_reclaim },
- { &vop_remove_desc, (vop_t *) union_remove },
- { &vop_rename_desc, (vop_t *) union_rename },
- { &vop_revoke_desc, (vop_t *) union_revoke },
- { &vop_rmdir_desc, (vop_t *) union_rmdir },
- { &vop_setattr_desc, (vop_t *) union_setattr },
- { &vop_strategy_desc, (vop_t *) union_strategy },
- { &vop_symlink_desc, (vop_t *) union_symlink },
- { &vop_unlock_desc, (vop_t *) union_unlock },
- { &vop_whiteout_desc, (vop_t *) union_whiteout },
- { &vop_write_desc, (vop_t *) union_write },
- { NULL, NULL }
-};
-static struct vnodeopv_desc union_vnodeop_opv_desc =
- { &union_vnodeop_p, union_vnodeop_entries };
-
-VNODEOP_SET(union_vnodeop_opv_desc);
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index eac6ea8..f93f393 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -7,12 +7,12 @@ _random= random
.endif
SUBDIR= 3dfx accf_data accf_http agp aha amr an aue \
- cam ccd cd9660 coda cue dc de dgm digi ed fdesc fxp if_disc if_ef \
+ cam ccd cd9660 coda cue dc de dgm digi ed fdescfs fxp if_disc if_ef \
if_ppp if_sl if_tap if_tun ip6fw ipfilter ipfw ispfw joy kue \
libmchain linux lnc md mfs mii mlx msdos ncp netgraph nfs nge ntfs \
- nullfs nwfs pcn portal procfs ${_random} \
+ nullfs nwfs pcn portalfs procfs ${_random} \
rl rp sf sis sk sn sound sppp ste sym syscons sysvipc ti tl twe tx \
- udbp ugen uhid ukbd ulpt umapfs umass umodem ums union urio usb \
+ udbp ugen uhid ukbd ulpt umapfs umass umodem ums unionfs urio usb \
uscanner \
vinum vpo vr vx wb wx xl
diff --git a/sys/modules/fdesc/Makefile b/sys/modules/fdesc/Makefile
deleted file mode 100644
index 4344517..0000000
--- a/sys/modules/fdesc/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../miscfs/fdesc
-
-KMOD= fdesc
-SRCS= vnode_if.h \
- fdesc_vfsops.c fdesc_vnops.c
-NOMAN=
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/fdescfs/Makefile b/sys/modules/fdescfs/Makefile
index 4344517..dc8b6db 100644
--- a/sys/modules/fdescfs/Makefile
+++ b/sys/modules/fdescfs/Makefile
@@ -1,8 +1,8 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../miscfs/fdesc
+.PATH: ${.CURDIR}/../../fs/fdescfs
-KMOD= fdesc
+KMOD= fdescfs
SRCS= vnode_if.h \
fdesc_vfsops.c fdesc_vnops.c
NOMAN=
diff --git a/sys/modules/nullfs/Makefile b/sys/modules/nullfs/Makefile
index 3df3d26..d41ac21 100644
--- a/sys/modules/nullfs/Makefile
+++ b/sys/modules/nullfs/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../miscfs/nullfs
+.PATH: ${.CURDIR}/../../fs/nullfs
KMOD= nullfs
SRCS= vnode_if.h \
diff --git a/sys/modules/portal/Makefile b/sys/modules/portal/Makefile
deleted file mode 100644
index a14a8fa..0000000
--- a/sys/modules/portal/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../miscfs/portal
-
-KMOD= portal
-SRCS= vnode_if.h \
- portal_vfsops.c portal_vnops.c
-NOMAN=
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/portalfs/Makefile b/sys/modules/portalfs/Makefile
index a14a8fa..f23e69e 100644
--- a/sys/modules/portalfs/Makefile
+++ b/sys/modules/portalfs/Makefile
@@ -1,8 +1,8 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../miscfs/portal
+.PATH: ${.CURDIR}/../../fs/portalfs
-KMOD= portal
+KMOD= portalfs
SRCS= vnode_if.h \
portal_vfsops.c portal_vnops.c
NOMAN=
diff --git a/sys/modules/procfs/Makefile b/sys/modules/procfs/Makefile
index d132b0d..3d9338e 100644
--- a/sys/modules/procfs/Makefile
+++ b/sys/modules/procfs/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../miscfs/procfs
+.PATH: ${.CURDIR}/../../fs/procfs
KMOD= procfs
SRCS= vnode_if.h \
diff --git a/sys/modules/umapfs/Makefile b/sys/modules/umapfs/Makefile
index 279a3a4..346f903 100644
--- a/sys/modules/umapfs/Makefile
+++ b/sys/modules/umapfs/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../miscfs/umapfs
+.PATH: ${.CURDIR}/../../fs/umapfs
KMOD= umap
SRCS= vnode_if.h \
diff --git a/sys/modules/union/Makefile b/sys/modules/union/Makefile
deleted file mode 100644
index 8f3f852..0000000
--- a/sys/modules/union/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../miscfs/union
-
-KMOD= union
-SRCS= vnode_if.h \
- union_subr.c union_vfsops.c union_vnops.c
-NOMAN=
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/unionfs/Makefile b/sys/modules/unionfs/Makefile
index 8f3f852..2f80909 100644
--- a/sys/modules/unionfs/Makefile
+++ b/sys/modules/unionfs/Makefile
@@ -1,8 +1,8 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../miscfs/union
+.PATH: ${.CURDIR}/../../fs/unionfs
-KMOD= union
+KMOD= unionfs
SRCS= vnode_if.h \
union_subr.c union_vfsops.c union_vnops.c
NOMAN=
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
index 61fb9e2..d37615a 100644
--- a/sys/nfs/nfs_vnops.c
+++ b/sys/nfs/nfs_vnops.c
@@ -66,7 +66,7 @@
#include <vm/vm.h>
#include <vm/vm_extern.h>
-#include <miscfs/fifofs/fifo.h>
+#include <fs/fifofs/fifo.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index 61fb9e2..d37615a 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -66,7 +66,7 @@
#include <vm/vm.h>
#include <vm/vm_extern.h>
-#include <miscfs/fifofs/fifo.h>
+#include <fs/fifofs/fifo.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
diff --git a/sys/powerpc/powerpc/procfs_machdep.c b/sys/powerpc/powerpc/procfs_machdep.c
index 06869b0..96fd0e5 100644
--- a/sys/powerpc/powerpc/procfs_machdep.c
+++ b/sys/powerpc/powerpc/procfs_machdep.c
@@ -75,7 +75,7 @@
#include <machine/md_var.h>
#include <machine/reg.h>
-#include <miscfs/procfs/procfs.h>
+#include <fs/procfs/procfs.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index eae3707..7afeca4 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -68,7 +68,7 @@
#include <vm/vm.h>
#include <vm/vm_extern.h>
-#include <miscfs/fifofs/fifo.h>
+#include <fs/fifofs/fifo.h>
#include <ufs/ufs/acl.h>
#include <ufs/ufs/extattr.h>
diff --git a/usr.sbin/mount_portalfs/Makefile b/usr.sbin/mount_portalfs/Makefile
index 00b96dc..fc332ee 100644
--- a/usr.sbin/mount_portalfs/Makefile
+++ b/usr.sbin/mount_portalfs/Makefile
@@ -7,7 +7,7 @@ SRCS= mount_portal.c activate.c conf.c getmntopts.c pt_conf.c \
MAN= mount_portal.8
MOUNT= ${.CURDIR}/../mount
-CFLAGS+= -I${.CURDIR}/../../sys -I${MOUNT}
+CFLAGS+=-I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>
diff --git a/usr.sbin/mount_portalfs/portald.h b/usr.sbin/mount_portalfs/portald.h
index 4131834..5837bd7 100644
--- a/usr.sbin/mount_portalfs/portald.h
+++ b/usr.sbin/mount_portalfs/portald.h
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-#include <miscfs/portal/portal.h>
+#include <fs/portalfs/portal.h>
/*
* Meta-chars in an RE. Paths in the config file containing
diff --git a/usr.sbin/pstat/Makefile b/usr.sbin/pstat/Makefile
index 72a86aa..b96e391 100644
--- a/usr.sbin/pstat/Makefile
+++ b/usr.sbin/pstat/Makefile
@@ -2,7 +2,6 @@
# $FreeBSD$
PROG= pstat
-CFLAGS+=-I${.CURDIR}/../../sys
BINGRP= kmem
BINMODE=2555
DPADD= ${LIBKVM}
diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c
index 7ac83fb..d8ddfbf 100644
--- a/usr.sbin/pstat/pstat.c
+++ b/usr.sbin/pstat/pstat.c
@@ -56,7 +56,7 @@ static const char rcsid[] =
#include <sys/mount.h>
#include <sys/uio.h>
#include <sys/namei.h>
-#include <miscfs/union/union.h>
+#include <fs/unionfs/union.h>
#undef _KERNEL
#include <sys/stat.h>
#include <nfs/rpcv2.h>
OpenPOWER on IntegriCloud